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