[Updated] D11836: rust: Add Vfs::write_atomic
SimonSapin
phabricator at mercurial-scm.org
Tue Dec 7 15:05:34 UTC 2021
Closed by commit rHGabeae090ce67: rust: Add Vfs::write_atomic (authored by SimonSapin).
This revision was automatically updated to reflect the committed changes.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D11836?vs=31265&id=31351
CHANGES SINCE LAST ACTION
https://phab.mercurial-scm.org/D11836/new/
REVISION DETAIL
https://phab.mercurial-scm.org/D11836
AFFECTED FILES
rust/hg-core/src/errors.rs
rust/hg-core/src/vfs.rs
CHANGE DETAILS
diff --git a/rust/hg-core/src/vfs.rs b/rust/hg-core/src/vfs.rs
--- a/rust/hg-core/src/vfs.rs
+++ b/rust/hg-core/src/vfs.rs
@@ -1,6 +1,6 @@
use crate::errors::{HgError, IoErrorContext, IoResultExt};
use memmap2::{Mmap, MmapOptions};
-use std::io::ErrorKind;
+use std::io::{ErrorKind, Write};
use std::path::{Path, PathBuf};
/// Filesystem access abstraction for the contents of a given "base" diretory
@@ -105,7 +105,28 @@
) -> Result<(), HgError> {
let link_path = self.join(relative_link_path);
std::os::unix::fs::symlink(target_path, &link_path)
- .with_context(|| IoErrorContext::WritingFile(link_path))
+ .when_writing_file(&link_path)
+ }
+
+ /// Write `contents` into a temporary file, then rename to `relative_path`.
+ /// This makes writing to a file "atomic": a reader opening that path will
+ /// see either the previous contents of the file or the complete new
+ /// content, never a partial write.
+ pub fn atomic_write(
+ &self,
+ relative_path: impl AsRef<Path>,
+ contents: &[u8],
+ ) -> Result<(), HgError> {
+ let mut tmp = tempfile::NamedTempFile::new_in(self.base)
+ .when_writing_file(self.base)?;
+ tmp.write_all(contents)
+ .and_then(|()| tmp.flush())
+ .when_writing_file(tmp.path())?;
+ let path = self.join(relative_path);
+ tmp.persist(&path)
+ .map_err(|e| e.error)
+ .when_writing_file(&path)?;
+ Ok(())
}
}
diff --git a/rust/hg-core/src/errors.rs b/rust/hg-core/src/errors.rs
--- a/rust/hg-core/src/errors.rs
+++ b/rust/hg-core/src/errors.rs
@@ -151,6 +151,8 @@
/// Converts a `Result` with `std::io::Error` into one with `HgError`.
fn when_reading_file(self, path: &std::path::Path) -> Result<T, HgError>;
+ fn when_writing_file(self, path: &std::path::Path) -> Result<T, HgError>;
+
fn with_context(
self,
context: impl FnOnce() -> IoErrorContext,
@@ -162,6 +164,10 @@
self.with_context(|| IoErrorContext::ReadingFile(path.to_owned()))
}
+ fn when_writing_file(self, path: &std::path::Path) -> Result<T, HgError> {
+ self.with_context(|| IoErrorContext::WritingFile(path.to_owned()))
+ }
+
fn with_context(
self,
context: impl FnOnce() -> IoErrorContext,
To: SimonSapin, #hg-reviewers, Alphare
Cc: mercurial-patches
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-patches/attachments/20211207/49f83436/attachment-0002.html>
More information about the Mercurial-patches
mailing list