about summary refs log tree commit diff
path: root/src/libextra
diff options
context:
space:
mode:
authorKevin Ballard <kevin@sb.org>2013-09-26 17:21:59 -0700
committerKevin Ballard <kevin@sb.org>2013-10-15 21:56:54 -0700
commit73d3d00ec437f87ac665b4e4da3bedec8ce4f9ef (patch)
tree7050b2b93e3c58d7766e9aecd7e973ea88d9210e /src/libextra
parent6741241f4046aea4014b1a23618593fb481c8606 (diff)
downloadrust-73d3d00ec437f87ac665b4e4da3bedec8ce4f9ef.tar.gz
rust-73d3d00ec437f87ac665b4e4da3bedec8ce4f9ef.zip
path2: Replace the path module outright
Remove the old path.
Rename path2 to path.
Update all clients for the new path.

Also make some miscellaneous changes to the Path APIs to help the
adoption process.
Diffstat (limited to 'src/libextra')
-rw-r--r--src/libextra/fileinput.rs12
-rw-r--r--src/libextra/glob.rs83
-rw-r--r--src/libextra/tempfile.rs2
-rw-r--r--src/libextra/terminfo/searcher.rs42
-rw-r--r--src/libextra/test.rs12
-rw-r--r--src/libextra/workcache.rs17
6 files changed, 104 insertions, 64 deletions
diff --git a/src/libextra/fileinput.rs b/src/libextra/fileinput.rs
index bf3fe4b39b2..08d1222ff46 100644
--- a/src/libextra/fileinput.rs
+++ b/src/libextra/fileinput.rs
@@ -362,7 +362,7 @@ pub fn make_path_option_vec(vec: &[~str], stdin_hyphen : bool) -> ~[Option<Path>
         if stdin_hyphen && "-" == *str {
             None
         } else {
-            Some(Path(*str))
+            Some(Path::from_str(*str))
         }
     }).collect()
 }
@@ -435,14 +435,14 @@ mod test {
     fn test_make_path_option_vec() {
         let strs = [~"some/path",
                     ~"some/other/path"];
-        let paths = ~[Some(Path("some/path")),
-                      Some(Path("some/other/path"))];
+        let paths = ~[Some(Path::from_str("some/path")),
+                      Some(Path::from_str("some/other/path"))];
 
         assert_eq!(make_path_option_vec(strs, true), paths.clone());
         assert_eq!(make_path_option_vec(strs, false), paths);
 
         assert_eq!(make_path_option_vec([~"-"], true), ~[None]);
-        assert_eq!(make_path_option_vec([~"-"], false), ~[Some(Path("-"))]);
+        assert_eq!(make_path_option_vec([~"-"], false), ~[Some(Path::from_str("-"))]);
     }
 
     #[test]
@@ -567,9 +567,9 @@ mod test {
     #[test]
     fn test_no_trailing_newline() {
         let f1 =
-            Some(Path("tmp/lib-fileinput-test-no-trailing-newline-1.tmp"));
+            Some(Path::from_str("tmp/lib-fileinput-test-no-trailing-newline-1.tmp"));
         let f2 =
-            Some(Path("tmp/lib-fileinput-test-no-trailing-newline-2.tmp"));
+            Some(Path::from_str("tmp/lib-fileinput-test-no-trailing-newline-2.tmp"));
 
         {
             let mut wr = file::open(f1.get_ref(), io::CreateOrTruncate,
diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs
index 112ea142189..e398f41c467 100644
--- a/src/libextra/glob.rs
+++ b/src/libextra/glob.rs
@@ -35,7 +35,7 @@ pub struct GlobIterator {
     priv root: Path,
     priv dir_patterns: ~[Pattern],
     priv options: MatchOptions,
-    priv todo: ~[Path]
+    priv todo: ~[(Path,uint)]
 }
 
 /**
@@ -80,18 +80,32 @@ pub fn glob(pattern: &str) -> GlobIterator {
  * Paths are yielded in alphabetical order, as absolute paths.
  */
 pub fn glob_with(pattern: &str, options: MatchOptions) -> GlobIterator {
+    #[cfg(windows)]
+    use is_sep = std::path::windows::is_sep2;
+    #[cfg(not(windows))]
+    fn is_sep(c: char) -> bool { c <= '\x7F' && ::std::path::posix::is_sep(&(c as u8)) }
+    #[cfg(windows)]
+    fn check_windows_verbatim(p: &Path) -> bool { p.is_verbatim() }
+    #[cfg(not(windows))]
+    fn check_windows_verbatim(_: &Path) -> bool { false }
+
+    // calculate root this way to handle volume-relative Windows paths correctly
+    let mut root = os::getcwd();
+    let pat_root = Path::from_str(pattern).root_path();
+    if pat_root.is_some() {
+        if check_windows_verbatim(pat_root.get_ref()) {
+            // XXX: How do we want to handle verbatim paths? I'm inclined to return nothing,
+            // since we can't very well find all UNC shares with a 1-letter server name.
+            return GlobIterator { root: root, dir_patterns: ~[], options: options, todo: ~[] };
+        }
+        root.push_path(pat_root.get_ref());
+    }
 
-    // note that this relies on the glob meta characters not
-    // having any special meaning in actual pathnames
-    let path = Path(pattern);
-    let dir_patterns = path.components.map(|s| Pattern::new(*s));
+    let root_len = pat_root.map_move_default(0u, |p| p.as_vec().len());
+    let dir_patterns = pattern.slice_from(root_len.min(&pattern.len()))
+                       .split_terminator_iter(is_sep).map(|s| Pattern::new(s)).to_owned_vec();
 
-    let root = if path.is_absolute() {
-        Path {components: ~[], .. path} // preserve windows path host/device
-    } else {
-        os::getcwd()
-    };
-    let todo = list_dir_sorted(&root);
+    let todo = list_dir_sorted(&root).move_iter().map(|x|(x,0u)).to_owned_vec();
 
     GlobIterator {
         root: root,
@@ -109,18 +123,24 @@ impl Iterator<Path> for GlobIterator {
                 return None;
             }
 
-            let path = self.todo.pop();
-            let pattern_index = path.components.len() - self.root.components.len() - 1;
-            let ref pattern = self.dir_patterns[pattern_index];
-
-            if pattern.matches_with(*path.components.last(), self.options) {
+            let (path,idx) = self.todo.pop();
+            let ref pattern = self.dir_patterns[idx];
 
-                if pattern_index == self.dir_patterns.len() - 1 {
+            if pattern.matches_with(match path.filename_str() {
+                // this ugly match needs to go here to avoid a borrowck error
+                None => {
+                    // FIXME (#9639): How do we handle non-utf8 filenames? Ignore them for now
+                    // Ideally we'd still match them against a *
+                    loop;
+                }
+                Some(x) => x
+            }, self.options) {
+                if idx == self.dir_patterns.len() - 1 {
                     // it is not possible for a pattern to match a directory *AND* its children
                     // so we don't need to check the children
                     return Some(path);
                 } else {
-                    self.todo.push_all(list_dir_sorted(&path));
+                    self.todo.extend(&mut list_dir_sorted(&path).move_iter().map(|x|(x,idx+1)));
                 }
             }
         }
@@ -130,7 +150,7 @@ impl Iterator<Path> for GlobIterator {
 
 fn list_dir_sorted(path: &Path) -> ~[Path] {
     let mut children = os::list_dir_path(path);
-    sort::quick_sort(children, |p1, p2| p2.components.last() <= p1.components.last());
+    sort::quick_sort(children, |p1, p2| p2.filename().unwrap() <= p1.filename().unwrap());
     children
 }
 
@@ -285,7 +305,10 @@ impl Pattern {
      * using the default match options (i.e. `MatchOptions::new()`).
      */
     pub fn matches_path(&self, path: &Path) -> bool {
-        self.matches(path.to_str())
+        // FIXME (#9639): This needs to handle non-utf8 paths
+        do path.as_str().map_move_default(false) |s| {
+            self.matches(s)
+        }
     }
 
     /**
@@ -300,7 +323,10 @@ impl Pattern {
      * using the specified match options.
      */
     pub fn matches_path_with(&self, path: &Path, options: MatchOptions) -> bool {
-        self.matches_with(path.to_str(), options)
+        // FIXME (#9639): This needs to handle non-utf8 paths
+        do path.as_str().map_move_default(false) |s| {
+            self.matches_with(s, options)
+        }
     }
 
     fn matches_from(&self,
@@ -436,7 +462,7 @@ fn in_char_specifiers(specifiers: &[CharSpecifier], c: char, options: MatchOptio
 
 /// A helper function to determine if two chars are (possibly case-insensitively) equal.
 fn chars_eq(a: char, b: char, case_sensitive: bool) -> bool {
-    if cfg!(windows) && path::windows::is_sep(a) && path::windows::is_sep(b) {
+    if cfg!(windows) && path::windows::is_sep2(a) && path::windows::is_sep2(b) {
         true
     } else if !case_sensitive && a.is_ascii() && b.is_ascii() {
         // FIXME: work with non-ascii chars properly (issue #1347)
@@ -449,9 +475,9 @@ fn chars_eq(a: char, b: char, case_sensitive: bool) -> bool {
 /// A helper function to determine if a char is a path separator on the current platform.
 fn is_sep(c: char) -> bool {
     if cfg!(windows) {
-        path::windows::is_sep(c)
+        path::windows::is_sep2(c)
     } else {
-        path::posix::is_sep(c)
+        c <= '\x7F' && path::posix::is_sep(&(c as u8))
     }
 }
 
@@ -522,8 +548,9 @@ mod test {
         assert!(glob("//").next().is_none());
 
         // check windows absolute paths with host/device components
-        let root_with_device = (Path {components: ~[], .. os::getcwd()}).to_str() + "*";
-        assert!(glob(root_with_device).next().is_some());
+        let root_with_device = os::getcwd().root_path().unwrap().join_str("*");
+        // FIXME (#9639): This needs to handle non-utf8 paths
+        assert!(glob(root_with_device.as_str().unwrap()).next().is_some());
     }
 
     #[test]
@@ -745,9 +772,9 @@ mod test {
 
     #[test]
     fn test_matches_path() {
-        // on windows, (Path("a/b").to_str() == "a\\b"), so this
+        // on windows, (Path::from_str("a/b").as_str().unwrap() == "a\\b"), so this
         // tests that / and \ are considered equivalent on windows
-        assert!(Pattern::new("a/b").matches_path(&Path("a/b")));
+        assert!(Pattern::new("a/b").matches_path(&Path::from_str("a/b")));
     }
 }
 
diff --git a/src/libextra/tempfile.rs b/src/libextra/tempfile.rs
index 60084faad98..12263188787 100644
--- a/src/libextra/tempfile.rs
+++ b/src/libextra/tempfile.rs
@@ -35,7 +35,7 @@ impl TempDir {
 
         let mut r = rand::rng();
         for _ in range(0u, 1000) {
-            let p = tmpdir.push(r.gen_ascii_str(16) + suffix);
+            let p = tmpdir.join_str(r.gen_ascii_str(16) + suffix);
             if os::make_dir(&p, 0x1c0) { // 700
                 return Some(TempDir { path: Some(p) });
             }
diff --git a/src/libextra/terminfo/searcher.rs b/src/libextra/terminfo/searcher.rs
index 5c7efdb298f..cd4e487d70f 100644
--- a/src/libextra/terminfo/searcher.rs
+++ b/src/libextra/terminfo/searcher.rs
@@ -14,10 +14,9 @@
 use std::{os, str};
 use std::os::getenv;
 use std::io::{file_reader, Reader};
-use path = std::path::Path;
 
 /// Return path to database entry for `term`
-pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
+pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
     if term.len() == 0 {
         return None;
     }
@@ -29,25 +28,26 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
 
     // Find search directory
     match getenv("TERMINFO") {
-        Some(dir) => dirs_to_search.push(path(dir)),
+        Some(dir) => dirs_to_search.push(Path::from_str(dir)),
         None => {
             if homedir.is_some() {
-                dirs_to_search.push(homedir.unwrap().push(".terminfo")); // ncurses compatability
+                // ncurses compatability;
+                dirs_to_search.push(homedir.unwrap().join_str(".terminfo"))
             }
             match getenv("TERMINFO_DIRS") {
                 Some(dirs) => for i in dirs.split_iter(':') {
                     if i == "" {
-                        dirs_to_search.push(path("/usr/share/terminfo"));
+                        dirs_to_search.push(Path::from_str("/usr/share/terminfo"));
                     } else {
-                        dirs_to_search.push(path(i.to_owned()));
+                        dirs_to_search.push(Path::from_str(i.to_owned()));
                     }
                 },
                 // Found nothing, use the default paths
                 // /usr/share/terminfo is the de facto location, but it seems
                 // Ubuntu puts it in /lib/terminfo
                 None => {
-                    dirs_to_search.push(path("/usr/share/terminfo"));
-                    dirs_to_search.push(path("/lib/terminfo"));
+                    dirs_to_search.push(Path::from_str("/usr/share/terminfo"));
+                    dirs_to_search.push(Path::from_str("/lib/terminfo"));
                 }
             }
         }
@@ -55,14 +55,18 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
 
     // Look for the terminal in all of the search directories
     for p in dirs_to_search.iter() {
-        let newp = ~p.push_many(&[str::from_char(first_char), term.to_owned()]);
-        if os::path_exists(p) && os::path_exists(newp) {
-            return Some(newp);
-        }
-        // on some installations the dir is named after the hex of the char (e.g. OS X)
-        let newp = ~p.push_many(&[format!("{:x}", first_char as uint), term.to_owned()]);
-        if os::path_exists(p) && os::path_exists(newp) {
-            return Some(newp);
+        if os::path_exists(p) {
+            let f = str::from_char(first_char);
+            let newp = p.join_many_str([f.as_slice(), term]);
+            if os::path_exists(&newp) {
+                return Some(~newp);
+            }
+            // on some installations the dir is named after the hex of the char (e.g. OS X)
+            let f = format!("{:x}", first_char as uint);
+            let newp = p.join_many_str([f.as_slice(), term]);
+            if os::path_exists(&newp) {
+                return Some(~newp);
+            }
         }
     }
     None
@@ -82,7 +86,11 @@ fn test_get_dbpath_for_term() {
     // woefully inadequate test coverage
     // note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's)
     use std::os::{setenv, unsetenv};
-    fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() };
+    // FIXME (#9639): This needs to handle non-utf8 paths
+    fn x(t: &str) -> ~str {
+        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
+        p.as_str().unwrap().to_owned()
+    };
     assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
     assert!(get_dbpath_for_term("") == None);
     setenv("TERMINFO_DIRS", ":");
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index a352a2e4678..20690283dd5 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -271,20 +271,20 @@ pub fn parse_opts(args: &[~str]) -> Option<OptRes> {
     let run_ignored = matches.opt_present("ignored");
 
     let logfile = matches.opt_str("logfile");
-    let logfile = logfile.map(|s| Path(s));
+    let logfile = logfile.map(|s| Path::from_str(s));
 
     let run_benchmarks = matches.opt_present("bench");
     let run_tests = ! run_benchmarks ||
         matches.opt_present("test");
 
     let ratchet_metrics = matches.opt_str("ratchet-metrics");
-    let ratchet_metrics = ratchet_metrics.map(|s| Path(s));
+    let ratchet_metrics = ratchet_metrics.map(|s| Path::from_str(s));
 
     let ratchet_noise_percent = matches.opt_str("ratchet-noise-percent");
     let ratchet_noise_percent = ratchet_noise_percent.map(|s| from_str::<f64>(s).unwrap());
 
     let save_metrics = matches.opt_str("save-metrics");
-    let save_metrics = save_metrics.map(|s| Path(s));
+    let save_metrics = save_metrics.map(|s| Path::from_str(s));
 
     let test_shard = matches.opt_str("test-shard");
     let test_shard = opt_shard(test_shard);
@@ -547,7 +547,7 @@ impl ConsoleTestState {
         let ratchet_success = match *ratchet_metrics {
             None => true,
             Some(ref pth) => {
-                self.out.write_str(format!("\nusing metrics ratchet: {}\n", pth.to_str()));
+                self.out.write_str(format!("\nusing metrics ratchet: {}\n", pth.display()));
                 match ratchet_pct {
                     None => (),
                     Some(pct) =>
@@ -659,7 +659,7 @@ pub fn run_tests_console(opts: &TestOpts,
         None => (),
         Some(ref pth) => {
             st.metrics.save(pth);
-            st.out.write_str(format!("\nmetrics saved to: {}", pth.to_str()));
+            st.out.write_str(format!("\nmetrics saved to: {}", pth.display()));
         }
     }
     return st.write_run_finish(&opts.ratchet_metrics, opts.ratchet_noise_percent);
@@ -1440,7 +1440,7 @@ mod tests {
     pub fn ratchet_test() {
 
         let dpth = TempDir::new("test-ratchet").expect("missing test for ratchet");
-        let pth = dpth.path().push("ratchet.json");
+        let pth = dpth.path().join_str("ratchet.json");
 
         let mut m1 = MetricMap::new();
         m1.insert_metric("runtime", 1000.0, 2.0);
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index 32a2d83d814..ea943cdb01b 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -184,11 +184,11 @@ impl Database {
         let f = io::file_reader(&self.db_filename);
         match f {
             Err(e) => fail2!("Couldn't load workcache database {}: {}",
-                            self.db_filename.to_str(), e.to_str()),
+                            self.db_filename.display(), e.to_str()),
             Ok(r) =>
                 match json::from_reader(r) {
                     Err(e) => fail2!("Couldn't parse workcache database (from file {}): {}",
-                                    self.db_filename.to_str(), e.to_str()),
+                                    self.db_filename.display(), e.to_str()),
                     Ok(r) => {
                         let mut decoder = json::Decoder(r);
                         self.db_cache = Decodable::decode(&mut decoder);
@@ -498,7 +498,7 @@ fn test() {
     // Create a path to a new file 'filename' in the directory in which
     // this test is running.
     fn make_path(filename: ~str) -> Path {
-        let pth = os::self_exe_path().expect("workcache::test failed").pop().push(filename);
+        let pth = os::self_exe_path().expect("workcache::test failed").with_filename_str(filename);
         if os::path_exists(&pth) {
             os::remove_file(&pth);
         }
@@ -522,15 +522,20 @@ fn test() {
         let subcx = cx.clone();
         let pth = pth.clone();
 
-        prep.declare_input("file", pth.to_str(), digest_file(&pth));
+        // FIXME (#9639): This needs to handle non-utf8 paths
+        prep.declare_input("file", pth.as_str().unwrap(), digest_file(&pth));
         do prep.exec |_exe| {
             let out = make_path(~"foo.o");
-            run::process_status("gcc", [pth.to_str(), ~"-o", out.to_str()]);
+            // FIXME (#9639): This needs to handle non-utf8 paths
+            run::process_status("gcc", [pth.as_str().unwrap().to_owned(),
+                                        ~"-o",
+                                        out.as_str().unwrap().to_owned()]);
 
             let _proof_of_concept = subcx.prep("subfn");
             // Could run sub-rules inside here.
 
-            out.to_str()
+            // FIXME (#9639): This needs to handle non-utf8 paths
+            out.as_str().unwrap().to_owned()
         }
     };