mod clean;
mod common;
mod sync;
use anyhow::Result;
use clap::{Parser, Subcommand};
#[derive(Parser)]
pub struct SkillsCommand {
#[command(subcommand)]
pub command: SkillsSubcommands,
}
#[derive(Subcommand)]
pub enum SkillsSubcommands {
Sync(sync::SyncCommand),
Clean(clean::CleanCommand),
}
impl SkillsCommand {
pub fn execute(self) -> Result<()> {
match self.command {
SkillsSubcommands::Sync(cmd) => cmd.execute(),
SkillsSubcommands::Clean(cmd) => cmd.execute(),
}
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod tests {
use super::*;
use std::fs;
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
fn tempdir() -> TempDir {
fs::create_dir_all("tmp").ok();
TempDir::new_in("tmp").unwrap()
}
fn init_repo(dir: &Path) {
let status = Command::new("git").arg("init").arg(dir).output().unwrap();
assert!(status.status.success());
}
#[test]
fn dispatch_sync() {
let src = tempdir();
let tgt = tempdir();
init_repo(src.path());
init_repo(tgt.path());
let skills_dir = src.path().join(".claude/skills/alpha");
fs::create_dir_all(&skills_dir).unwrap();
fs::write(skills_dir.join("SKILL.md"), "# alpha").unwrap();
let cmd = SkillsCommand {
command: SkillsSubcommands::Sync(sync::SyncCommand {
source: Some(src.path().to_path_buf()),
target: Some(tgt.path().to_path_buf()),
worktrees: false,
dry_run: false,
}),
};
cmd.execute().unwrap();
assert!(tgt.path().join(".claude/skills/alpha").exists());
}
#[test]
fn dispatch_clean() {
let tgt = tempdir();
init_repo(tgt.path());
let cmd = SkillsCommand {
command: SkillsSubcommands::Clean(clean::CleanCommand {
target: Some(tgt.path().to_path_buf()),
worktrees: false,
dry_run: false,
}),
};
cmd.execute().unwrap();
}
}