Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/vfs.rs @ 48546:e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
When status is unsure based on `stat()` and the dirstate if a file is clean
or modified, we need to compare it against the filelog.
This comparison can skip looking at contents if the lengths differ.
This changeset optimize this further to deduce what we can about the length
if the filelog without decompressing it or resolving deltas.
Differential Revision: https://phab.mercurial-scm.org/D11965
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Fri, 07 Jan 2022 14:40:21 +0100 |
parents | abeae090ce67 |
children | ffd4b1f1c9cb |
rev | line source |
---|---|
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
1 use crate::errors::{HgError, IoErrorContext, IoResultExt}; |
47955
e834b79def74
rust: Switch to the memmap2-rs crate
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
2 use memmap2::{Mmap, MmapOptions}; |
48418
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
3 use std::io::{ErrorKind, Write}; |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
4 use std::path::{Path, PathBuf}; |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
5 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
6 /// Filesystem access abstraction for the contents of a given "base" diretory |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
7 #[derive(Clone, Copy)] |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
8 pub struct Vfs<'a> { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
9 pub(crate) base: &'a Path, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
10 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
11 |
48199
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
12 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
|
13 |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
14 impl Vfs<'_> { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
15 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
|
16 self.base.join(relative_path) |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
17 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
18 |
48345
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
19 pub fn symlink_metadata( |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
20 &self, |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
21 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
|
22 ) -> 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
|
23 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
|
24 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
|
25 } |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
26 |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
27 pub fn read_link( |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
28 &self, |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
29 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
|
30 ) -> Result<PathBuf, HgError> { |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
31 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
|
32 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
|
33 } |
d5a91701f7dc
rhg: Fix status desambiguation of symlinks and executable files
Simon Sapin <simon.sapin@octobus.net>
parents:
48199
diff
changeset
|
34 |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
35 pub fn read( |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
36 &self, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
37 relative_path: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
38 ) -> Result<Vec<u8>, HgError> { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
39 let path = self.join(relative_path); |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
40 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
|
41 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
42 |
48199
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
43 fn mmap_open_gen( |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
44 &self, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
45 relative_path: impl AsRef<Path>, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
46 ) -> Result<Result<Mmap, FileNotFound>, HgError> { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
47 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
|
48 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
|
49 Err(err) => { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
50 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
|
51 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
|
52 }; |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
53 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
|
54 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
55 Ok(file) => file, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
56 }; |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
57 // TODO: what are the safety requirements here? |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
58 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
|
59 .when_reading_file(&path)?; |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
60 Ok(Ok(mmap)) |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
61 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
62 |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
63 pub fn mmap_open_opt( |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
64 &self, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
65 relative_path: impl AsRef<Path>, |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
66 ) -> Result<Option<Mmap>, HgError> { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
67 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
|
68 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
69 |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
70 pub fn mmap_open( |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
71 &self, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
72 relative_path: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
73 ) -> Result<Mmap, HgError> { |
48199
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
74 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
|
75 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
|
76 Ok(res) => Ok(res), |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47955
diff
changeset
|
77 } |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
78 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
79 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
80 pub fn rename( |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
81 &self, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
82 relative_from: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
83 relative_to: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
84 ) -> Result<(), HgError> { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
85 let from = self.join(relative_from); |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
86 let to = self.join(relative_to); |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
87 std::fs::rename(&from, &to) |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
88 .with_context(|| IoErrorContext::RenamingFile { from, to }) |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
89 } |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
90 |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
91 pub fn remove_file( |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
92 &self, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
93 relative_path: impl AsRef<Path>, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
94 ) -> Result<(), HgError> { |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
95 let path = self.join(relative_path); |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
96 std::fs::remove_file(&path) |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
97 .with_context(|| IoErrorContext::RemovingFile(path)) |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
98 } |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
99 |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
100 #[cfg(unix)] |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
101 pub fn create_symlink( |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
102 &self, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
103 relative_link_path: impl AsRef<Path>, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
104 target_path: impl AsRef<Path>, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
105 ) -> Result<(), HgError> { |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
106 let link_path = self.join(relative_link_path); |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
107 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
|
108 .when_writing_file(&link_path) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
109 } |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
110 |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
111 /// 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
|
112 /// 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
|
113 /// 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
|
114 /// content, never a partial write. |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
115 pub fn atomic_write( |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
116 &self, |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
117 relative_path: impl AsRef<Path>, |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
118 contents: &[u8], |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
119 ) -> Result<(), HgError> { |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
120 let mut tmp = tempfile::NamedTempFile::new_in(self.base) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
121 .when_writing_file(self.base)?; |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
122 tmp.write_all(contents) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
123 .and_then(|()| tmp.flush()) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
124 .when_writing_file(tmp.path())?; |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
125 let path = self.join(relative_path); |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
126 tmp.persist(&path) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
127 .map_err(|e| e.error) |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
128 .when_writing_file(&path)?; |
abeae090ce67
rust: Add Vfs::write_atomic
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
129 Ok(()) |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48345
diff
changeset
|
130 } |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
131 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
132 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
133 fn fs_metadata( |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
134 path: impl AsRef<Path>, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
135 ) -> Result<Option<std::fs::Metadata>, HgError> { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
136 let path = path.as_ref(); |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
137 match std::fs::metadata(path) { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
138 Ok(meta) => Ok(Some(meta)), |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
139 Err(error) => match error.kind() { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
140 // 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
|
141 // 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
|
142 // and propagate any other error. |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
143 ErrorKind::PermissionDenied => Err(error).with_context(|| { |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
144 IoErrorContext::ReadingMetadata(path.to_owned()) |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
145 }), |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
146 _ => Ok(None), |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
147 }, |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
148 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
149 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
150 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
151 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
|
152 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
|
153 } |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
154 |
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
155 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
|
156 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
|
157 } |