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
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;
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
16 #[derive(Clone)]
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
17 pub struct VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
126 // 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
127 // 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
128 // 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
129 // 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
130 // mitigating.
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
174 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
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
205 /// Writable file object that atomically updates a file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
206 ///
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
207 /// 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
208 /// [`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
209 /// 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
210 /// 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
211 /// writes are discarded.
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
212 pub struct AtomicFile {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
213 /// The temporary file to write to
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
214 fp: std::fs::File,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
215 /// Path of the temp file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
216 temp_path: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
217 /// 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
218 /// 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
219 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
220 /// Path of the target file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
221 target_name: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
222 /// Whether the file is open or not
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
223 is_open: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
224 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
225
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
226 impl AtomicFile {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
227 pub fn new(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
228 fp: std::fs::File,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
229 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
230 temp_name: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
231 target_name: PathBuf,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
232 ) -> Self {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
233 Self {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
234 fp,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
235 check_ambig,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
236 temp_path: temp_name,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
237 target_name,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
238 is_open: true,
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 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
241
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
242 /// Write `buf` to the temporary file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
243 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
244 self.fp.write_all(buf)
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
245 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
246
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
247 fn target(&self) -> PathBuf {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
248 self.temp_path
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
249 .parent()
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
250 .expect("should not be at the filesystem root")
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
251 .join(&self.target_name)
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
252 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
253
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
254 /// 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
255 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
256 self.fp.flush()?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
257 let target = self.target();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
258 if self.check_ambig {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
259 if let Ok(stat) = std::fs::metadata(&target) {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
260 std::fs::rename(&self.temp_path, &target)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
261 let new_stat = std::fs::metadata(&target)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
262 let ctime = new_stat.ctime();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
263 let is_ambiguous = ctime == stat.ctime();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
264 if is_ambiguous {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
265 let advanced =
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
266 filetime::FileTime::from_unix_time(ctime + 1, 0);
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
267 filetime::set_file_times(target, advanced, advanced)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
268 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
269 } else {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
270 std::fs::rename(&self.temp_path, target)?;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
271 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
272 } else {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
273 std::fs::rename(&self.temp_path, target).unwrap();
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
274 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
275 self.is_open = false;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
276 Ok(())
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 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
279
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
280 impl Drop for AtomicFile {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
281 fn drop(&mut self) {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
282 if self.is_open {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
283 std::fs::remove_file(self.target()).ok();
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 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
287
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
288 /// 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
289 /// filesystem layer (like passing one from Python).
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
292 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
293 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
294 fn open_check_ambig(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
295 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
296 filename: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
297 ) -> Result<std::fs::File, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
298 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
299 /// Must truncate the new file if exist
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
300 fn create_atomic(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
301 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
302 filename: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
303 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
304 ) -> Result<AtomicFile, HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
305 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
306 fn exists(&self, filename: &Path) -> bool;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
307 fn unlink(&self, filename: &Path) -> Result<(), HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
308 fn rename(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
309 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
310 from: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
311 to: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
312 check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
313 ) -> Result<(), HgError>;
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
316 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
317
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
318 /// 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
319 /// 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
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
340 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
341
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
344 let path = self.base.join(filename);
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
345 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
346 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
347
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
348 fn open_check_ambig(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
404 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
405
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
406 fn create_atomic(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
407 &self,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
408 _filename: &Path,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
409 _check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
410 ) -> Result<AtomicFile, HgError> {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
411 todo!()
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
412 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
413
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
414 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
415 Ok(file
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
416 .metadata()
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
417 .map_err(|e| {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
418 HgError::abort(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
419 format!("Could not get file metadata: {}", e),
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
420 exit_codes::ABORT,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
421 None,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
422 )
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
423 })?
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
424 .size())
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
442 }
52167
7be39c5110c9 hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52157
diff changeset
443
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
444 fn rename(
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
448 _check_ambig: bool,
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
670 }
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50274
diff changeset
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 }