rust/hg-core/src/vfs.rs
changeset 48418 abeae090ce67
parent 48417 5734b03ecf3e
child 49485 ffd4b1f1c9cb
equal deleted inserted replaced
48417:5734b03ecf3e 48418:abeae090ce67
     1 use crate::errors::{HgError, IoErrorContext, IoResultExt};
     1 use crate::errors::{HgError, IoErrorContext, IoResultExt};
     2 use memmap2::{Mmap, MmapOptions};
     2 use memmap2::{Mmap, MmapOptions};
     3 use std::io::ErrorKind;
     3 use std::io::{ErrorKind, Write};
     4 use std::path::{Path, PathBuf};
     4 use std::path::{Path, PathBuf};
     5 
     5 
     6 /// Filesystem access abstraction for the contents of a given "base" diretory
     6 /// Filesystem access abstraction for the contents of a given "base" diretory
     7 #[derive(Clone, Copy)]
     7 #[derive(Clone, Copy)]
     8 pub struct Vfs<'a> {
     8 pub struct Vfs<'a> {
   103         relative_link_path: impl AsRef<Path>,
   103         relative_link_path: impl AsRef<Path>,
   104         target_path: impl AsRef<Path>,
   104         target_path: impl AsRef<Path>,
   105     ) -> Result<(), HgError> {
   105     ) -> Result<(), HgError> {
   106         let link_path = self.join(relative_link_path);
   106         let link_path = self.join(relative_link_path);
   107         std::os::unix::fs::symlink(target_path, &link_path)
   107         std::os::unix::fs::symlink(target_path, &link_path)
   108             .with_context(|| IoErrorContext::WritingFile(link_path))
   108             .when_writing_file(&link_path)
       
   109     }
       
   110 
       
   111     /// Write `contents` into a temporary file, then rename to `relative_path`.
       
   112     /// This makes writing to a file "atomic": a reader opening that path will
       
   113     /// see either the previous contents of the file or the complete new
       
   114     /// content, never a partial write.
       
   115     pub fn atomic_write(
       
   116         &self,
       
   117         relative_path: impl AsRef<Path>,
       
   118         contents: &[u8],
       
   119     ) -> Result<(), HgError> {
       
   120         let mut tmp = tempfile::NamedTempFile::new_in(self.base)
       
   121             .when_writing_file(self.base)?;
       
   122         tmp.write_all(contents)
       
   123             .and_then(|()| tmp.flush())
       
   124             .when_writing_file(tmp.path())?;
       
   125         let path = self.join(relative_path);
       
   126         tmp.persist(&path)
       
   127             .map_err(|e| e.error)
       
   128             .when_writing_file(&path)?;
       
   129         Ok(())
   109     }
   130     }
   110 }
   131 }
   111 
   132 
   112 fn fs_metadata(
   133 fn fs_metadata(
   113     path: impl AsRef<Path>,
   134     path: impl AsRef<Path>,