ADR-0001: Inline get_diff instead of depending on cruft¶
Status: Accepted
Context¶
The original sync command depended on cruft — a third-party template management
tool — to compute the diff between the base and upstream versions of a template. This
required importing cruft's private _generate_diff API, which:
- Was an undocumented internal function not intended for external use and subject to breaking changes without notice.
- Added
cruftas a runtime dependency even though Rhiza only used a single helper. - Made the diff pipeline opaque: callers could not control the exact
git diffarguments (e.g., prefixes, binary handling, path stripping) needed for the subsequentgit apply -3step. - Introduced cross-platform path issues on Windows where absolute path prefixes in the generated diff prevented clean patch application.
Decision¶
Replace the cruft dependency with an inline _get_diff(repo0, repo1) function in
src/rhiza/commands/sync.py that calls git diff --no-index directly:
result = subprocess.run(
[
git, "-c", "diff.noprefix=",
"diff", "--no-index", "--relative", "--binary",
f"--src-prefix={_DIFF_SRC_PREFIX}/",
f"--dst-prefix={_DIFF_DST_PREFIX}/",
"--no-ext-diff", "--no-color",
repo0_str, repo1_str,
],
cwd=repo0_str,
capture_output=True,
)
Fixed prefixes (upstream-template-old / upstream-template-new) are used and any
absolute path segments are stripped from the diff output so that git apply -3 can
locate files relative to the project root on all platforms.
Consequences¶
Positive
cruftis no longer a runtime dependency, reducing the dependency surface area and eliminating the risk of upstream breakage from internal API changes.- Full control over every
git diffflag:--binaryhandles binary files correctly,--no-ext-diffprevents external diff drivers from corrupting the patch, and the fixed prefix scheme is stable across runs. - Cross-platform path normalisation (Windows drive letters are stripped via regex) makes the patch portable.
- The implementation is self-contained and easier to test in isolation.
Negative
gitmust be available onPATH(mitigated bymodels.get_git_executablewhich raises a clear error if git is missing).- The regex strip of drive letters (
/[a-z]:) is a heuristic that could in theory affect non-Windows paths with a matching pattern, though this has not been observed in practice.