annotate rust/hg-core/src/vfs.rs @ 52167:7be39c5110c9

hg-core: add a complete VFS This will be used from Python in a later change. More changes are needed in hg-core and rhg to properly clean up the APIs of the old VFS implementation but it can be done when the dust settles and we start adding more functionality to the pure Rust VFS.
author Rapha?l Gom?s <rgomes@octobus.net>
date Mon, 29 Jul 2024 20:47:43 +0200
parents 46c68c0fe137
children 067ec8574c33
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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};
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
2 use crate::exit_codes;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
3 use dyn_clone::DynClone;
47955
e834b79def74 rust: Switch to the memmap2-rs crate
Simon Sapin <simon.sapin@octobus.net>
parents: 47952
diff changeset
4 use memmap2::{Mmap, MmapOptions};
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
5 use rand::distributions::DistString;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
6 use rand_distr::Alphanumeric;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
7 use std::fs::{File, OpenOptions};
48418
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
8 use std::io::{ErrorKind, Write};
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
9 use std::os::unix::fs::{MetadataExt, PermissionsExt};
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
10 use std::path::{Path, PathBuf};
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
11 use std::sync::OnceLock;
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
12
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
13 /// Filesystem access abstraction for the contents of a given "base" diretory
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
14 #[derive(Clone)]
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
15 pub struct VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
16 pub(crate) base: PathBuf,
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
17 pub readonly: bool,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
18 pub mode: Option<u32>,
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
19 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
20
48199
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
21 struct FileNotFound(std::io::Error, PathBuf);
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
22
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
23 /// Store the umask for the whole process since it's expensive to get.
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
24 static UMASK: OnceLock<u32> = OnceLock::new();
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
25
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
26 fn get_umask() -> u32 {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
27 *UMASK.get_or_init(|| unsafe {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
28 // TODO is there any way of getting the umask without temporarily
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
29 // setting it? Doesn't this affect all threads in this tiny window?
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
30 let mask = libc::umask(0);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
31 libc::umask(mask);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
32 mask & 0o777
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
33 })
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
34 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
35
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
36 /// Return the (unix) mode with which we will create/fix files
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
37 fn get_mode(base: impl AsRef<Path>) -> Option<u32> {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
38 match base.as_ref().metadata() {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
39 Ok(meta) => {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
40 // files in .hg/ will be created using this mode
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
41 let mode = meta.mode();
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
42 // avoid some useless chmods
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
43 if (0o777 & !get_umask()) == (0o777 & mode) {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
44 None
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
45 } else {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
46 Some(mode)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
47 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
48 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
49 Err(_) => None,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
50 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
51 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
52
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
53 impl VfsImpl {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
54 pub fn new(base: PathBuf, readonly: bool) -> Self {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
55 let mode = get_mode(&base);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
56 Self {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
57 base,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
58 readonly,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
59 mode,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
60 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
61 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
62
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
63 // XXX these methods are probably redundant with VFS trait?
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
64
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
65 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
66 self.base.join(relative_path)
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
67 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
68
48345
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
69 pub fn symlink_metadata(
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
70 &self,
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
71 relative_path: impl AsRef<Path>,
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
72 ) -> Result<std::fs::Metadata, HgError> {
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
73 let path = self.join(relative_path);
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
74 std::fs::symlink_metadata(&path).when_reading_file(&path)
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
75 }
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
76
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
77 pub fn read_link(
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
78 &self,
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
79 relative_path: impl AsRef<Path>,
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
80 ) -> Result<PathBuf, HgError> {
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
81 let path = self.join(relative_path);
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
82 std::fs::read_link(&path).when_reading_file(&path)
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
83 }
d5a91701f7dc rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents: 48199
diff changeset
84
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
85 pub fn read(
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
86 &self,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
87 relative_path: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
88 ) -> Result<Vec<u8>, HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
89 let path = self.join(relative_path);
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
90 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
91 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
92
49485
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
93 /// Returns `Ok(None)` if the file does not exist.
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
94 pub fn try_read(
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
95 &self,
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
96 relative_path: impl AsRef<Path>,
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
97 ) -> Result<Option<Vec<u8>>, HgError> {
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
98 match self.read(relative_path) {
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
99 Err(e) => match &e {
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
100 HgError::IoError { error, .. } => match error.kind() {
49914
58074252db3c rust: run `cargo clippy`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
101 ErrorKind::NotFound => Ok(None),
49485
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
102 _ => Err(e),
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
103 },
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
104 _ => Err(e),
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
105 },
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
106 Ok(v) => Ok(Some(v)),
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
107 }
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
108 }
ffd4b1f1c9cb rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48418
diff changeset
109
48199
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
110 fn mmap_open_gen(
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
111 &self,
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
112 relative_path: impl AsRef<Path>,
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
113 ) -> Result<Result<Mmap, FileNotFound>, HgError> {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
114 let path = self.join(relative_path);
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
115 let file = match std::fs::File::open(&path) {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
116 Err(err) => {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
117 if let ErrorKind::NotFound = err.kind() {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
118 return Ok(Err(FileNotFound(err, path)));
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
119 };
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
120 return (Err(err)).when_reading_file(&path);
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
121 }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
122 Ok(file) => file,
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
123 };
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
124 // Safety is "enforced" by locks and assuming other processes are
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
125 // well-behaved. If any misbehaving or malicious process does touch
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
126 // the index, it could lead to corruption. This is inherent
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
127 // to file-based `mmap`, though some platforms have some ways of
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
128 // mitigating.
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
129 // TODO linux: set the immutable flag with `chattr(1)`?
48199
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
130 let mmap = unsafe { MmapOptions::new().map(&file) }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
131 .when_reading_file(&path)?;
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
132 Ok(Ok(mmap))
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
133 }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
134
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
135 pub fn mmap_open_opt(
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
136 &self,
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
137 relative_path: impl AsRef<Path>,
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
138 ) -> Result<Option<Mmap>, HgError> {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
139 self.mmap_open_gen(relative_path).map(|res| res.ok())
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
140 }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
141
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
142 pub fn mmap_open(
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
143 &self,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
144 relative_path: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
145 ) -> Result<Mmap, HgError> {
48199
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
146 match self.mmap_open_gen(relative_path)? {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
147 Err(FileNotFound(err, path)) => Err(err).when_reading_file(&path),
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
148 Ok(res) => Ok(res),
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 47955
diff changeset
149 }
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
150 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
151
48417
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
152 #[cfg(unix)]
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
153 pub fn create_symlink(
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
154 &self,
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
155 relative_link_path: impl AsRef<Path>,
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
156 target_path: impl AsRef<Path>,
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
157 ) -> Result<(), HgError> {
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
158 let link_path = self.join(relative_link_path);
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
159 std::os::unix::fs::symlink(target_path, &link_path)
48418
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
160 .when_writing_file(&link_path)
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
161 }
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
162
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
163 /// Write `contents` into a temporary file, then rename to `relative_path`.
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
164 /// This makes writing to a file "atomic": a reader opening that path will
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
165 /// see either the previous contents of the file or the complete new
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
166 /// content, never a partial write.
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
167 pub fn atomic_write(
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
168 &self,
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
169 relative_path: impl AsRef<Path>,
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
170 contents: &[u8],
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
171 ) -> Result<(), HgError> {
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
172 let mut tmp = tempfile::NamedTempFile::new_in(&self.base)
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
173 .when_writing_file(&self.base)?;
48418
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
174 tmp.write_all(contents)
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
175 .and_then(|()| tmp.flush())
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
176 .when_writing_file(tmp.path())?;
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
177 let path = self.join(relative_path);
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
178 tmp.persist(&path)
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
179 .map_err(|e| e.error)
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
180 .when_writing_file(&path)?;
abeae090ce67 rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents: 48417
diff changeset
181 Ok(())
48417
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48345
diff changeset
182 }
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
183 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
184
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
185 fn fs_metadata(
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
186 path: impl AsRef<Path>,
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
187 ) -> Result<Option<std::fs::Metadata>, HgError> {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
188 let path = path.as_ref();
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
189 match std::fs::metadata(path) {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
190 Ok(meta) => Ok(Some(meta)),
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
191 Err(error) => match error.kind() {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
192 // 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
193 // 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
194 // and propagate any other error.
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
195 ErrorKind::PermissionDenied => Err(error).with_context(|| {
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
196 IoErrorContext::ReadingMetadata(path.to_owned())
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
197 }),
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
198 _ => Ok(None),
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
199 },
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
200 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
201 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
202
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
203 /// Writable file object that atomically updates a file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
204 ///
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
205 /// All writes will go to a temporary copy of the original file. Call
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
206 /// [`Self::close`] when you are done writing, and [`Self`] will rename
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
207 /// the temporary copy to the original name, making the changes
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
208 /// visible. If the object is destroyed without being closed, all your
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
209 /// writes are discarded.
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
210 pub struct AtomicFile {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
211 /// The temporary file to write to
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
212 fp: std::fs::File,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
213 /// Path of the temp file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
214 temp_path: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
215 /// Used when stat'ing the file, is useful only if the target file is
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
216 /// guarded by any lock (e.g. repo.lock or repo.wlock).
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
217 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
218 /// Path of the target file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
219 target_name: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
220 /// Whether the file is open or not
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
221 is_open: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
222 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
223
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
224 impl AtomicFile {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
225 pub fn new(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
226 fp: std::fs::File,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
227 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
228 temp_name: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
229 target_name: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
230 ) -> Self {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
231 Self {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
232 fp,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
233 check_ambig,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
234 temp_path: temp_name,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
235 target_name,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
236 is_open: true,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
237 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
238 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
239
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
240 /// Write `buf` to the temporary file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
241 pub fn write_all(&mut self, buf: &[u8]) -> Result<(), std::io::Error> {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
242 self.fp.write_all(buf)
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
243 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
244
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
245 fn target(&self) -> PathBuf {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
246 self.temp_path
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
247 .parent()
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
248 .expect("should not be at the filesystem root")
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
249 .join(&self.target_name)
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
250 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
251
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
252 /// Close the temporary file and rename to the target
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
253 pub fn close(mut self) -> Result<(), std::io::Error> {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
254 self.fp.flush()?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
255 let target = self.target();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
256 if self.check_ambig {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
257 if let Ok(stat) = std::fs::metadata(&target) {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
258 std::fs::rename(&self.temp_path, &target)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
259 let new_stat = std::fs::metadata(&target)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
260 let ctime = new_stat.ctime();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
261 let is_ambiguous = ctime == stat.ctime();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
262 if is_ambiguous {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
263 let advanced =
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
264 filetime::FileTime::from_unix_time(ctime + 1, 0);
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
265 filetime::set_file_times(target, advanced, advanced)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
266 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
267 } else {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
268 std::fs::rename(&self.temp_path, target)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
269 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
270 } else {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
271 std::fs::rename(&self.temp_path, target).unwrap();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
272 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
273 self.is_open = false;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
274 Ok(())
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
275 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
276 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
277
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
278 impl Drop for AtomicFile {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
279 fn drop(&mut self) {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
280 if self.is_open {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
281 std::fs::remove_file(self.target()).ok();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
282 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
283 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
284 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
285
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
286 /// Abstracts over the VFS to allow for different implementations of the
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
287 /// filesystem layer (like passing one from Python).
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
288 pub trait Vfs: Sync + Send + DynClone {
52157
46c68c0fe137 rust-vfs: add a TODO to remember a decision taken about naming
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51864
diff changeset
289 // TODO make `open` readonly and make `open_read` an `open_write`
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
290 fn open(&self, filename: &Path) -> Result<std::fs::File, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
291 fn open_read(&self, filename: &Path) -> Result<std::fs::File, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
292 fn open_check_ambig(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
293 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
294 filename: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
295 ) -> Result<std::fs::File, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
296 fn create(&self, filename: &Path) -> Result<std::fs::File, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
297 /// Must truncate the new file if exist
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
298 fn create_atomic(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
299 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
300 filename: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
301 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
302 ) -> Result<AtomicFile, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
303 fn file_size(&self, file: &File) -> Result<u64, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
304 fn exists(&self, filename: &Path) -> bool;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
305 fn unlink(&self, filename: &Path) -> Result<(), HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
306 fn rename(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
307 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
308 from: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
309 to: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
310 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
311 ) -> Result<(), HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
312 fn copy(&self, from: &Path, to: &Path) -> Result<(), HgError>;
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
313 fn base(&self) -> &Path;
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
314 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
315
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
316 /// These methods will need to be implemented once `rhg` (and other) non-Python
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
317 /// users of `hg-core` start doing more on their own, like writing to files.
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
318 impl Vfs for VfsImpl {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
319 fn open(&self, filename: &Path) -> Result<std::fs::File, HgError> {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
320 if self.readonly {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
321 return Err(HgError::abort(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
322 "write access in a readonly vfs",
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
323 exit_codes::ABORT,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
324 None,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
325 ));
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
326 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
327 // TODO auditpath
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
328 let path = self.base.join(filename);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
329 copy_in_place_if_hardlink(&path)?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
330
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
331 OpenOptions::new()
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
332 .create(false)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
333 .create_new(false)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
334 .write(true)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
335 .read(true)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
336 .open(&path)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
337 .when_writing_file(&path)
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
338 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
339
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
340 fn open_read(&self, filename: &Path) -> Result<std::fs::File, HgError> {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
341 // TODO auditpath
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
342 let path = self.base.join(filename);
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
343 std::fs::File::open(&path).when_reading_file(&path)
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
344 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
345
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
346 fn open_check_ambig(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
347 &self,
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
348 filename: &Path,
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
349 ) -> Result<std::fs::File, HgError> {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
350 if self.readonly {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
351 return Err(HgError::abort(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
352 "write access in a readonly vfs",
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
353 exit_codes::ABORT,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
354 None,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
355 ));
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
356 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
357
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
358 let path = self.base.join(filename);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
359 copy_in_place_if_hardlink(&path)?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
360
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
361 // TODO auditpath, check ambig
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
362 OpenOptions::new()
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
363 .write(true)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
364 .read(true) // Can be used for reading to save on `open` calls
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
365 .create(false)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
366 .open(&path)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
367 .when_reading_file(&path)
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
368 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
369
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
370 fn create(&self, filename: &Path) -> Result<std::fs::File, HgError> {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
371 if self.readonly {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
372 return Err(HgError::abort(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
373 "write access in a readonly vfs",
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
374 exit_codes::ABORT,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
375 None,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
376 ));
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
377 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
378 // TODO auditpath
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
379 let path = self.base.join(filename);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
380 let parent = path.parent().expect("file at root");
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
381 std::fs::create_dir_all(parent).when_writing_file(parent)?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
382 // TODO checkambig (wrap File somehow)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
383
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
384 let file = OpenOptions::new()
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
385 .create(true)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
386 .truncate(true)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
387 .write(true)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
388 .read(true)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
389 .open(&path)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
390 .when_writing_file(&path)?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
391
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
392 if let Some(mode) = self.mode {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
393 // Creating the file with the right permission (with `.mode()`)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
394 // may not work since umask takes effect for file creation.
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
395 // So we need to fix the permission after creating the file.
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
396 fix_directory_permissions(&self.base, &path, mode)?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
397 let perm = std::fs::Permissions::from_mode(mode & 0o666);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
398 std::fs::set_permissions(&path, perm).when_writing_file(&path)?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
399 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
400
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
401 Ok(file)
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
402 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
403
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
404 fn create_atomic(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
405 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
406 _filename: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
407 _check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
408 ) -> Result<AtomicFile, HgError> {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
409 todo!()
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
410 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
411
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
412 fn file_size(&self, file: &File) -> Result<u64, HgError> {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
413 Ok(file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
414 .metadata()
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
415 .map_err(|e| {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
416 HgError::abort(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
417 format!("Could not get file metadata: {}", e),
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
418 exit_codes::ABORT,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
419 None,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
420 )
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
421 })?
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
422 .size())
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
423 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
424
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
425 fn exists(&self, filename: &Path) -> bool {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
426 self.base.join(filename).exists()
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
427 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
428
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
429 fn unlink(&self, filename: &Path) -> Result<(), HgError> {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
430 if self.readonly {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
431 return Err(HgError::abort(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
432 "write access in a readonly vfs",
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
433 exit_codes::ABORT,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
434 None,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
435 ));
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
436 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
437 let path = self.base.join(filename);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
438 std::fs::remove_file(&path)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
439 .with_context(|| IoErrorContext::RemovingFile(path))
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
440 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
441
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
442 fn rename(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
443 &self,
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
444 from: &Path,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
445 to: &Path,
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
446 _check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
447 ) -> Result<(), HgError> {
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
448 if self.readonly {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
449 return Err(HgError::abort(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
450 "write access in a readonly vfs",
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
451 exit_codes::ABORT,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
452 None,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
453 ));
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
454 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
455 // TODO checkambig
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
456 let from = self.base.join(from);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
457 let to = self.base.join(to);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
458 std::fs::rename(&from, &to)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
459 .with_context(|| IoErrorContext::RenamingFile { from, to })
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
460 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
461
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
462 fn copy(&self, from: &Path, to: &Path) -> Result<(), HgError> {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
463 // TODO checkambig?
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
464 let from = self.base.join(from);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
465 let to = self.base.join(to);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
466 std::fs::copy(&from, &to)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
467 .with_context(|| IoErrorContext::CopyingFile { from, to })
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
468 .map(|_| ())
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
469 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
470
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
471 fn base(&self) -> &Path {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
472 &self.base
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
473 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
474 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
475
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
476 fn fix_directory_permissions(
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
477 base: &Path,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
478 path: &Path,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
479 mode: u32,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
480 ) -> Result<(), HgError> {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
481 let mut ancestors = path.ancestors();
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
482 ancestors.next(); // yields the path itself
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
483
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
484 for ancestor in ancestors {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
485 if ancestor == base {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
486 break;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
487 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
488 let perm = std::fs::Permissions::from_mode(mode);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
489 std::fs::set_permissions(ancestor, perm)
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
490 .when_writing_file(ancestor)?;
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
491 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
492 Ok(())
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
493 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
494
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
495 /// Detects whether `path` is a hardlink and does a tmp copy + rename erase
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
496 /// to turn it into its own file. Revlogs are usually hardlinked when doing
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
497 /// a local clone, and we don't want to modify the original repo.
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
498 fn copy_in_place_if_hardlink(path: &Path) -> Result<(), HgError> {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
499 let metadata = path.metadata().when_writing_file(path)?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
500 if metadata.nlink() > 0 {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
501 // If it's hardlinked, copy it and rename it back before changing it.
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
502 let tmpdir = path.parent().expect("file at root");
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
503 let name = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
504 let tmpfile = tmpdir.join(name);
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
505 std::fs::create_dir_all(tmpfile.parent().expect("file at root"))
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
506 .with_context(|| IoErrorContext::CopyingFile {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
507 from: path.to_owned(),
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
508 to: tmpfile.to_owned(),
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
509 })?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
510 std::fs::copy(path, &tmpfile).with_context(|| {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
511 IoErrorContext::CopyingFile {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
512 from: path.to_owned(),
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
513 to: tmpfile.to_owned(),
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
514 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
515 })?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
516 std::fs::rename(&tmpfile, path).with_context(|| {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
517 IoErrorContext::RenamingFile {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
518 from: tmpfile,
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
519 to: path.to_owned(),
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
520 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
521 })?;
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
522 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
523 Ok(())
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
524 }
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
525
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
526 pub fn is_revlog_file(path: impl AsRef<Path>) -> bool {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
527 path.as_ref()
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
528 .extension()
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
529 .map(|ext| {
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
530 ["i", "idx", "d", "dat", "n", "nd", "sda"]
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
531 .contains(&ext.to_string_lossy().as_ref())
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
532 })
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
533 .unwrap_or(false)
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
534 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
535
47952
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
536 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
537 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
538 }
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
539
9cd35c8c6044 rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
540 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
541 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
542 }
50180
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
543
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
544 /// Returns whether the given `path` is on a network file system.
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
545 /// Taken from `cargo`'s codebase.
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
546 #[cfg(target_os = "linux")]
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
547 pub(crate) fn is_on_nfs_mount(path: impl AsRef<Path>) -> bool {
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
548 use std::ffi::CString;
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
549 use std::mem;
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
550 use std::os::unix::prelude::*;
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
551
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
552 let path = match CString::new(path.as_ref().as_os_str().as_bytes()) {
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
553 Ok(path) => path,
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
554 Err(_) => return false,
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
555 };
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
556
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
557 unsafe {
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
558 let mut buf: libc::statfs = mem::zeroed();
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
559 let r = libc::statfs(path.as_ptr(), &mut buf);
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
560
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
561 r == 0 && buf.f_type as u32 == libc::NFS_SUPER_MAGIC as u32
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
562 }
be019ac8c1e4 dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49485
diff changeset
563 }
50274
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
564
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
565 /// Similar to what Cargo does; although detecting NFS (or non-local
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
566 /// file systems) _should_ be possible on other operating systems,
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
567 /// we'll just assume that mmap() works there, for now; after all,
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
568 /// _some_ functionality is better than a compile error, i.e. none at
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
569 /// all
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
570 #[cfg(not(target_os = "linux"))]
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
571 pub(crate) fn is_on_nfs_mount(_path: impl AsRef<Path>) -> bool {
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
572 false
0cc19a53cef4 rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 50252
diff changeset
573 }