Skip to main content

rollback_file_patch

Function rollback_file_patch 

Source
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 or ENOSPC mid-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-writeoriginal_content is 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 0o444 Go-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.