Przeglądaj źródła

Fix, and add tests for, slashes in link paths

Ben S 9 lat temu
rodzic
commit
b8191670c7
3 zmienionych plików z 50 dodań i 15 usunięć
  1. 4 4
      src/fs/file.rs
  2. 25 11
      src/output/mod.rs
  3. 21 0
      tests/links.rs

+ 4 - 4
src/fs/file.rs

@@ -163,12 +163,12 @@ impl<'dir> File<'dir> {
     /// returns a File object from the path the link points to.
     ///
     /// If statting the file fails (usually because the file on the
-    /// other end doesn't exist), returns the *filename* of the file
+    /// other end doesn't exist), returns the path to the file
     /// that should be there.
-    pub fn link_target(&self) -> Result<File<'dir>, String> {
+    pub fn link_target(&self) -> Result<File<'dir>, PathBuf> {
         let path = match fs::read_link(&self.path) {
             Ok(path)  => path,
-            Err(_)    => return Err(self.name.clone()),
+            Err(_)    => panic!("This was not a link!"),
         };
 
         let target_path = match self.dir {
@@ -192,7 +192,7 @@ impl<'dir> File<'dir> {
             })
         }
         else {
-            Err(target_path.display().to_string())
+            Err(target_path)
         }
     }
 

+ 25 - 11
src/output/mod.rs

@@ -24,14 +24,21 @@ pub fn filename(file: &File, colours: &Colours, links: bool) -> TextCellContents
 
     if file.dir.is_none() {
         if let Some(ref parent) = file.path.parent() {
-            if parent.components().count() > 0 {
-                bits.push(Style::default().paint(parent.to_string_lossy().to_string()));
-                bits.push(Style::default().paint("/"));
+            let coconut = parent.components().count();
+
+            if coconut == 1 && parent.has_root() {
+                bits.push(colours.symlink_path.paint("/"));
+            }
+            else if coconut > 1 {
+                bits.push(colours.symlink_path.paint(parent.to_string_lossy().to_string()));
+                bits.push(colours.symlink_path.paint("/"));
             }
         }
     }
 
-    bits.push(file_colour(colours, &file).paint(file.name.clone()));
+    if !file.name.is_empty() {
+        bits.push(file_colour(colours, &file).paint(file.name.clone()));
+    }
 
     if links && file.is_link() {
         match file.link_target() {
@@ -42,22 +49,29 @@ pub fn filename(file: &File, colours: &Colours, links: bool) -> TextCellContents
 
                 if let Some(ref parent) = target.path.parent() {
                     let coconut = parent.components().count();
-                    if coconut != 0 {
-                        if !(coconut == 1 && parent.has_root()) {
-                            bits.push(colours.symlink_path.paint(parent.to_string_lossy().to_string()));
-                        }
+
+                    if coconut == 1 && parent.has_root() {
+                        bits.push(colours.symlink_path.paint("/"));
+                    }
+                    else if coconut > 1 {
+                        bits.push(colours.symlink_path.paint(parent.to_string_lossy().to_string()));
                         bits.push(colours.symlink_path.paint("/"));
                     }
                 }
+                else {
+                    bits.push(colours.symlink_path.paint("/"));
+                }
 
-                bits.push(file_colour(colours, &target).paint(target.name));
+                if !target.name.is_empty() {
+                    bits.push(file_colour(colours, &target).paint(target.name));
+                }
             },
 
-            Err(filename) => {
+            Err(broken_path) => {
                 bits.push(Style::default().paint(" "));
                 bits.push(colours.broken_arrow.paint("->"));
                 bits.push(Style::default().paint(" "));
-                bits.push(colours.broken_filename.paint(filename));
+                bits.push(colours.broken_filename.paint(broken_path.display().to_string()));
             },
         }
     }

+ 21 - 0
tests/links.rs

@@ -0,0 +1,21 @@
+extern crate exa;
+use exa::Exa;
+
+/// --------------------------------------------------------------------------
+/// These tests assume that the ‘generate annoying testcases’ script has been
+/// run first. Otherwise, they will break!
+/// --------------------------------------------------------------------------
+
+
+static LINKS: &'static str = concat!(
+    "\x1B[36m", "broken",  "\x1B[0m", " ", "\x1B[31m",       "->", "\x1B[0m", " ", "\x1B[4;31m", "testcases/links/nowhere", "\x1B[0m", '\n',
+    "\x1B[36m", "root",    "\x1B[0m", " ", "\x1B[38;5;244m", "->", "\x1B[0m", " ", "\x1B[36m",   "/",                       "\x1B[0m", '\n',
+    "\x1B[36m", "usr",     "\x1B[0m", " ", "\x1B[38;5;244m", "->", "\x1B[0m", " ", "\x1B[36m",   "/", "\x1B[1;34m", "usr",  "\x1B[0m", '\n',
+);
+
+#[test]
+fn links() {
+    let mut output = Vec::<u8>::new();
+    Exa::new( &[ "-1", "testcases/links" ], &mut output).unwrap().run().unwrap();
+    assert_eq!(output, LINKS.as_bytes());
+}