Fix, and add tests for, slashes in link paths

This commit is contained in:
Ben S 2016-06-11 16:54:06 +01:00
parent 580ad0cfec
commit b8191670c7
3 changed files with 50 additions and 15 deletions

View File

@ -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)
}
}

View File

@ -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("/"));
}
}
}
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("/"));
}
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
tests/links.rs Normal file
View File

@ -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());
}