Skip to content

feat: add remote repository command#5

Merged
atrtde merged 9 commits intomainfrom
staging
Feb 9, 2026
Merged

feat: add remote repository command#5
atrtde merged 9 commits intomainfrom
staging

Conversation

@atrtde
Copy link
Copy Markdown
Owner

@atrtde atrtde commented Feb 9, 2026

Summary by CodeRabbit

  • New Features

    • Remote repository support with --repo, --repo-branch, and --repo-commit CLI options
    • Repository cloning and processing in temporary directories
  • Changed

    • Typed error handling system
    • Shallow cloning behavior when using --repo-commit
    • Documentation updated with remote repository usage examples
  • Fixed

    • CLI prevents conflicting use of --repo and --dir
  • Tests

    • Added repository integration tests for clone, cleanup, and commit checkout

@atrtde atrtde self-assigned this Feb 9, 2026
Copilot AI review requested due to automatic review settings February 9, 2026 15:02
@atrtde atrtde merged commit 8f51d94 into main Feb 9, 2026
11 of 12 checks passed
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 9, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This pull request introduces remote repository support to the application, adding new CLI options (--repo, --repo-branch, --repo-commit) to clone and process Git repositories. It establishes a new error handling system via typed AppError variants and AppResult, refactors existing functions to propagate structured errors, adds a repository management module for Git operations with temporary directory handling, extends test coverage with repository integration tests, and updates documentation and dependencies accordingly.

Changes

Cohort / File(s) Summary
Documentation
CHANGELOG.md, README.md
Added 1.7.0 release notes documenting new repository CLI options, remote processing capabilities, typed error handling migration, and usage examples. Updated README with new CLI flags, subcommands section, and remote repository usage patterns.
Error Handling Infrastructure
src/error.rs
Introduced new AppError enum with variants for I/O, clipboard, YAML parse, missing inputs, size validation, config conflicts, and Git operations. Added AppResult<T> type alias and automatic conversion from io::Error.
Error Propagation
src/config.rs, src/clipboard.rs, src/cli.rs
Updated function signatures to return AppResult instead of io::Result. Refactored error handling to map I/O and validation errors into structured AppError variants. CLI extended with three new mutually-exclusive repository arguments.
Core Module & Integration
src/main.rs, src/repository.rs
Updated main entry points to return AppResult. Added repository module providing clone_repository (with optional branch/commit checkout) and run_on_repository orchestration. Integrated repository cloning into main control flow when --repo is provided. Added clipboard error suppression for CI/headless environments.
Dependency Management
Cargo.toml
Promoted tempfile from dev-dependencies to runtime dependencies and added thiserror as a new dependency to support structured error handling.
Test Coverage
src/tests/cli_tests.rs, src/tests/clipboard_tests.rs, src/tests/config_tests.rs, src/tests/main_tests.rs, src/tests/mod.rs, src/tests/repository_tests.rs
Updated existing tests to assert on AppError variants instead of io::ErrorKind. Added comprehensive repository integration tests covering clone operations, commit checkout, temporary directory cleanup, and remote repository processing.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as CLI Handler
    participant Main as main()
    participant Repo as repository::run_on_repository()
    participant Git as Git Command
    participant TempDir as Temp Directory
    participant Config as run_with_config()
    
    User->>CLI: Provide --repo URL, --repo-branch, output path
    CLI->>Main: Pass parsed arguments
    Main->>Repo: Call run_on_repository(url, branch, config)
    Repo->>Git: Execute git clone [--branch] --depth 1
    Git->>TempDir: Create repository copy
    TempDir->>Repo: Return TempDir handle & path
    Repo->>Config: Update config.directory to cloned path
    Repo->>Config: Call run_with_config(updated_config)
    Config->>Config: Process files in cloned repository
    Config->>User: Write results to output file
    Repo->>TempDir: Drop TempDir (cleanup)
    TempDir->>User: Cleanup complete, return success
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit hops through git-cloned repos so fine,
Temp dirs dance before they fade away in time,
Typed errors catch the mistakes with flair,
Remote branches checked with utmost care,
New features bloom—the warren's code runs fair! 🌿

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch staging

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for processing a remote git repository by cloning it into a temporary directory, running the existing file-combine flow on the clone, and cleaning up afterward. This also introduces a typed AppError error model and updates tests/docs to match.

Changes:

  • Add --repo (+ optional --repo-branch / --repo-commit) and implement clone+run workflow via new repository module.
  • Introduce AppError / AppResult (via thiserror) and migrate clipboard/config/init flows + tests to structured errors.
  • Add README + changelog updates and repository integration tests.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/repository.rs Implements git clone + optional checkout into TempDir, then runs processing on the clone
src/cli.rs Adds --repo, --repo-branch, --repo-commit CLI flags
src/main.rs Routes execution through repository flow when --repo is provided; adds typed error handling + clipboard fallback behavior
src/error.rs Defines AppError / AppResult
src/config.rs Switches config parsing + YAML parse errors to AppError
src/clipboard.rs Converts clipboard errors into AppError
src/tests/repository_tests.rs Adds tests for remote-repo processing, commit checkout, and temp cleanup
src/tests/*.rs, src/tests/mod.rs Updates tests to match typed errors and registers new test module
README.md Documents remote repo usage + subcommands
CHANGELOG.md Adds release notes for the feature
Cargo.toml / Cargo.lock Adds thiserror and promotes tempfile to non-dev dependency
Comments suppressed due to low confidence (1)

src/config.rs:140

  • ExplicitFlags is intended to track which CLI values were explicitly provided vs clap defaults, but *_set is computed via try_get_one, which will be Some even when values come from default_value (e.g., directory/output). This causes config-file values for directory/output to never take effect. Use ArgMatches::value_source (or similar) to detect ValueSource::CommandLine instead of presence.
pub fn config_from_matches(matches: clap::ArgMatches) -> AppResult<(Config, ExplicitFlags)> {
    let directory_set = match matches.try_get_one::<String>("directory") {
        Ok(Some(_)) => true,
        Ok(None) => false,
        Err(_) => false,
    };
    let output_set = match matches.try_get_one::<String>("output") {
        Ok(Some(_)) => true,
        Ok(None) => false,
        Err(_) => false,
    };

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/repository.rs
let output = Command::new("git")
.arg("-C")
.arg(&clone_path)
.args(["checkout", commit])
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git checkout is invoked with the user-provided commit as a raw argument. If the commit string starts with -, git can parse it as an option (option injection). Validate commit (and potentially branch) to reject leading -, or use a safer invocation pattern that prevents option parsing.

Suggested change
.args(["checkout", commit])
.arg("checkout")
.arg("--")
.arg(commit)

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +17
fn init_sample_repo() -> TempDir {
let repo_dir = TempDir::new().expect("create temp repo");

let status = Command::new("git")
.args(["init", "."])
.current_dir(repo_dir.path())
.status()
.expect("init git repo");
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests assume the git executable is available on the test runner; if it isn't, they will fail with expect("init git repo"). Consider adding a quick git --version probe at the start and early-return/skip when git isn't installed to keep the suite portable.

Copilot uses AI. Check for mistakes.
Comment thread Cargo.toml
serde_yaml = "0.9.34"
walkdir = "2.5.0"
tempfile = "3.19.1"
thiserror = "1.0"
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a direct dependency on thiserror = "1.0" introduces a second thiserror major version alongside an existing transitive thiserror 2.x (see Cargo.lock), increasing compile time and binary size. Prefer aligning to the already-used major version (if MSRV allows) or otherwise pin/justify the dual-version situation.

Suggested change
thiserror = "1.0"
thiserror = "2"

Copilot uses AI. Check for mistakes.
Comment thread src/cli.rs
Arg::new("repo")
.long("repo")
.value_name("URL")
.help("Clone a git repository (GitHub/GitLab) into a temporary directory before processing").conflicts_with("directory"),
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--repo is declared as conflicts_with("directory"), but directory has a default_value("."). With clap defaults treated as present, this makes --repo conflict even when the user did not pass --dir, effectively breaking the remote-repo feature. Consider removing the default on directory (set it in code when --repo is absent) or using clap value-source/conditional defaults so the conflict only triggers when --dir is explicitly provided.

Suggested change
.help("Clone a git repository (GitHub/GitLab) into a temporary directory before processing").conflicts_with("directory"),
.help("Clone a git repository (GitHub/GitLab) into a temporary directory before processing"),

Copilot uses AI. Check for mistakes.
Comment thread src/repository.rs
if let Some(branch) = branch {
cmd.args(["--branch", branch]);
}
cmd.arg(repo_url).arg(&clone_path);
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repo_url is passed to git clone without an end-of-options delimiter. A malicious or accidental value starting with - can be interpreted as extra git clone flags (option injection). Add -- before the URL (if supported) and/or validate repo_url to reject values starting with -.

Suggested change
cmd.arg(repo_url).arg(&clone_path);
cmd.arg("--").arg(repo_url).arg(&clone_path);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants