Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/vfs.rs @ 52178:bd8081e9fd62
rust: don't star export from the `revlog` module
This made a lot of the imports confusing because they didn't make sense
at the top level (so, outside of `revlog`), and they hide the more common
types when autocompleting.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Thu, 26 Sep 2024 14:26:24 +0200 |
parents | 067ec8574c33 |
children | 82007b8c189e |
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 | 2 use crate::exit_codes; |
52168
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
3 use crate::fncache::FnCache; |
52178
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52168
diff
changeset
|
4 use crate::revlog::path_encode::path_encode; |
52168
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
5 use crate::utils::files::{get_bytes_from_path, get_path_from_bytes}; |
51864 | 6 use dyn_clone::DynClone; |
47955
e834b79def74
rust: Switch to the memmap2-rs crate
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
7 use memmap2::{Mmap, MmapOptions}; |
52168
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
8 use rand::distributions::{Alphanumeric, DistString}; |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
9 use std::fs::{File, OpenOptions}; |
48418
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
10 use std::io::{ErrorKind, Write}; |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
11 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
|
12 use std::path::{Path, PathBuf}; |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
13 use std::sync::OnceLock; |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
14 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
15 /// Filesystem access abstraction for the contents of a given "base" diretory |
51864 | 16 #[derive(Clone)] |
17 pub struct VfsImpl { | |
18 pub(crate) base: PathBuf, | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
19 pub readonly: bool, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
20 pub mode: Option<u32>, |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
21 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
22 |
48199
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
23 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
|
24 |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
25 /// 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
|
26 static UMASK: OnceLock<u32> = OnceLock::new(); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
27 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
28 fn get_umask() -> u32 { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
29 *UMASK.get_or_init(|| unsafe { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
30 // 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
|
31 // 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
|
32 let mask = libc::umask(0); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
33 libc::umask(mask); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
34 mask & 0o777 |
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 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
37 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
38 /// 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
|
39 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
|
40 match base.as_ref().metadata() { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
41 Ok(meta) => { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
42 // 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
|
43 let mode = meta.mode(); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
44 // avoid some useless chmods |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
45 if (0o777 & !get_umask()) == (0o777 & mode) { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
46 None |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
47 } else { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
48 Some(mode) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
49 } |
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 Err(_) => None, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
52 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
53 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
54 |
51864 | 55 impl VfsImpl { |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
56 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
|
57 let mode = get_mode(&base); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
58 Self { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
59 base, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
60 readonly, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
61 mode, |
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 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
64 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
65 // 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
|
66 |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
67 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
|
68 self.base.join(relative_path) |
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 |
48345
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
71 pub fn symlink_metadata( |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
72 &self, |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
73 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
|
74 ) -> 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
|
75 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
|
76 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
|
77 } |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
78 |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
79 pub fn read_link( |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
80 &self, |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
81 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
|
82 ) -> Result<PathBuf, HgError> { |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
83 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
|
84 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
|
85 } |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
86 |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
87 pub fn read( |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
88 &self, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
89 relative_path: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
90 ) -> Result<Vec<u8>, HgError> { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
91 let path = self.join(relative_path); |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
92 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
|
93 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
94 |
49485
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
95 /// 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
|
96 pub fn try_read( |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
97 &self, |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
98 relative_path: impl AsRef<Path>, |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
99 ) -> Result<Option<Vec<u8>>, HgError> { |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
100 match self.read(relative_path) { |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
101 Err(e) => match &e { |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
102 HgError::IoError { error, .. } => match error.kind() { |
49914
58074252db3c
rust: run `cargo clippy`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
103 ErrorKind::NotFound => Ok(None), |
49485
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 _ => Err(e), |
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 Ok(v) => Ok(Some(v)), |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
109 } |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
110 } |
ffd4b1f1c9cb
rhg: add sparse support
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48418
diff
changeset
|
111 |
48199
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
112 fn mmap_open_gen( |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
113 &self, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
114 relative_path: impl AsRef<Path>, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
115 ) -> Result<Result<Mmap, FileNotFound>, HgError> { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
116 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
|
117 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
|
118 Err(err) => { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
119 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
|
120 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
|
121 }; |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
122 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
|
123 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
124 Ok(file) => file, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
125 }; |
51864 | 126 // Safety is "enforced" by locks and assuming other processes are |
127 // well-behaved. If any misbehaving or malicious process does touch | |
128 // the index, it could lead to corruption. This is inherent | |
129 // to file-based `mmap`, though some platforms have some ways of | |
130 // mitigating. | |
131 // 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
|
132 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
|
133 .when_reading_file(&path)?; |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
134 Ok(Ok(mmap)) |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
135 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
136 |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
137 pub fn mmap_open_opt( |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
138 &self, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
139 relative_path: impl AsRef<Path>, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
140 ) -> Result<Option<Mmap>, HgError> { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
141 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
|
142 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
143 |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
144 pub fn mmap_open( |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
145 &self, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
146 relative_path: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
147 ) -> Result<Mmap, HgError> { |
48199
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
148 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
|
149 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
|
150 Ok(res) => Ok(res), |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
151 } |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
152 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
153 |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
154 #[cfg(unix)] |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
155 pub fn create_symlink( |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
156 &self, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
157 relative_link_path: impl AsRef<Path>, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
158 target_path: impl AsRef<Path>, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
159 ) -> Result<(), HgError> { |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
160 let link_path = self.join(relative_link_path); |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
161 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
|
162 .when_writing_file(&link_path) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
163 } |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
164 |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
165 /// 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
|
166 /// 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
|
167 /// 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
|
168 /// content, never a partial write. |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
169 pub fn atomic_write( |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
170 &self, |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
171 relative_path: impl AsRef<Path>, |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
172 contents: &[u8], |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
173 ) -> Result<(), HgError> { |
51864 | 174 let mut tmp = tempfile::NamedTempFile::new_in(&self.base) |
175 .when_writing_file(&self.base)?; | |
48418
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
176 tmp.write_all(contents) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
177 .and_then(|()| tmp.flush()) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
178 .when_writing_file(tmp.path())?; |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
179 let path = self.join(relative_path); |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
180 tmp.persist(&path) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
181 .map_err(|e| e.error) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
182 .when_writing_file(&path)?; |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
183 Ok(()) |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
184 } |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
185 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
186 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
187 fn fs_metadata( |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
188 path: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
189 ) -> Result<Option<std::fs::Metadata>, HgError> { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
190 let path = path.as_ref(); |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
191 match std::fs::metadata(path) { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
192 Ok(meta) => Ok(Some(meta)), |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
193 Err(error) => match error.kind() { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
194 // 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
|
195 // 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
|
196 // and propagate any other error. |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
197 ErrorKind::PermissionDenied => Err(error).with_context(|| { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
198 IoErrorContext::ReadingMetadata(path.to_owned()) |
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 _ => Ok(None), |
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 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
203 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
204 |
51864 | 205 /// Writable file object that atomically updates a file |
206 /// | |
207 /// All writes will go to a temporary copy of the original file. Call | |
208 /// [`Self::close`] when you are done writing, and [`Self`] will rename | |
209 /// the temporary copy to the original name, making the changes | |
210 /// visible. If the object is destroyed without being closed, all your | |
211 /// writes are discarded. | |
212 pub struct AtomicFile { | |
213 /// The temporary file to write to | |
214 fp: std::fs::File, | |
215 /// Path of the temp file | |
216 temp_path: PathBuf, | |
217 /// Used when stat'ing the file, is useful only if the target file is | |
218 /// guarded by any lock (e.g. repo.lock or repo.wlock). | |
219 check_ambig: bool, | |
220 /// Path of the target file | |
221 target_name: PathBuf, | |
222 /// Whether the file is open or not | |
223 is_open: bool, | |
224 } | |
225 | |
226 impl AtomicFile { | |
227 pub fn new( | |
228 fp: std::fs::File, | |
229 check_ambig: bool, | |
230 temp_name: PathBuf, | |
231 target_name: PathBuf, | |
232 ) -> Self { | |
233 Self { | |
234 fp, | |
235 check_ambig, | |
236 temp_path: temp_name, | |
237 target_name, | |
238 is_open: true, | |
239 } | |
240 } | |
241 | |
242 /// Write `buf` to the temporary file | |
243 pub fn write_all(&mut self, buf: &[u8]) -> Result<(), std::io::Error> { | |
244 self.fp.write_all(buf) | |
245 } | |
246 | |
247 fn target(&self) -> PathBuf { | |
248 self.temp_path | |
249 .parent() | |
250 .expect("should not be at the filesystem root") | |
251 .join(&self.target_name) | |
252 } | |
253 | |
254 /// Close the temporary file and rename to the target | |
255 pub fn close(mut self) -> Result<(), std::io::Error> { | |
256 self.fp.flush()?; | |
257 let target = self.target(); | |
258 if self.check_ambig { | |
259 if let Ok(stat) = std::fs::metadata(&target) { | |
260 std::fs::rename(&self.temp_path, &target)?; | |
261 let new_stat = std::fs::metadata(&target)?; | |
262 let ctime = new_stat.ctime(); | |
263 let is_ambiguous = ctime == stat.ctime(); | |
264 if is_ambiguous { | |
265 let advanced = | |
266 filetime::FileTime::from_unix_time(ctime + 1, 0); | |
267 filetime::set_file_times(target, advanced, advanced)?; | |
268 } | |
269 } else { | |
270 std::fs::rename(&self.temp_path, target)?; | |
271 } | |
272 } else { | |
273 std::fs::rename(&self.temp_path, target).unwrap(); | |
274 } | |
275 self.is_open = false; | |
276 Ok(()) | |
277 } | |
278 } | |
279 | |
280 impl Drop for AtomicFile { | |
281 fn drop(&mut self) { | |
282 if self.is_open { | |
283 std::fs::remove_file(self.target()).ok(); | |
284 } | |
285 } | |
286 } | |
287 | |
288 /// Abstracts over the VFS to allow for different implementations of the | |
289 /// filesystem layer (like passing one from Python). | |
290 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
|
291 // TODO make `open` readonly and make `open_read` an `open_write` |
51864 | 292 fn open(&self, filename: &Path) -> Result<std::fs::File, HgError>; |
293 fn open_read(&self, filename: &Path) -> Result<std::fs::File, HgError>; | |
294 fn open_check_ambig( | |
295 &self, | |
296 filename: &Path, | |
297 ) -> Result<std::fs::File, HgError>; | |
298 fn create(&self, filename: &Path) -> Result<std::fs::File, HgError>; | |
299 /// Must truncate the new file if exist | |
300 fn create_atomic( | |
301 &self, | |
302 filename: &Path, | |
303 check_ambig: bool, | |
304 ) -> Result<AtomicFile, HgError>; | |
305 fn file_size(&self, file: &File) -> Result<u64, HgError>; | |
306 fn exists(&self, filename: &Path) -> bool; | |
307 fn unlink(&self, filename: &Path) -> Result<(), HgError>; | |
308 fn rename( | |
309 &self, | |
310 from: &Path, | |
311 to: &Path, | |
312 check_ambig: bool, | |
313 ) -> Result<(), HgError>; | |
314 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
|
315 fn base(&self) -> &Path; |
51864 | 316 } |
317 | |
318 /// These methods will need to be implemented once `rhg` (and other) non-Python | |
319 /// users of `hg-core` start doing more on their own, like writing to files. | |
320 impl Vfs for VfsImpl { | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
321 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
|
322 if self.readonly { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
323 return Err(HgError::abort( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
324 "write access in a readonly vfs", |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
325 exit_codes::ABORT, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
326 None, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
327 )); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
328 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
329 // TODO auditpath |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
330 let path = self.base.join(filename); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
331 copy_in_place_if_hardlink(&path)?; |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
332 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
333 OpenOptions::new() |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
334 .create(false) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
335 .create_new(false) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
336 .write(true) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
337 .read(true) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
338 .open(&path) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
339 .when_writing_file(&path) |
51864 | 340 } |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
341 |
51864 | 342 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
|
343 // TODO auditpath |
51864 | 344 let path = self.base.join(filename); |
345 std::fs::File::open(&path).when_reading_file(&path) | |
346 } | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
347 |
51864 | 348 fn open_check_ambig( |
349 &self, | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
350 filename: &Path, |
51864 | 351 ) -> Result<std::fs::File, HgError> { |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
352 if self.readonly { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
353 return Err(HgError::abort( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
354 "write access in a readonly vfs", |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
355 exit_codes::ABORT, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
356 None, |
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 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
359 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
360 let path = self.base.join(filename); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
361 copy_in_place_if_hardlink(&path)?; |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
362 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
363 // TODO auditpath, check ambig |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
364 OpenOptions::new() |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
365 .write(true) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
366 .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
|
367 .create(false) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
368 .open(&path) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
369 .when_reading_file(&path) |
51864 | 370 } |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
371 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
372 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
|
373 if self.readonly { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
374 return Err(HgError::abort( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
375 "write access in a readonly vfs", |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
376 exit_codes::ABORT, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
377 None, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
378 )); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
379 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
380 // TODO auditpath |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
381 let path = self.base.join(filename); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
382 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
|
383 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
|
384 // TODO checkambig (wrap File somehow) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
385 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
386 let file = OpenOptions::new() |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
387 .create(true) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
388 .truncate(true) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
389 .write(true) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
390 .read(true) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
391 .open(&path) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
392 .when_writing_file(&path)?; |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
393 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
394 if let Some(mode) = self.mode { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
395 // 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
|
396 // 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
|
397 // 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
|
398 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
|
399 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
|
400 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
|
401 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
402 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
403 Ok(file) |
51864 | 404 } |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
405 |
51864 | 406 fn create_atomic( |
407 &self, | |
408 _filename: &Path, | |
409 _check_ambig: bool, | |
410 ) -> Result<AtomicFile, HgError> { | |
411 todo!() | |
412 } | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
413 |
51864 | 414 fn file_size(&self, file: &File) -> Result<u64, HgError> { |
415 Ok(file | |
416 .metadata() | |
417 .map_err(|e| { | |
418 HgError::abort( | |
419 format!("Could not get file metadata: {}", e), | |
420 exit_codes::ABORT, | |
421 None, | |
422 ) | |
423 })? | |
424 .size()) | |
425 } | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
426 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
427 fn exists(&self, filename: &Path) -> bool { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
428 self.base.join(filename).exists() |
51864 | 429 } |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
430 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
431 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
|
432 if self.readonly { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
433 return Err(HgError::abort( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
434 "write access in a readonly vfs", |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
435 exit_codes::ABORT, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
436 None, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
437 )); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
438 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
439 let path = self.base.join(filename); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
440 std::fs::remove_file(&path) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
441 .with_context(|| IoErrorContext::RemovingFile(path)) |
51864 | 442 } |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
443 |
51864 | 444 fn rename( |
445 &self, | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
446 from: &Path, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
447 to: &Path, |
51864 | 448 _check_ambig: bool, |
449 ) -> Result<(), HgError> { | |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
450 if self.readonly { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
451 return Err(HgError::abort( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
452 "write access in a readonly vfs", |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
453 exit_codes::ABORT, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
454 None, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
455 )); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
456 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
457 // TODO checkambig |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
458 let from = self.base.join(from); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
459 let to = self.base.join(to); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
460 std::fs::rename(&from, &to) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
461 .with_context(|| IoErrorContext::RenamingFile { from, to }) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
462 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
463 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
464 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
|
465 // TODO checkambig? |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
466 let from = self.base.join(from); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
467 let to = self.base.join(to); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
468 std::fs::copy(&from, &to) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
469 .with_context(|| IoErrorContext::CopyingFile { from, to }) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
470 .map(|_| ()) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
471 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
472 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
473 fn base(&self) -> &Path { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
474 &self.base |
51864 | 475 } |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
476 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
477 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
478 fn fix_directory_permissions( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
479 base: &Path, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
480 path: &Path, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
481 mode: u32, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
482 ) -> Result<(), HgError> { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
483 let mut ancestors = path.ancestors(); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
484 ancestors.next(); // yields the path itself |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
485 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
486 for ancestor in ancestors { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
487 if ancestor == base { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
488 break; |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
489 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
490 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
|
491 std::fs::set_permissions(ancestor, perm) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
492 .when_writing_file(ancestor)?; |
51864 | 493 } |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
494 Ok(()) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
495 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
496 |
52168
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
497 /// A VFS that understands the `fncache` store layout (file encoding), and |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
498 /// adds new entries to the `fncache`. |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
499 /// TODO Only works when using from Python for now. |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
500 pub struct FnCacheVfs { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
501 inner: VfsImpl, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
502 fncache: Box<dyn FnCache>, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
503 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
504 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
505 impl Clone for FnCacheVfs { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
506 fn clone(&self) -> Self { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
507 Self { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
508 inner: self.inner.clone(), |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
509 fncache: dyn_clone::clone_box(&*self.fncache), |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
510 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
511 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
512 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
513 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
514 impl FnCacheVfs { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
515 pub fn new( |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
516 base: PathBuf, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
517 readonly: bool, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
518 fncache: Box<dyn FnCache>, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
519 ) -> Self { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
520 let inner = VfsImpl::new(base, readonly); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
521 Self { inner, fncache } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
522 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
523 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
524 fn maybe_add_to_fncache( |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
525 &self, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
526 filename: &Path, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
527 encoded_path: &Path, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
528 ) -> Result<(), HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
529 let relevant_file = (filename.starts_with("data/") |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
530 || filename.starts_with("meta/")) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
531 && is_revlog_file(filename); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
532 if relevant_file { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
533 let not_load = !self.fncache.is_loaded() |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
534 && (self.exists(filename) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
535 && self |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
536 .inner |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
537 .join(encoded_path) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
538 .metadata() |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
539 .when_reading_file(encoded_path)? |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
540 .size() |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
541 != 0); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
542 if !not_load { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
543 self.fncache.add(filename); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
544 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
545 }; |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
546 Ok(()) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
547 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
548 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
549 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
550 impl Vfs for FnCacheVfs { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
551 fn open(&self, filename: &Path) -> Result<std::fs::File, HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
552 let encoded = path_encode(&get_bytes_from_path(filename)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
553 let encoded_path = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
554 self.maybe_add_to_fncache(filename, encoded_path)?; |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
555 self.inner.open(encoded_path) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
556 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
557 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
558 fn open_read(&self, filename: &Path) -> Result<std::fs::File, HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
559 let encoded = path_encode(&get_bytes_from_path(filename)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
560 let filename = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
561 self.inner.open_read(filename) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
562 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
563 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
564 fn open_check_ambig( |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
565 &self, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
566 filename: &Path, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
567 ) -> Result<std::fs::File, HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
568 let encoded = path_encode(&get_bytes_from_path(filename)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
569 let filename = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
570 self.inner.open_check_ambig(filename) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
571 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
572 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
573 fn create(&self, filename: &Path) -> Result<std::fs::File, HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
574 let encoded = path_encode(&get_bytes_from_path(filename)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
575 let encoded_path = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
576 self.maybe_add_to_fncache(filename, encoded_path)?; |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
577 self.inner.create(encoded_path) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
578 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
579 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
580 fn create_atomic( |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
581 &self, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
582 filename: &Path, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
583 check_ambig: bool, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
584 ) -> Result<AtomicFile, HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
585 let encoded = path_encode(&get_bytes_from_path(filename)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
586 let filename = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
587 self.inner.create_atomic(filename, check_ambig) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
588 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
589 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
590 fn file_size(&self, file: &File) -> Result<u64, HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
591 self.inner.file_size(file) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
592 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
593 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
594 fn exists(&self, filename: &Path) -> bool { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
595 let encoded = path_encode(&get_bytes_from_path(filename)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
596 let filename = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
597 self.inner.exists(filename) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
598 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
599 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
600 fn unlink(&self, filename: &Path) -> Result<(), HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
601 let encoded = path_encode(&get_bytes_from_path(filename)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
602 let filename = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
603 self.inner.unlink(filename) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
604 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
605 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
606 fn rename( |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
607 &self, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
608 from: &Path, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
609 to: &Path, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
610 check_ambig: bool, |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
611 ) -> Result<(), HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
612 let encoded = path_encode(&get_bytes_from_path(from)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
613 let from = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
614 let encoded = path_encode(&get_bytes_from_path(to)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
615 let to = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
616 self.inner.rename(from, to, check_ambig) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
617 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
618 |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
619 fn copy(&self, from: &Path, to: &Path) -> Result<(), HgError> { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
620 let encoded = path_encode(&get_bytes_from_path(from)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
621 let from = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
622 let encoded = path_encode(&get_bytes_from_path(to)); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
623 let to = get_path_from_bytes(&encoded); |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
624 self.inner.copy(from, to) |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
625 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
626 fn base(&self) -> &Path { |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
627 self.inner.base() |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
628 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
629 } |
067ec8574c33
hg-core: add FnCacheVFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
630 |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
631 /// 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
|
632 /// 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
|
633 /// 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
|
634 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
|
635 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
|
636 if metadata.nlink() > 0 { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
637 // 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
|
638 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
|
639 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
|
640 let tmpfile = tmpdir.join(name); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
641 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
|
642 .with_context(|| IoErrorContext::CopyingFile { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
643 from: path.to_owned(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
644 to: tmpfile.to_owned(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
645 })?; |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
646 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
|
647 IoErrorContext::CopyingFile { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
648 from: path.to_owned(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
649 to: tmpfile.to_owned(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
650 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
651 })?; |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
652 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
|
653 IoErrorContext::RenamingFile { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
654 from: tmpfile, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
655 to: path.to_owned(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
656 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
657 })?; |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
658 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
659 Ok(()) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
660 } |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
661 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
662 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
|
663 path.as_ref() |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
664 .extension() |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
665 .map(|ext| { |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
666 ["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
|
667 .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
|
668 }) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52157
diff
changeset
|
669 .unwrap_or(false) |
51864 | 670 } |
671 | |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
672 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
|
673 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
|
674 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
675 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
676 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
|
677 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
|
678 } |
50180
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
679 |
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
680 /// 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
|
681 /// 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
|
682 #[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
|
683 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
|
684 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
|
685 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
|
686 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
|
687 |
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
688 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
|
689 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
|
690 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
|
691 }; |
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
692 |
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
693 unsafe { |
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
694 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
|
695 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
|
696 |
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
697 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
|
698 } |
be019ac8c1e4
dirstate-v2: don't mmap the data file when on NFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49485
diff
changeset
|
699 } |
50274
0cc19a53cef4
rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
50252
diff
changeset
|
700 |
0cc19a53cef4
rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
50252
diff
changeset
|
701 /// 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
|
702 /// 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
|
703 /// 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
|
704 /// _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
|
705 /// all |
0cc19a53cef4
rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
50252
diff
changeset
|
706 #[cfg(not(target_os = "linux"))] |
0cc19a53cef4
rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
50252
diff
changeset
|
707 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
|
708 false |
0cc19a53cef4
rust: fix building on macOS (issue6801)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
50252
diff
changeset
|
709 } |