Repository navigation
Harvester first run fails when no checkpoint exists #1128
Description
Issue
What is the issue?
The no-checkpoint branch of _harvest_repository() cannot bootstrap a new repository. It passes a hardcoded empty-tree ID to ChangeDetector.get_modified_files_since(), but:
- The configured ID (
4b825dc642cb6eb9a060e54bf8d6927bf442cfb4) is incorrect. The SHA-1 empty-tree ID is4b825dc642cb6eb9a060e54bf8d69288fbee4904. - Correcting the ID alone still fails:
_resolve_commit()verifies every input with^{commit}, which rejects a tree object beforegit diffruns.
On main fbacf559, the code is at pipeline.py:139 and change_detector.py:14.
Expected Behaviour
A repository with no checkpoint should discover tracked files at HEAD, apply existing include/exclude rules, and process initial security documents. Subsequent checkpoint-based runs should continue comparing commits normally.
Actual Behaviour
The first-run branch raises CalledProcessError (Git exit 128) before filtering or document processing. Using the correct empty-tree ID changes the error to "expected commit type, but the object dereferences to tree type".
Steps to reproduce
From the repo root with Python dependencies installed, run this with the project's Python interpreter. This uses the actual detector and a temporary real Git repository; it does not alter the OpenCRE checkout or database.
import subprocess
import tempfile
from pathlib import Path
from application.utils.harvester.change_detector import ChangeDetector
from application.utils.harvester.git_repository_client import GitRepositoryClient
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
def git(*args, input_text=None):
return subprocess.run(
["git", "-C", str(root), "-c", "core.hooksPath=/dev/null", *args],
input=input_text, check=True, capture_output=True, text=True,
).stdout.strip()
git("init", "--object-format=sha1")
(root / "requirement.md").write_text("# Auth\nUse MFA.\n")
git("add", "requirement.md")
git("-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid",
"-c", "commit.gpgsign=false", "commit", "-m", "Fixture")
head = git("rev-parse", "HEAD")
empty_tree = git("hash-object", "-t", "tree", "-w", "--stdin", input_text="")
print("Direct git diff:", git("diff", "--name-only", empty_tree, head))
detector = ChangeDetector(GitRepositoryClient("LOCAL", "fixture", local_path=root))
for base in ("4b825dc642cb6eb9a060e54bf8d6927bf442cfb4", empty_tree):
try:
print(detector.get_modified_files_since(base, head))
except subprocess.CalledProcessError as error:
print(error.returncode, error.stderr.strip())Observed: the direct Git diff lists requirement.md; both detector calls fail. A separate two-commit control succeeds, isolating this to bootstrap input.
This reproduction isolates the per-repository first-run branch. The separate configuration-validation mismatch in run_harvester() is addressed by #1115; that patch does not alter this branch. The path parsing fix in #1032 / #1056 concerns DiffParser, a different component.
Proposed direction
Enumerate tracked files at the verified HEAD commit using git ls-tree -r --name-only -z for the no-checkpoint case, then retain the existing include/exclude filtering. This avoids a hardcoded empty-tree object and keeps commit-only verification for incremental history operations.
Regression coverage should use real Git fixtures for bootstrap and incremental runs, with nested/space/non-ASCII paths, excluded files, and an empty committed tree. No dependency or schema change is needed.
I checked existing issue/PR searches for the incorrect ID and empty-tree/first-run harvester failures and did not find a dedicated pending fix. Would this scoped fix be useful, and is anyone already working on it?
Activity