Mercurial > public > mercurial-scm > hg
comparison rust/hg-core/src/utils/path.rs @ 44068:4b953cb17612
hg-core: rustfmt path.rs
The file as vendored does not conform to our source formatting
conventions. Let's reformat it so it does.
# skip-blame automated code reformatting
Differential Revision: https://phab.mercurial-scm.org/D7580
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 07 Dec 2019 13:13:48 -0800 |
parents | 6a1729ed223d |
children |
comparison
equal
deleted
inserted
replaced
44067:6a1729ed223d | 44068:4b953cb17612 |
---|---|
45 /// This function does not access the filesystem. Therefore it can behave | 45 /// This function does not access the filesystem. Therefore it can behave |
46 /// differently from the kernel or other library functions in corner cases. | 46 /// differently from the kernel or other library functions in corner cases. |
47 /// For example: | 47 /// For example: |
48 /// | 48 /// |
49 /// - On some systems with symlink support, `foo/bar/..` and `foo` can be | 49 /// - On some systems with symlink support, `foo/bar/..` and `foo` can be |
50 /// different as seen by the kernel, if `foo/bar` is a symlink. This | 50 /// different as seen by the kernel, if `foo/bar` is a symlink. This function |
51 /// function always returns `foo` in this case. | 51 /// always returns `foo` in this case. |
52 /// - On Windows, the official normalization rules are much more complicated. | 52 /// - On Windows, the official normalization rules are much more complicated. |
53 /// See https://github.com/rust-lang/rust/pull/47363#issuecomment-357069527. | 53 /// See https://github.com/rust-lang/rust/pull/47363#issuecomment-357069527. |
54 /// For example, this function cannot translate "drive relative" path like | 54 /// For example, this function cannot translate "drive relative" path like |
55 /// "X:foo" to an absolute path. | 55 /// "X:foo" to an absolute path. |
56 /// | 56 /// |
72 } | 72 } |
73 | 73 |
74 let mut result = PathBuf::new(); | 74 let mut result = PathBuf::new(); |
75 for component in path.components() { | 75 for component in path.components() { |
76 match component { | 76 match component { |
77 Component::Normal(_) | Component::RootDir | Component::Prefix(_) => { | 77 Component::Normal(_) |
78 | Component::RootDir | |
79 | Component::Prefix(_) => { | |
78 result.push(component); | 80 result.push(component); |
79 } | 81 } |
80 Component::ParentDir => { | 82 Component::ParentDir => { |
81 result.pop(); | 83 result.pop(); |
82 } | 84 } |
93 Ok(()) | 95 Ok(()) |
94 } | 96 } |
95 | 97 |
96 /// Remove the file pointed by `path`. | 98 /// Remove the file pointed by `path`. |
97 /// | 99 /// |
98 /// On Windows, removing a file can fail for various reasons, including if the file is memory | 100 /// On Windows, removing a file can fail for various reasons, including if the |
99 /// mapped. This can happen when the repository is accessed concurrently while a background task is | 101 /// file is memory mapped. This can happen when the repository is accessed |
100 /// trying to remove a packfile. To solve this, we can rename the file before trying to remove it. | 102 /// concurrently while a background task is trying to remove a packfile. To |
103 /// solve this, we can rename the file before trying to remove it. | |
101 /// If the remove operation fails, a future repack will clean it up. | 104 /// If the remove operation fails, a future repack will clean it up. |
102 #[cfg(not(unix))] | 105 #[cfg(not(unix))] |
103 pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<()> { | 106 pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<()> { |
104 let path = path.as_ref(); | 107 let path = path.as_ref(); |
105 let extension = path | 108 let extension = path |
114 .tempfile_in(path.parent().unwrap())? | 117 .tempfile_in(path.parent().unwrap())? |
115 .into_temp_path(); | 118 .into_temp_path(); |
116 | 119 |
117 rename(path, &dest_path)?; | 120 rename(path, &dest_path)?; |
118 | 121 |
119 // Ignore errors when removing the file, it will be cleaned up at a later time. | 122 // Ignore errors when removing the file, it will be cleaned up at a later |
123 // time. | |
120 let _ = fs_remove_file(dest_path); | 124 let _ = fs_remove_file(dest_path); |
121 Ok(()) | 125 Ok(()) |
122 } | 126 } |
123 | 127 |
124 /// Create the directory and ignore failures when a directory of the same name already exists. | 128 /// Create the directory and ignore failures when a directory of the same name |
129 /// already exists. | |
125 pub fn create_dir(path: impl AsRef<Path>) -> io::Result<()> { | 130 pub fn create_dir(path: impl AsRef<Path>) -> io::Result<()> { |
126 match fs::create_dir(path.as_ref()) { | 131 match fs::create_dir(path.as_ref()) { |
127 Ok(()) => Ok(()), | 132 Ok(()) => Ok(()), |
128 Err(e) => { | 133 Err(e) => { |
129 if e.kind() == ErrorKind::AlreadyExists && path.as_ref().is_dir() { | 134 if e.kind() == ErrorKind::AlreadyExists && path.as_ref().is_dir() { |
133 } | 138 } |
134 } | 139 } |
135 } | 140 } |
136 } | 141 } |
137 | 142 |
138 /// Expand the user's home directory and any environment variables references in | 143 /// Expand the user's home directory and any environment variables references |
139 /// the given path. | 144 /// in the given path. |
140 /// | 145 /// |
141 /// This function is designed to emulate the behavior of Mercurial's `util.expandpath` | 146 /// This function is designed to emulate the behavior of Mercurial's |
142 /// function, which in turn uses Python's `os.path.expand{user,vars}` functions. This | 147 /// `util.expandpath` function, which in turn uses Python's |
143 /// results in behavior that is notably different from the default expansion behavior | 148 /// `os.path.expand{user,vars}` functions. This results in behavior that is |
144 /// of the `shellexpand` crate. In particular: | 149 /// notably different from the default expansion behavior of the `shellexpand` |
145 /// | 150 /// crate. In particular: |
146 /// - If a reference to an environment variable is missing or invalid, the reference | 151 /// |
147 /// is left unchanged in the resulting path rather than emitting an error. | 152 /// - If a reference to an environment variable is missing or invalid, the |
153 /// reference is left unchanged in the resulting path rather than emitting an | |
154 /// error. | |
148 /// | 155 /// |
149 /// - Home directory expansion explicitly happens after environment variable | 156 /// - Home directory expansion explicitly happens after environment variable |
150 /// expansion, meaning that if an environment variable is expanded into a | 157 /// expansion, meaning that if an environment variable is expanded into a |
151 /// string starting with a tilde (`~`), the tilde will be expanded into the | 158 /// string starting with a tilde (`~`), the tilde will be expanded into the |
152 /// user's home directory. | 159 /// user's home directory. |
153 /// | |
154 pub fn expand_path(path: impl AsRef<str>) -> PathBuf { | 160 pub fn expand_path(path: impl AsRef<str>) -> PathBuf { |
155 expand_path_impl(path.as_ref(), |k| env::var(k).ok(), dirs::home_dir) | 161 expand_path_impl(path.as_ref(), |k| env::var(k).ok(), dirs::home_dir) |
156 } | 162 } |
157 | 163 |
158 /// Same as `expand_path` but explicitly takes closures for environment variable | 164 /// Same as `expand_path` but explicitly takes closures for environment |
159 /// and home directory lookup for the sake of testability. | 165 /// variable and home directory lookup for the sake of testability. |
160 fn expand_path_impl<E, H>(path: &str, getenv: E, homedir: H) -> PathBuf | 166 fn expand_path_impl<E, H>(path: &str, getenv: E, homedir: H) -> PathBuf |
161 where | 167 where |
162 E: FnMut(&str) -> Option<String>, | 168 E: FnMut(&str) -> Option<String>, |
163 H: FnOnce() -> Option<PathBuf>, | 169 H: FnOnce() -> Option<PathBuf>, |
164 { | 170 { |
236 mod unix { | 242 mod unix { |
237 use super::*; | 243 use super::*; |
238 | 244 |
239 #[test] | 245 #[test] |
240 fn test_absolute_fullpath() { | 246 fn test_absolute_fullpath() { |
241 assert_eq!(absolute("/a/./b\\c/../d/.").unwrap(), Path::new("/a/d")); | 247 assert_eq!( |
248 absolute("/a/./b\\c/../d/.").unwrap(), | |
249 Path::new("/a/d") | |
250 ); | |
242 assert_eq!(absolute("/a/../../../../b").unwrap(), Path::new("/b")); | 251 assert_eq!(absolute("/a/../../../../b").unwrap(), Path::new("/b")); |
243 assert_eq!(absolute("/../../..").unwrap(), Path::new("/")); | 252 assert_eq!(absolute("/../../..").unwrap(), Path::new("/")); |
244 assert_eq!(absolute("/../../../").unwrap(), Path::new("/")); | 253 assert_eq!(absolute("/../../../").unwrap(), Path::new("/")); |
245 assert_eq!( | 254 assert_eq!( |
246 absolute("//foo///bar//baz").unwrap(), | 255 absolute("//foo///bar//baz").unwrap(), |