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(),