Oxidized Patch #
Part of the overby.me monorepo, where this lives in
safety/oxidized/patchand where all development happens.It is also published on its own, as tangled.org/overby.me/oxidized-patch and github.com/overby-me/oxidized-patch. Both are read-only mirrors, rebuilt from the monorepo with josh: a commit made to either is overwritten by the next sync, so please open issues and pull requests on the monorepo.
A pure-Rust reimplementation of GNU patch(1) that aims to be output-
compatible with the upstream tool. Passes 49/49 tests from the
GNU patch 2.8 test suite.
Building #
nix build .#oxidized-patch
./result/bin/patch --help
A debug build is also available as .#oxidized-patch-dev for quick iteration.
Running the test suite #
Tests are run in a Nix sandbox. Each test script comes from the GNU patch
source tarball; oxidized-patch is placed at $abs_top_builddir/src/patch and
the script is executed against it.
# Run a single test
nix build .#checks.x86_64-linux.oxidized-patch-test-{name}
# View failure diff
nix log .#checks.x86_64-linux.oxidized-patch-test-{name}
See default.nix for the full list of test names. Tests time out after 60s.
Supported features #
All GNU patch 2.8 features exercised by the upstream test suite, including:
- Unified, context, normal, and ed-style diffs (auto-detected)
- Git extended headers:
diff --git,new/deleted file mode,old/new mode,rename from/to,copy from/to,index, symlink mode (120000) -p Npath stripping (including-p0and stripping empty)-Rreverse,-N/--forward,-f/--force,-t/--batch-b/--backupwith--backup-suffix,--backup-prefix,--basename-prefix, numbered/existing/simple backups viaVERSION_CONTROL--no-backup-if-mismatch,-E/--remove-empty-files-o FILEwith POSIX multi-patch concatenation-i FILE,-d DIR,-r FILE(reject file)--dry-run,--silent/-s,--verbose/-v--read-only={ignore,warn,fail}--reject-format={context,unified},--posix,--binary--follow-symlinks(writes a regular file, doesn't write through the link)-e/--edand auto-detection of ed-style input via positional file--set-utc(parses YYYY-MM-DD HH:MM:SS + offset, updates mtime)- CRLF handling: per-file decision,
--binarybyte-exact mode, "different line endings" hunk-failure suffix - Fuzz/offset matching with GNU's asymmetric-context heuristic
- Reject files in the matching format (or explicit
--reject-format) - Shell-quoted filenames with embedded whitespace or meta-chars in diagnostics
Known limitations #
--merge(diff3-style conflict merging) is not implemented; invoking it exits with a "not implemented" error so the upstreammergetest suite detects the absence and skips.- Interactive prompts (e.g. "Apply anyway? [n]") are emitted as static
text and the implicit "no" is taken;
-f/-tcover the non-interactive cases. - GIT binary payloads are recognised (the header is parsed) but the base85 delta is not decoded — the file is left unmodified and a diagnostic is printed.
Layout #
safety/oxidized/patch/
Cargo.toml
default.nix # Nix package + test checks
testsuite.nix # Per-test Nix sandbox runner
CHANGELOG.md
README.md
src/
main.rs # Single-file implementation