Show More
@@ -47,8 +47,8 b' pub fn normalize_for_display_bytes(path:' | |||||
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 |
/// |
|
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 | |
@@ -74,7 +74,9 b' pub fn absolute(path: impl AsRef<Path>) ' | |||||
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 => { | |
@@ -95,9 +97,10 b' pub fn remove_file<P: AsRef<Path>>(path:' | |||||
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 |
|
100 | /// On Windows, removing a file can fail for various reasons, including if the | |
99 |
/// mapped. This can happen when the repository is accessed |
|
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<()> { | |
@@ -116,12 +119,14 b' pub fn remove_file<P: AsRef<Path>>(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 |
|
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 |
|
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(()), | |
@@ -135,28 +140,29 b' pub fn create_dir(path: impl AsRef<Path>' | |||||
135 | } |
|
140 | } | |
136 | } |
|
141 | } | |
137 |
|
142 | |||
138 |
/// Expand the user's home directory and any environment variables references |
|
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 |
|
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` | |
|
150 | /// crate. In particular: | |||
145 | /// |
|
151 | /// | |
146 |
/// - If a reference to an environment variable is missing or invalid, the |
|
152 | /// - If a reference to an environment variable is missing or invalid, the | |
147 |
/// is left unchanged in the resulting path rather than emitting an |
|
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 |
|
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>, | |
@@ -238,7 +244,10 b' mod tests {' | |||||
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("/")); |
General Comments 0
You need to be logged in to leave comments.
Login now