Commit graph

35 commits

Author SHA1 Message Date
7ff9086215
docs: add AGENTS.md file 2026-02-11 03:49:08 +00:00
f4a498e28e
show fingerprint instead of bare GPG fallback for gpg signatures 2026-02-10 21:56:01 +00:00
686190a4fc
fix: GPG signed commit test fails in nix build
The test hardcoded 'refs/heads/main' for update-ref, but without
init.defaultBranch config (as in nix sandbox), git defaults to 'master'.
This caused the signed commit to be on a different branch than HEAD,
so arc log showed the unsigned commit instead.

Use 'git symbolic-ref HEAD' to get the actual branch name.
Also fix missing blank line separator between header and body.
2026-02-10 21:53:31 +00:00
dd5b3f0b06
add backwards compat for gpg signed commits
Detect GPG vs SSH signatures when displaying commits. GPG-signed
commits from cloned/migrated git repos now show as valid with the
issuer key ID instead of failing SSH signature verification.
2026-02-10 21:37:52 +00:00
f73878c555
feat: preserve commit signatures across git bridge operations
- Extract git commit signatures (gpgsig) during clone, migrate, and pull
- Sign git commits on push/sync when a signing key is configured
- Add tests for signature preservation and signed push
2026-02-10 21:24:12 +00:00
6f307c139b
feat: add backwards compatibility for legacy msgpack storage format 2026-02-10 21:09:58 +00:00
a6b1a027c8
refactor: switch storage format from MessagePack to bincode
- Replace rmp-serde with bincode 1.x in Cargo.toml
- Update store.rs serialization/deserialization and ID hashing
- Rename model.rs helpers from to_msgpack/from_msgpack to to_bytes/from_bytes
- Consolidate MsgPack/MsgPackDecode error variants into single Bincode variant
- Remove skip_serializing_if on ssh_signature (incompatible with bincode)
- Update all documentation to reflect bincode storage format
2026-02-10 21:03:53 +00:00
adcdaa20c6
feat: add corruption prevention and integrity checking
- Add read-time validation of commit objects in store.rs (verify
  delta IDs, commit IDs, parent references)
- Enable zstd frame checksums on write
- Add directory fsync after atomic renames for durability
- Validate delta chain consistency in materialize_committed_tree
- Reject unsupported Patch delta variants in apply_delta
- Defer ref updates in graft to avoid dangling references
- Add 'arc check' command (fsck) with orphan detection
- Add CorruptObject and UnsupportedDelta error variants
2026-02-10 21:03:22 +00:00
d03ae3c2c3
fix: implement range-based diff 2026-02-10 00:36:22 +00:00
86a49961ad
docs: add project documentation 2026-02-10 00:00:27 +00:00
0bc174e341
chore: add license file 2026-02-09 23:58:40 +00:00
d8710a79c9
docs: add README.md 2026-02-09 23:57:36 +00:00
a70f7eb2cb
fix: missing newlines in status, tag list, and mark list output 2026-02-09 18:05:00 +00:00
d4cd32454e
fix migrate reporting wrong commit count
The imported counter was incrementing once per ref processed, not once
per commit converted. Since git_to_arc recursively walks the entire
ancestor chain, a single ref import would convert all reachable commits
but only count as 1.

Fix by measuring the growth of the git-to-arc map before and after the
import loop. Also strengthen tests to assert exact counts for commits,
bookmarks, and tags.
2026-02-09 17:58:03 +00:00
5d95b093c8
support multi-level verbosity (-v, -vv, -vvv)
Replace the boolean verbose flag with a u8 counter using
clap's ArgAction::Count. The debug! macro now accepts an
optional level as its first argument.

Level 1 (-v):  command dispatch, high-level operations
Level 2 (-vv): internal ops (scanning, resolving, merging)
Level 3 (-vvv): low-level I/O (commit objects, hashing, trees)
2026-02-09 17:51:16 +00:00
7d5157d526
add top-level --verbose flag with debug output across all commands and internal components 2026-02-09 17:41:17 +00:00
07b46e46eb
fix ssh auth: add retry limit and key file fallback
the credential callback had no attempt counter, causing libgit2 to
retry indefinitely when ssh-agent auth failed (hanging on clone).
it also had no fallback to key files on disk, failing when the agent
wasn't running.

replace the stateless cred_callback with make_cred_callback() which
caps retries at 4, tries ssh-agent first then falls back to reading
~/.ssh/id_ed25519, id_rsa, id_ecdsa directly, and returns an error
instead of sending empty credentials for plaintext auth.
2026-02-09 17:32:31 +00:00
2e0952f9fb
feat: add colored output with distinct symbols using the colored crate
Add a centralized ui module with Arc's visual identity: colored commit
IDs (magenta), bookmarks (cyan), tags (yellow), status symbols, and
diff highlighting. Update all command output and tests accordingly.
2026-02-09 03:51:59 +00:00
0e1cc7ff89
bridge: fix SSH auth for clone, clean up directory on failure
Extract shared cred_callback for SSH agent authentication and use it
in clone, push, and pull. Wrap clone in an outer function that removes
the target directory if it was freshly created and cloning fails.
2026-02-09 03:39:07 +00:00
7fe99cabbd
feat: optional SSH key commit signing (phase 10)
- Add ssh-key crate dependency for SSHSIG format signing/verification
- Add signing module with sign, verify, and fingerprint functions
- Add ssh_signature field to Commit model (optional, backward-compatible)
- Integrate signing into commit flow (signs when user.key is configured)
- Show [signed] tag in log output for signed commits
- Show signature fingerprint and verification status in show output
- Gracefully degrade if key is missing/invalid (warns, commits unsigned)
- Add openssh to nix flake nativeCheckInputs for ssh-keygen in tests
- Add comprehensive signing tests covering signed/unsigned commits
2026-02-08 16:34:05 +00:00
d7694737de
feat: implement phase 9 - git bridge and remotes
- Add git2 dependency with vendored libgit2/openssl for nix compatibility
- Add src/remote.rs: remote add/rm/list with YAML persistence (.arc/remotes.yml)
- Add src/bridge.rs: git bridge with shadow repo (.arc/git/) and commit mapping
  - arc-to-git conversion: materialize trees, create git commits via TreeBuilder
  - git-to-arc conversion: walk git trees, compute deltas, create arc commits
  - Bidirectional mapping cache in .arc/git-map.yml
- Implement push: convert arc commits to git, push bookmarks as branches and
  tags as git tags (rules 19/20) via git2 with SSH agent support
- Implement pull: fetch from remote, import new commits, fast-forward bookmarks
- Implement clone: git2 clone into shadow repo, import all history, set up
  worktree at specified branch with origin remote auto-configured
- Implement migrate: convert existing git repo to arc, preserving all branches
  as bookmarks, tags, commit history, and git remotes
- Implement sync: ensure shadow git mirrors arc refs, optionally push to remote
- Wire all CLI stubs (push/pull/clone/migrate/sync/remote) to implementations
- Add new error variants: Git, RemoteNotFound, RemoteAlreadyExists, etc.
- Exclude .git/ from worktree scanning alongside .arc/ for coexistence
- Update flake.nix with cmake/perl/git build inputs for vendored compilation
- Add 23 new integration tests (16 bridge + 7 remote) covering all commands
2026-02-08 02:53:12 +00:00
0e9c810a41
feat: implement config system with set/get/show/unset and alias expansion
- config set/get/show/unset commands with dotted key paths (user.name, default.bookmark, aliases.c, etc.)
- local config overrides global config per rule 21
- alias expansion at CLI level before dispatch per rule 23
- InvalidConfigKey error variant
- 28 tests covering all config operations, global/local resolution, and alias expansion
2026-02-08 02:34:48 +00:00
ea07d74457
feat: implement stash system (phase 7)
Add named stash support with create, use, push, pop, rm, and list
commands. Stashes are stored as YAML in .arc/stashes/named/ with a
stack-based push/pop model. Active stash tracked in state.yml.

- stash push saves dirty changes and resets worktree to clean state
- stash pop requires clean worktree and matching HEAD base commit
- 28 integration tests covering all commands and edge cases
- new error variants: StashAlreadyExists, StashNotFound, NoActiveStash,
  NothingToStash, StashEmpty, StashBaseMismatch
2026-02-07 16:48:54 +00:00
8fec7a170a
fix: path traversal vulnerabilities, remove production panics, deduplicate code, fix idioms
Security:
- validate ref names before all bookmark/tag filesystem operations
- validate repo paths before worktree joins in clean/write/reset

Panics removed:
- system clock .expect() -> ArcError::ClockError
- hash serialization .expect() -> ArcError::HashError (fallible return)
- .unwrap() in resolve/merge replaced with proper error handling

DRY:
- extract load_effective_config -> config::load_effective
- extract update_refs_after_commit -> refs::update_refs_after_commit

Idioms:
- remove dead let _ = suppressions in merge.rs
- remove unused _worktree param from diff::render_diff
- &PathBuf -> &Path in config.rs
2026-02-07 16:26:06 +00:00
b52b2b709b
feat: implement phase 6 - revert, reset, merge, and graft commands
- Add reset command to discard worktree changes (all or specific files)
- Add revert command to create inverse commits (preserving immutability)
- Add merge command with three-way merge and conflict detection
- Add graft command to cherry-pick commits onto bookmarks
- Create merge.rs with file-level and line-level three-way merge engine
- Create modify.rs orchestrating undo/modification operations
- Add MergeConflicts and NoMergeBase error variants
- Make refs utility functions (write_tree, clean_tracked_files) public
- Make inspect::myers_diff public for reuse in merge engine
- Add comprehensive tests for all four commands
2026-02-07 16:07:45 +00:00
d8cce41809
fix: add path validation helpers to prevent path traversal
Add validate_ref_name() to reject ref names with separators, .., or
leading dots. Add validate_repo_path() to reject absolute paths and
parent-directory traversal in repo-relative paths.
2026-02-06 23:27:45 +00:00
acd6ad919d
refactor: add new error variants and Display/AsRef impls for newtypes
Add InvalidRefName, ClockError, and HashError variants to ArcError.
Implement Display and AsRef<str> for CommitId and DeltaId.
2026-02-06 23:27:30 +00:00
8a2a189576
feat: implement bookmarks, tags, and switch (phase 5)
- Add src/refs.rs with mark_add/rm/list/rename, tag_add/rm/list, switch
- Bookmarks stored as YAML RefTarget files in .arc/bookmarks/
- Tags stored as YAML RefTarget files in .arc/tags/ (immutable)
- Switch reconstructs worktree from delta chain, checks for dirty state
- Add error variants: BookmarkNotFound, BookmarkAlreadyExists, TagNotFound,
  TagAlreadyExists, CannotRemoveActiveMark, DirtyWorktree
- Wire up CLI dispatch for mark, tag, and switch commands
- Fix cli.rs tests to run mark/tag list within a repo context
- Add 35 new tests across tests/mark.rs, tests/tag.rs, tests/switch.rs
2026-02-06 18:31:31 +00:00
4d3c87674b
feat: implement phase 4 - log, show, history commands
- arc log: shows commit history newest-first with optional range support
- arc show: displays commit details by bookmark/tag/commit-id/prefix
- arc history: blame-style line attribution using Myers diff algorithm
- New resolve module for target resolution (bookmark → tag → commit prefix)
- New inspect module with timestamp formatting (no extra deps)
- Tests for all three commands (17 new tests, 82 total)
2026-02-06 18:24:07 +00:00
1433c2fed6
feat: implement phase 3 - tracking, committing, status, and diff
- Add commit command with auto-change detection (no staging area)
- Add status command showing added/modified/deleted files
- Add diff command with unified diff output
- Store commits as ZSTD-compressed MessagePack in .arc/commits/<id>.zst
- Generate commit/delta IDs via SHA-256 hashing
- Reconstruct committed state by replaying delta chains
- Add ignore pattern matching with glob support (.arcignore/.ignore)
- Always exclude .arc/ directory from worktree scanning
- Update HEAD and bookmark refs on commit
- Add NothingToCommit error variant
- Add zstd, sha2, hex dependencies
- Add 30 new tests across commit, status, diff, and tracking
2026-02-06 18:16:42 +00:00
5792e0b520
chore: add .arc directory to gitignore 2026-02-06 18:07:35 +00:00
dca6a9ae76
feat: implement phase 2 core repo structure
- Add Repository struct with init/open/discover methods
- Create .arc/ directory layout: commits/, bookmarks/, tags/, stashes/, HEAD, config.yml
- Define data model types: Commit, Delta, FileChange, Head, RefTarget with serde derives
- Implement YAML config with local/global resolution and EffectiveConfig merging
- Implement .arcignore/.ignore file parsing
- Add error module with ArcError type
- Wire arc init command to create real repository structure
- Add serde, serde_yaml, rmp-serde dependencies; tempfile dev-dependency
- Add 16 new integration tests across init, config, ignore, and model test files
2026-02-06 18:06:13 +00:00
a9615b9d78
docs: update spec formatting 2026-02-06 17:58:28 +00:00
c2eb9f42ba
feat: project scaffolding with nix flake, direnv, and CLI skeleton
- Nix flake with nixpkgs-unstable, flake-parts, fenix, and crane
- .envrc for direnv integration
- Rust project with clap-based CLI covering all planned commands
- Subcommands: init, commit, log, status, diff, switch, merge, show,
  history, revert, reset, push, pull, clone, migrate, mark, tag,
  stash, graft, config, sync, remote
- Integration tests for CLI help, version, and subcommand parsing
- All commands print placeholder output for future implementation
2026-02-06 17:55:42 +00:00
1fc7fa8ede
feat: create implementation spec 2026-02-06 17:50:03 +00:00