Mercurial > public > mercurial-scm > hg
comparison rust/hg-core/src/utils/files.rs @ 42957:7a01778bc7b7
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf
Differential Revision: https://phab.mercurial-scm.org/D6774
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Sun, 01 Sep 2019 20:53:14 +0200 |
parents | b1b984f9c01d |
children | 98d996a138de |
comparison
equal
deleted
inserted
replaced
42956:3fe40dd6355d | 42957:7a01778bc7b7 |
---|---|
7 // This software may be used and distributed according to the terms of the | 7 // This software may be used and distributed according to the terms of the |
8 // GNU General Public License version 2 or any later version. | 8 // GNU General Public License version 2 or any later version. |
9 | 9 |
10 //! Functions for fiddling with files. | 10 //! Functions for fiddling with files. |
11 | 11 |
12 use crate::utils::hg_path::{HgPath, HgPathBuf}; | |
12 use std::iter::FusedIterator; | 13 use std::iter::FusedIterator; |
14 | |
13 use std::path::Path; | 15 use std::path::Path; |
14 | 16 |
15 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { | 17 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { |
16 let os_str; | 18 let os_str; |
17 #[cfg(unix)] | 19 #[cfg(unix)] |
21 } | 23 } |
22 #[cfg(windows)] | 24 #[cfg(windows)] |
23 { | 25 { |
24 // TODO: convert from Windows MBCS (ANSI encoding) to WTF8. | 26 // TODO: convert from Windows MBCS (ANSI encoding) to WTF8. |
25 // Perhaps, the return type would have to be Result<PathBuf>. | 27 // Perhaps, the return type would have to be Result<PathBuf>. |
26 use std::os::windows::ffi::OsStrExt; | 28 unimplemented!() |
27 os_str = std::ffi::OsString::from_wide(bytes); | |
28 } | 29 } |
29 | 30 |
30 Path::new(os_str) | 31 Path::new(os_str) |
31 } | 32 } |
32 | 33 |
33 /// An iterator over repository path yielding itself and its ancestors. | 34 /// An iterator over repository path yielding itself and its ancestors. |
34 #[derive(Copy, Clone, Debug)] | 35 #[derive(Copy, Clone, Debug)] |
35 pub struct Ancestors<'a> { | 36 pub struct Ancestors<'a> { |
36 next: Option<&'a [u8]>, | 37 next: Option<&'a HgPath>, |
37 } | 38 } |
38 | 39 |
39 impl<'a> Iterator for Ancestors<'a> { | 40 impl<'a> Iterator for Ancestors<'a> { |
40 // if we had an HgPath type, this would yield &'a HgPath | 41 type Item = &'a HgPath; |
41 type Item = &'a [u8]; | |
42 | 42 |
43 fn next(&mut self) -> Option<Self::Item> { | 43 fn next(&mut self) -> Option<Self::Item> { |
44 let next = self.next; | 44 let next = self.next; |
45 self.next = match self.next { | 45 self.next = match self.next { |
46 Some(s) if s.is_empty() => None, | 46 Some(s) if s.is_empty() => None, |
47 Some(s) => { | 47 Some(s) => { |
48 let p = s.iter().rposition(|&c| c == b'/').unwrap_or(0); | 48 let p = s.bytes().rposition(|c| *c == b'/').unwrap_or(0); |
49 Some(&s[..p]) | 49 Some(HgPath::new(&s.as_bytes()[..p])) |
50 } | 50 } |
51 None => None, | 51 None => None, |
52 }; | 52 }; |
53 next | 53 next |
54 } | 54 } |
61 /// | 61 /// |
62 /// The path is separated by '/', and must not start with '/'. | 62 /// The path is separated by '/', and must not start with '/'. |
63 /// | 63 /// |
64 /// The path itself isn't included unless it is b"" (meaning the root | 64 /// The path itself isn't included unless it is b"" (meaning the root |
65 /// directory.) | 65 /// directory.) |
66 pub fn find_dirs<'a>(path: &'a [u8]) -> Ancestors<'a> { | 66 pub fn find_dirs<'a>(path: &'a HgPath) -> Ancestors<'a> { |
67 let mut dirs = Ancestors { next: Some(path) }; | 67 let mut dirs = Ancestors { next: Some(path) }; |
68 if !path.is_empty() { | 68 if !path.is_empty() { |
69 dirs.next(); // skip itself | 69 dirs.next(); // skip itself |
70 } | 70 } |
71 dirs | 71 dirs |
72 } | 72 } |
73 | 73 |
74 /// TODO improve handling of utf8 file names. Our overall strategy for | 74 /// TODO more than ASCII? |
75 /// filenames has to be revisited anyway, since Windows is UTF-16. | 75 pub fn normalize_case(path: &HgPath) -> HgPathBuf { |
76 pub fn normalize_case(bytes: &[u8]) -> Vec<u8> { | |
77 #[cfg(windows)] // NTFS compares via upper() | 76 #[cfg(windows)] // NTFS compares via upper() |
78 return bytes.to_ascii_uppercase(); | 77 return path.to_ascii_uppercase(); |
79 #[cfg(unix)] | 78 #[cfg(unix)] |
80 bytes.to_ascii_lowercase() | 79 path.to_ascii_lowercase() |
81 } | 80 } |
82 | 81 |
83 #[cfg(test)] | 82 #[cfg(test)] |
84 mod tests { | 83 mod tests { |
84 use super::*; | |
85 | |
85 #[test] | 86 #[test] |
86 fn find_dirs_some() { | 87 fn find_dirs_some() { |
87 let mut dirs = super::find_dirs(b"foo/bar/baz"); | 88 let mut dirs = super::find_dirs(HgPath::new(b"foo/bar/baz")); |
88 assert_eq!(dirs.next(), Some(b"foo/bar".as_ref())); | 89 assert_eq!(dirs.next(), Some(HgPath::new(b"foo/bar"))); |
89 assert_eq!(dirs.next(), Some(b"foo".as_ref())); | 90 assert_eq!(dirs.next(), Some(HgPath::new(b"foo"))); |
90 assert_eq!(dirs.next(), Some(b"".as_ref())); | 91 assert_eq!(dirs.next(), Some(HgPath::new(b""))); |
91 assert_eq!(dirs.next(), None); | 92 assert_eq!(dirs.next(), None); |
92 assert_eq!(dirs.next(), None); | 93 assert_eq!(dirs.next(), None); |
93 } | 94 } |
94 | 95 |
95 #[test] | 96 #[test] |
96 fn find_dirs_empty() { | 97 fn find_dirs_empty() { |
97 // looks weird, but mercurial.util.finddirs(b"") yields b"" | 98 // looks weird, but mercurial.util.finddirs(b"") yields b"" |
98 let mut dirs = super::find_dirs(b""); | 99 let mut dirs = super::find_dirs(HgPath::new(b"")); |
99 assert_eq!(dirs.next(), Some(b"".as_ref())); | 100 assert_eq!(dirs.next(), Some(HgPath::new(b""))); |
100 assert_eq!(dirs.next(), None); | 101 assert_eq!(dirs.next(), None); |
101 assert_eq!(dirs.next(), None); | 102 assert_eq!(dirs.next(), None); |
102 } | 103 } |
103 } | 104 } |