From 9750fb7fca8dfc16752c79f1e0b5f4a2d73c4563 Mon Sep 17 00:00:00 2001 From: Stuart Dootson Date: Mon, 18 Jul 2016 22:05:01 +0100 Subject: [PATCH] Canonicalize file paths within the map of file line ranges (#1098) * Canonicalize file paths within the map of file line ranges * Forgot to run the tests - and of course, the formatting of the canonicalization change was off, but it's fixed now! * Move imports to the top of the file, as per @nrc. * Change `canonicalize_path_string` to return `Option`, `None` indicating an error rather than an empty string * `format!` is better than string concatenation... * Change `canonicalize_path_string` to return `Result` rather than `Option` --- src/file_lines.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/file_lines.rs b/src/file_lines.rs index 28fedad4cfd..61b43375dda 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -9,7 +9,7 @@ // except according to those terms. //! This module contains types and functions to support formatting specific line ranges. -use std::{cmp, iter, str}; +use std::{cmp, iter, path, str}; use itertools::Itertools; use multimap::MultiMap; @@ -119,9 +119,10 @@ impl FileLines { Some(ref map) => map, }; - match map.get_vec(range.file_name()) { - None => false, - Some(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), + match canonicalize_path_string(range.file_name()) + .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { + Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), + Err(_) => false, } } @@ -151,13 +152,20 @@ impl<'a> iter::Iterator for Files<'a> { } } +fn canonicalize_path_string(s: &str) -> Result { + match path::PathBuf::from(s).canonicalize() { + Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()).ok_or(()), + _ => Err(()), + } +} + // This impl is needed for `Config::override_value` to work for use in tests. impl str::FromStr for FileLines { type Err = String; fn from_str(s: &str) -> Result { let v: Vec = try!(json::decode(s).map_err(|e| e.to_string())); - let m = v.into_iter().map(JsonSpan::into_tuple).collect(); + let m = try!(v.into_iter().map(JsonSpan::into_tuple).collect()); Ok(FileLines::from_multimap(m)) } } @@ -171,9 +179,11 @@ struct JsonSpan { impl JsonSpan { // To allow `collect()`ing into a `MultiMap`. - fn into_tuple(self) -> (String, Range) { + fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; - (self.file, Range::new(lo, hi)) + let canonical = try!(canonicalize_path_string(&self.file) + .map_err(|_| format!("Can't canonicalize {}", &self.file))); + Ok((canonical, Range::new(lo, hi))) } }