dircue identify: match a directory against commits of local repositories

Aperta
#109 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
git, go
Ambito
backend, cli

Direzione di ricerca

Start with the pkg/treehash/hasher from #101 and the repository-reading pattern in pkg/scanner/git.go, then review the proposed pkg/identify/identify_test.go and tests/identify/ fixtures. The scope includes CLI wiring, bounded commit walking, subtree and nearest-match behavior, JSON output, fuzzing, and oracle tests; done means the listed exact-match, divergence, depth-limit, offline, and performance criteria pass.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

enhancement follow-up

User outcome

Run dircue identify DIR --against PATH_TO_REPO [PATH_TO_REPO...] and learn whether the directory is an exact match for any commit's tree in those repositories, or which commit it's closest to and how many paths differ. Works entirely offline, reading the repositories as data.

Why

  • Once #101 computes Git-compatible tree IDs for plain directories, the natural next step is matching a directory against known commits.
  • An unpacked source tarball, a copied checkout or a directory on an old drive can be confirmed as commit abc123 (or flagged as diverged from it) without executing git or connecting to a network.
  • The use case arises frequently when auditing archived source drops or reconstructing provenance of build inputs.
  • Building this on top of #101's tree hasher avoids any new identity format: the same git-sha1 / git-sha256 value is compared against the repository's commit graph.

Proposal

  • dircue identify DIR --against REPO...:
    • compute the tree ID for DIR (reusing the pkg/treehash/ hasher from #101, both SHA-1 and SHA-256);
    • walk each repository's commit graph (bounded, first-parent by default; --all-branches opt-in) from HEAD backwards, looking for an exact tree-ID match;
    • also try sub-tree matching: if no root match is found, check whether the directory matches a subtree at a known path (useful for vendored copies);
    • on an exact match, report the commit hash, its date, author identity stripped of email, and message subject;
    • on no exact match, report the nearest commit by number of differing paths and list the paths that differ (bounded at 100 paths);
    • all reading is through go-git's filesystem storage (same approach as pkg/scanner/git.go), no process spawning.
  • Bounded walk: default depth limit of 10,000 commits; --depth N to override; always report the search depth in output.
  • Output format: JSON (same --format flag as other dircue commands).

Tasks

  • Command wiring: dircue identify subcommand in the CLI.
  • Bounded commit-graph walker in pkg/treehash/ (or new pkg/identify/ if the scope grows): iterates commits, extracts tree IDs, supports first-parent and all-branches modes.
  • Sub-tree matching: compare the directory's tree ID against every named sub-tree of each candidate commit.
  • Nearest-match scorer: count differing paths between the directory tree and each candidate tree; report top N candidates.
  • Output rendering: exact-match and nearest-match JSON structures.

Test plan

  • Unit tests (pkg/identify/identify_test.go, new): exact match returns the correct commit; depth-limit is respected; sub-tree match finds a vendored copy; nearest-match returns the commit with the fewest path differences; empty directory matches Git's empty tree on any repo.
  • Independent oracle (dircue-identify-oracle:git-2.49, new container): git rev-parse HEAD^{tree} and git log --format=%T provide ground truth; harness unpacks a known-tagged tarball and asserts dircue identify returns the correct commit.
  • Fixtures (tests/identify/fixtures/, new): small synthetic repos with known commit graphs and tagged tarballs; generated by tests/identify/gen_fixtures.py (new), not committed as binaries.
  • Metamorphic invariants: adding one byte to any file in the directory → no exact match on the original commit; reverting the byte → exact match restored.
  • Fuzz target (pkg/identify/fuzz_test.go, new): FuzzCommitWalk — seeds from fixture repo paths; properties: never panics, depth limit is never exceeded.
  • Performance: make bench-identify (new) over a 10k-commit synthetic repo; assert walk completes in under 10 s on CI hardware.
  • CI placement: unit tests in the existing test job every PR; oracle harness workflow_dispatch only (network-free, but container build is slow).

Risks

  • Cost. Walking 10,000 commits and their trees is O(commits × tree size). The depth limit and first-parent default bound this, but very large shallow repos may still be slow.
  • Sub-tree combinatorics. Checking every subtree of every commit is expensive. Limit to named subtrees at known paths (e.g., vendor/, third_party/) with a configurable allow-list.
  • Ambiguity. Two different commits can share the same tree ID. Report all matches up to a bound.

Success criteria

  • dircue identify finds the tagged commit for an unpacked official release tarball of a corpus repo.
  • Nearest-match mode lists the correct differing paths when one file is modified.
  • No process is spawned; strace/dtrace in the test container confirms this.

Related

  • #101 (parent; provides the tree hasher and content identity this command depends on)
  • #99, #97 (ledger and cache use the same blob IDs)
  • #100 (root identity in forest mode reuses the same hasher)

This follow-up came out of an idea-wizard session on 2026-09-23. The milestone is deliberately unset. It must preserve dircue's contracts: deterministic, offline output, with no execution of inspected content; the legacy Linguist-compatible CLI and output unchanged; unknown never rendered as absent; no provider findings or verdicts imported; CI event-driven only (no schedule:).

Lingua principale
Go
Stelle
0
Fork
0
Merge medio
6h 18m
PR unite (30g)
16

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di war-and-code/dircue

Tutte le issue di war-and-code/dircue

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.