Skip to content

Latest commit

 

History

History
241 lines (180 loc) · 8.69 KB

File metadata and controls

241 lines (180 loc) · 8.69 KB

Architecture

repoverlay is a CLI tool that overlays config files into git repositories without committing them. It supports local overlays, GitHub repository overlays, and shared overlay repositories.

Module Structure

src/
├── main.rs         # CLI entry point (minimal - delegates to lib)
├── cli.rs          # CLI command definitions and argument parsing (clap)
├── lib.rs          # Core library with apply/remove/status/restore/update operations
├── state.rs        # State persistence (in-repo and external backup)
├── github.rs       # GitHub URL parsing and source resolution
├── cache.rs        # GitHub repository cache management
├── config.rs       # Global and per-repo configuration (CCL format)
├── sources.rs      # Multi-source overlay resolution with priority ordering
├── overlay_repo.rs # Shared overlay repository integration
├── upstream.rs     # Upstream repository detection for fork inheritance
├── library.rs      # In-repo overlay library management
├── detection.rs    # File discovery for overlay creation
├── selection.rs    # Interactive file selection UI
├── widgets/        # Reusable ratatui UI components
│   ├── mod.rs
│   └── multi_select_tree.rs  # Tree widget with tri-state checkboxes
└── testutil.rs     # Test utilities (create_test_repo, create_test_overlay)

tests/
├── cli.rs          # CLI integration tests using assert_cmd
└── common/mod.rs   # Shared test utilities and fixtures

Module Responsibilities

  • main.rs - Minimal CLI entry point. Initializes logging and delegates to lib::run().

  • cli.rs - CLI command definitions using clap derive macros. Defines all subcommands, arguments, and flags.

  • lib.rs - Core operations: apply_overlay, remove_overlay, show_status, restore_overlays, update_overlays, create_overlay, switch_overlay. Also handles git exclude file management.

  • selection.rs - Interactive file selection UI. Handles checkbox-style multi-select for overlay creation.

  • widgets/ - Reusable ratatui UI components.

    • multi_select_tree.rs - MultiSelectTree stateful widget: renders a tree with tri-state checkboxes (checked/unchecked/partial) based on descendant selection state.
  • state.rs - State persistence layer. Manages overlay state in two locations:

    • In-repo: .repoverlay/overlays/<name>.ccl - tracks applied overlays
    • External: ~/.local/share/repoverlay/applied/ - backup for recovery after git clean
  • github.rs - GitHub URL parsing. Handles URL formats like https://github.com/owner/repo/tree/branch/subpath and extracts owner, repo, ref, and subpath components.

  • cache.rs - GitHub repository caching. Manages cloned repos in ~/.cache/repoverlay/github/owner/repo/. Supports shallow clones and update checking.

  • config.rs - Configuration management using CCL format. Handles global config (~/.config/repoverlay/config.ccl) and per-overlay config (repoverlay.ccl).

  • sources.rs - Multi-source overlay resolution. Manages a priority-ordered list of overlay sources (configured via repoverlay source add/remove/list). Provides SourceManager for resolving overlay references across multiple sources with first-match-wins semantics.

  • overlay_repo.rs - Shared overlay repository support. Allows overlays to be referenced as org/repo/name from a centrally managed repository. Supports fallback resolution for fork inheritance.

  • upstream.rs - Upstream repository detection. Scans git remotes to identify parent repositories (forks), enabling automatic overlay inheritance from upstream.

  • library.rs - In-repo overlay library management. Handles the .repoverlay/library/ directory for storing shareable overlays within a repository. Provides path resolution (configurable via per-repo config), overlay listing, import/export/remove operations, and gitignore detection. Library overlays are auto-discovered and resolved with highest priority.

  • detection.rs - File discovery for the create command. Identifies AI configs, gitignored files, and untracked files that might be candidates for overlay creation.

  • testutil.rs - Test utilities including create_test_repo() and create_test_overlay() helpers for setting up temporary git repositories in tests.

Data Flow

Apply

Source string → resolve_source() → local path
    ↓
Walk files in overlay directory
    ↓
For each file:
    - Check for conflicts with existing overlays
    - Check for conflicts with existing files
    - Create symlink or copy
    ↓
Update .git/info/exclude with overlay section
    ↓
Save state to .repoverlay/overlays/<name>.ccl
    ↓
Save external backup to ~/.local/share/repoverlay/applied/

Remove

Load state from .repoverlay/overlays/<name>.ccl
    ↓
For each file entry:
    - Remove file/symlink
    - Clean empty parent directories
    ↓
Remove overlay section from .git/info/exclude
    ↓
Delete state file
    ↓
Remove external backup

Restore

Load external state backup from ~/.local/share/repoverlay/applied/
    ↓
For each saved overlay:
    - Re-apply using original source (path or GitHub URL)

Update

For each applied GitHub overlay:
    - Check remote for new commits
    - If updates available:
        - Remove old overlay
        - Re-apply with updated cache

Create

Discover files in repository (AI configs, gitignored, untracked)
    ↓
Interactive selection or --include flags
    ↓
Copy selected files to output directory
    ↓
Generate repoverlay.ccl config

Switch

Remove all existing overlays
    ↓
Apply new overlay (atomic replacement)

State File Format

Overlay state is stored in CCL format (a human-readable configuration language). Example:

name = my-overlay
applied_at = 2024-01-15T10:30:00Z
source = local|/path/to/overlay
files =
  source = .envrc
  target = .envrc
  link_type = symlink

Source types are encoded as pipe-delimited strings:

  • Local: local|/path/to/overlay
  • Library: library|name (in-repo .repoverlay/library/ overlay)
  • GitHub: github|url|owner|repo|ref|commit|subpath|cached_at
  • Overlay repo: overlay_repo|org|repo|name|commit

Git Integration

Overlay files are excluded from git tracking via .git/info/exclude using named sections:

# repoverlay:my-overlay start
.envrc
.claude/
# repoverlay:my-overlay end

This approach:

  • Keeps overlay files out of version control
  • Doesn't modify .gitignore (which is tracked)
  • Allows multiple overlays with distinct sections
  • Enables clean removal of individual overlays

Source Resolution

The resolve_source() function determines the overlay source type:

  1. GitHub URL (https://github.com/...) - Downloads to cache, returns cached path
  2. Local path (./path or /path) - Returns path directly after validation
  3. Library overlay (bare name) - Checks .repoverlay/library/ first (highest priority)
  4. Overlay repo reference (org/repo/name) - Resolves from configured shared repository

Fork Inheritance

When applying overlays from a shared repository to a forked repo, repoverlay automatically inherits overlays from the upstream (parent) repository.

Resolution Order

  1. Direct match - Look for fork-org/fork-repo/overlay-name
  2. Upstream fallback - If not found and upstream exists, look for upstream-org/upstream-repo/overlay-name

Upstream Detection

The upstream repository is detected by scanning git remotes:

  1. Check for a remote named upstream (standard fork convention)
  2. Parse the remote URL (supports both HTTPS and SSH formats)
  3. Extract org/repo for fallback resolution

Example:

# Fork setup
git remote -v
# origin    git@github.com:tylerbutler/FluidFramework.git (fetch)
# upstream  git@github.com:microsoft/FluidFramework.git (fetch)

# Apply overlay - will fallback to microsoft/FluidFramework if needed
repoverlay apply microsoft/FluidFramework/claude-config

State Tracking

The ResolvedVia enum tracks how an overlay was resolved:

  • Direct - Exact match in overlay repository
  • Upstream - Resolved via upstream fallback

This is stored in the overlay state and displayed in repoverlay status:

Overlay: claude-config
  Source:  microsoft/FluidFramework/claude-config (via upstream) (overlay repo)
  Commit:  abc123def456

Caching Strategy

GitHub repositories are cached in ~/.cache/repoverlay/github/owner/repo/:

  • Uses shallow clones to minimize disk usage
  • Caches are updated on repoverlay update or when --ref changes
  • Cache metadata tracks commit hash and last update time
  • repoverlay cache subcommands manage the cache

Decisions

See docs/adr/ for architectural decision records.