pub async fn rollback_file_patch(
pkg_path: &Path,
file_name: &str,
original_content: &[u8],
expected_hash: &str,
) -> Result<(), Error>Expand description
Rollback a single file to its original state by writing
original_content (whose Git SHA256 must equal expected_hash).
This delegates to apply_file_patch,
the hardened write path shared with apply. Rolling a file back is the
exact same operation as patching it forward — “safely overwrite this
file with these hash-verified bytes” — so it must get the exact same
guarantees:
- Atomic — the bytes are staged in the parent directory, fsync’d,
and
rename(2)d over the target. A crash orENOSPCmid-write leaves either the old or the new content, never a truncated file. - Copy-on-write safe — a symlink/hardlink into a shared content store (pnpm, Nix, the Go module cache) is broken into a private inode first, so a rollback never bleeds into a sibling project’s copy or the store entry.
- Validate-before-write —
original_contentis hash-checked in memory before any disk write, so a corrupt blob is refused instead of being committed over the file and only then flagged. - Permission-faithful — the file’s mode + uid/gid are restored
afterward. Because apply preserves a file’s original permissions
when patching, the on-disk patched file already carries the
pre-patch mode (e.g. a read-only
0o444Go-cache source), and that exact mode is re-applied to the rolled-back inode.
The previous implementation used a bare in-place tokio::fs::write,
which had none of these properties: it could corrupt a hardlinked
sibling, leave a half-written file on a crash, write a bad blob over
the file before discovering the hash mismatch, and leave a
read-only file writable.