rust/hg-core/src/vfs.rs
author Pierre-Yves David <pierre-yves.david@octobus.net>
Fri, 01 Oct 2021 03:30:00 +0200
changeset 48153 c29d312657d2
parent 47955 e834b79def74
child 48199 9d0e5629cfbf
permissions -rw-r--r--
dirstate-item: drop the `merged` property It has no user anymore. Differential Revision: https://phab.mercurial-scm.org/D11597
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     1
use crate::errors::{HgError, IoErrorContext, IoResultExt};
47955
e834b79def74 rust: Switch to the memmap2-rs crate
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
     2
use memmap2::{Mmap, MmapOptions};
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     3
use std::io::ErrorKind;
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     4
use std::path::{Path, PathBuf};
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     5
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     6
/// Filesystem access abstraction for the contents of a given "base" diretory
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     7
#[derive(Clone, Copy)]
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     8
pub struct Vfs<'a> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     9
    pub(crate) base: &'a Path,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    10
}
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    11
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    12
impl Vfs<'_> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    13
    pub fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    14
        self.base.join(relative_path)
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    15
    }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    16
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    17
    pub fn read(
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    18
        &self,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    19
        relative_path: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    20
    ) -> Result<Vec<u8>, HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    21
        let path = self.join(relative_path);
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    22
        std::fs::read(&path).when_reading_file(&path)
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    23
    }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    24
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    25
    pub fn mmap_open(
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    26
        &self,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    27
        relative_path: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    28
    ) -> Result<Mmap, HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    29
        let path = self.base.join(relative_path);
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    30
        let file = std::fs::File::open(&path).when_reading_file(&path)?;
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    31
        // TODO: what are the safety requirements here?
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    32
        let mmap = unsafe { MmapOptions::new().map(&file) }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    33
            .when_reading_file(&path)?;
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    34
        Ok(mmap)
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    35
    }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    36
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    37
    pub fn rename(
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    38
        &self,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    39
        relative_from: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    40
        relative_to: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    41
    ) -> Result<(), HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    42
        let from = self.join(relative_from);
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    43
        let to = self.join(relative_to);
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    44
        std::fs::rename(&from, &to)
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    45
            .with_context(|| IoErrorContext::RenamingFile { from, to })
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    46
    }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    47
}
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    48
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    49
fn fs_metadata(
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    50
    path: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    51
) -> Result<Option<std::fs::Metadata>, HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    52
    let path = path.as_ref();
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    53
    match std::fs::metadata(path) {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    54
        Ok(meta) => Ok(Some(meta)),
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    55
        Err(error) => match error.kind() {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    56
            // TODO: when we require a Rust version where `NotADirectory` is
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    57
            // stable, invert this logic and return None for it and `NotFound`
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    58
            // and propagate any other error.
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    59
            ErrorKind::PermissionDenied => Err(error).with_context(|| {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    60
                IoErrorContext::ReadingMetadata(path.to_owned())
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    61
            }),
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    62
            _ => Ok(None),
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    63
        },
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    64
    }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    65
}
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    66
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    67
pub(crate) fn is_dir(path: impl AsRef<Path>) -> Result<bool, HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    68
    Ok(fs_metadata(path)?.map_or(false, |meta| meta.is_dir()))
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    69
}
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    70
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    71
pub(crate) fn is_file(path: impl AsRef<Path>) -> Result<bool, HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    72
    Ok(fs_metadata(path)?.map_or(false, |meta| meta.is_file()))
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    73
}