- Single-package Go CLI at the repo root;
main.gocontains argument parsing, execution flow, preprocessing, and diff backend handling. - Unit tests live in
main_test.goand cover argument parsing, input resolution, rule selection/applicability, staging, color injection, shell quoting, and keyrunbranches. go.moddeclares modulegithub.com/tlil/diffhanceand Go1.26; there are no third-party Go dependencies orgo.sum.- The built local binary name
diffhanceis ignored by.gitignore; avoid committing binaries ordist/artifacts.
- Format after Go edits:
gofmt -w main.go main_test.go. - Run the unit test suite and compile-check everything:
go test ./.... - Check statement coverage when test behavior changes:
go test -cover ./.... - Build local CLI:
go build -o diffhance .. - Match CI release-style build:
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o diffhance ..
- Exit codes intentionally mirror
diff(1):0identical,1different,>1error. - In
--gitmode, a backend diff exit code of1is swallowed to0because Git treats non-zero external diff exits as fatal. - Preprocessors and diff backends run through a shell:
/bin/sh -cexcept Windows, whereComSpec /Corcmd /Cis used. --rule GLOB:CMDmatches onlyfilepath.Base(displayPath); all matching rules are applied in resolved order as a shell pipeline; explicit--pre/--pre-left/--pre-rightoverride rules.- Staged temp paths preserve safe relative
displayPathdirectories underl/andr/so diff headers remain meaningful; unsafe or unrelated absolute display paths fall back to a basename. --config PATHreads rules as oneGLOB:CMDper line, ignoring blank lines and lines starting with#; config rules are inserted where the flag appears.- Existing default rules configs are auto-loaded from platform config locations as
diffhance/rulesand appended after explicit--rule/--configrules; missing default config files are ignored. --printkeeps temp files and prints their paths separated by a tab; normal diff mode deletes temp files on exit.--print-rulesprints the resolved rules to stdout, one per line, after explicit and default configs are loaded; it exits without requiring positional file args or running preprocess/diff.--print-config-dirsprints the default config file paths checked, one per line, without reading them; it exits without requiring positional file args or running preprocess/diff.- Default diff backend is
diff -u; color injection only appends--color=alwaysfor barediffwhen stdout is a terminal andNO_COLORis unset. - Bare
diffbackends get--label l/... --label r/...for clean unified diff headers;deltabackends receive a labeleddiff -ustream; other custom backends and already-labeled diff commands are left unchanged. diffhance [flags] git [args...](first positional arg is the literalgit) runsgit diff [args...]withGIT_EXTERNAL_DIFFset to the current binary (os.Executable()) in--gitmode; flags beforegitare forwarded into that command with POSIX single-quote quoting (git always uses a POSIX shell for external diffs, even on Windows), git's exit code is propagated, and--beforegitdisables the shorthand.
.github/workflows/build.ymlrunsgo test ./...in a dedicatedtestjob before building binaries.- CI builds
linux-{amd64,arm64},windows-{amd64,arm64}, anddarwin-arm64withCGO_ENABLED=0and uploads artifacts fromdist/<target>/.