diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 130e25f..1683bbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,29 +7,49 @@ env: CARGO_TERM_COLOR: always jobs: - ci: - name: CI (${{ matrix.os }}) - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - + fmt: + name: Format + runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: - components: clippy, rustfmt - - - uses: Swatinem/rust-cache@v2 + components: rustfmt - name: Check formatting run: cargo fmt -- --check + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - uses: Swatinem/rust-cache@v2 + - name: Lint run: cargo clippy -- -D warnings + test: + name: Test (${{ matrix.os }}) + needs: [fmt, lint] + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - uses: actions/checkout@v6 + + - uses: dtolnay/rust-toolchain@stable + + - uses: Swatinem/rust-cache@v2 + - name: Test run: cargo test diff --git a/src/commands.rs b/src/commands.rs index bab2a24..26fd784 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -14,14 +14,12 @@ pub fn cmd_install( ) -> Result<()> { let providers = providers.unwrap_or_else(|| AgentProvider::ALL.to_vec()); - // Resolve the source: either a remote git URL or a local path let (manifest_dir, mut loaded) = if git::is_git_url(&source) { resolve_remote_source(&source)? } else { resolve_local_source(&source)? }; - // Apply strategy override to all files that use the default if let Some(strategy) = strategy_override { for file in &mut loaded.files { if file.strategy == FileStrategy::Copy { @@ -78,7 +76,6 @@ fn resolve_remote_source(source: &str) -> Result<(PathBuf, manifest::Manifest)> println!("Cached at: {}\n", local_path.display()); - // Try to load a manifest; fall back to scanning let manifest_path = local_path.join("agentfiles.json"); let loaded = if manifest_path.is_file() { println!("Found agentfiles.json in remote repository."); @@ -94,7 +91,6 @@ fn resolve_remote_source(source: &str) -> Result<(PathBuf, manifest::Manifest)> } println!("Discovered {} agent file(s) via scan.\n", files.len()); - // Build a synthetic manifest from scanned files let name = remote .url .rsplit('/') @@ -145,7 +141,6 @@ pub fn cmd_init(path: PathBuf, name: Option) -> Result<()> { ); } - // Try to scan for existing files let files = scanner::scan_agent_files(&dir).unwrap_or_default(); let pkg_name = name.unwrap_or_else(|| scanner::infer_name(&dir)); diff --git a/src/git.rs b/src/git.rs index d05efc4..2d0104c 100644 --- a/src/git.rs +++ b/src/git.rs @@ -136,10 +136,6 @@ pub fn get_cache_dir(url: &str) -> Result { Ok(base.join("agentfiles").join(hash)) } -// --------------------------------------------------------------------------- -// Internal helpers -// --------------------------------------------------------------------------- - /// Split a ref suffix from the input. /// /// The ref delimiter is `@` but only when it appears after a `/` character, @@ -298,11 +294,9 @@ fn reset_to_default_branch(repo_dir: &Path) -> Result<()> { .context("failed to determine default branch")?; let default_branch = if output.status.success() { - // Output is like "origin/main" — take just the branch name let full = String::from_utf8_lossy(&output.stdout).trim().to_string(); full.strip_prefix("origin/").unwrap_or(&full).to_string() } else { - // Fallback: try common default branch names "main".to_string() }; diff --git a/src/installer.rs b/src/installer.rs index 1bf0db0..9ab3505 100644 --- a/src/installer.rs +++ b/src/installer.rs @@ -49,11 +49,8 @@ pub fn install( } let target_dir = provider.get_target_dir(scope, &file.kind, project_root)?; - - // Determine the target filename/path let target_path = resolve_target_path(&file.path, &target_dir)?; - // Ensure parent directories exist if let Some(parent) = target_path.parent() { fs::create_dir_all(parent) .with_context(|| format!("failed to create directory: {}", parent.display()))?; @@ -75,7 +72,6 @@ pub fn install( } } FileStrategy::Link => { - // Remove existing target if present if target_path.exists() || target_path.is_symlink() { if target_path.is_dir() && !target_path.is_symlink() { fs::remove_dir_all(&target_path)?; @@ -143,22 +139,17 @@ pub fn install( /// For commands/agents (single .md files), we place the file directly /// (e.g., `deploy.md` -> `/deploy.md`). fn resolve_target_path(relative_path: &Path, target_dir: &Path) -> Result { - // Extract the meaningful part of the path. - // If it's a SKILL.md inside a named directory, keep `/SKILL.md`. - // If it's a command/agent .md file, keep just the filename. let file_name = relative_path .file_name() .context("file path has no filename")?; if file_name == "SKILL.md" { - // Skill: keep parent_dir_name/SKILL.md let parent_name = relative_path .parent() .and_then(|p| p.file_name()) .context("SKILL.md must be inside a named directory")?; Ok(target_dir.join(parent_name).join("SKILL.md")) } else { - // Command or Agent: just the filename Ok(target_dir.join(file_name)) } }