# Architecture

## Overview

RSMultiGit follows a simple pipeline: **discover projects** → **run command** → **collect results**.

## Module structure

```
src/
  main.rs              Entry point, CLI dispatch
  cli.rs               Clap derive definitions (Cli + Commands)
  config.rs            AppConfig runtime struct
  discovery.rs         Project discovery via glob or folder list
  runner.rs            Three execution patterns
  subprocess_utils.rs  Shell command helpers
  commands/
    mod.rs             Module declarations
    count.rs           git2-based repo inspection (dirty, untracked, synchronized)
    status.rs          git status / diff via subprocess
    branch.rs          Branch listing (local, remote, github)
    pull.rs            git pull
    clean.rs           git clean -ffxd
    diff.rs            git diff
    grep.rs            git grep with project-name prefix
    build.rs           Build commands (make, pydmt, rsconstruct, bootstrap)
```

## Runner patterns

All subcommands use one of three runner functions:

### `do_count`

For count commands (`count-dirty`, `untracked`, `synchronized`). Calls a test function on each project path (using libgit2, no subprocess), counts matches, optionally prints statistics.

### `do_for_all_projects`

For action commands (`pull`, `clean-hard`, `diff`, `grep`, `branch-*`, `build-*`). Changes into each project directory, runs the action, prints a header. Respects `--no-stop` for error handling.

### `print_if_data`

For status commands (`status`, `dirty`, `list-repos`). Changes into each project directory, calls a data function. If it returns `Some(text)`, prints the project name and data. If `None`, the project is silently skipped.

## Git inspection

The count commands (`count-dirty`, `untracked`, `synchronized`) use the `git2` crate for direct repository inspection. This avoids forking `git` subprocesses and is significantly faster for large numbers of repos.

All other git operations use `std::process::Command` to run the `git` CLI, which provides familiar output formatting and handles edge cases that libgit2 may not cover.

## Error handling

All functions return `anyhow::Result`. The `--no-stop` flag controls whether errors in individual projects are fatal (default) or logged and skipped.

## Build script

The `build.rs` script embeds git metadata (commit SHA, branch, dirty status, describe) and the Rust compiler version at compile time. These are accessible via `env!()` macros and displayed by `rsmultigit version`.
