summaryrefslogtreecommitdiffstats
path: root/src/parse.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.rs')
-rw-r--r--src/parse.rs57
1 files changed, 48 insertions, 9 deletions
diff --git a/src/parse.rs b/src/parse.rs
index 8e93dd6a..7b4ef430 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -2,6 +2,7 @@ use lazy_static::lazy_static;
use regex::Regex;
use std::borrow::Cow;
use std::path::Path;
+use unicode_segmentation::UnicodeSegmentation;
use crate::config::Config;
use crate::features;
@@ -73,18 +74,32 @@ pub fn parse_file_meta_line(
(path_or_mode, file_event)
}
-/// Given input like "diff --git a/src/main.rs b/src/main.rs"
-/// return (Some("src/main.rs"), Some("src/main.rs"))
-pub fn get_file_paths_from_diff_line(line: &str) -> (Option<String>, Option<String>) {
- let mut iter = line.split(' ').skip(2);
- (
- iter.next().map(|s| _parse_file_path(&s[2..], true)),
- iter.next().map(|s| _parse_file_path(&s[2..], true)),
- )
+/// Given input like "diff --git a/src/my file.rs b/src/my file.rs"
+/// return Some("src/my file.rs")
+pub fn get_repeated_file_path_from_diff_line(line: &str) -> Option<String> {
+ if let Some(line) = line.strip_prefix("diff --git ") {
+ let line: Vec<&str> = line.graphemes(true).collect();
+ let midpoint = line.len() / 2;
+ if line[midpoint] == " " {
+ let first_path = _parse_file_path(&line[..midpoint].join(""), true);
+ let second_path = _parse_file_path(&line[midpoint + 1..].join(""), true);
+ if first_path == second_path {
+ return Some(first_path);
+ }
+ }
+ }
+ None
}
fn _parse_file_path(s: &str, git_diff_name: bool) -> String {
- match s {
+ // It appears that, if the file name contains a space, git appends a tab
+ // character in the diff metadata lines, e.g.
+ // $ git diff --no-index "a b" "c d" | cat -A
+ // diff·--git·a/a·b·b/c·d␊
+ // index·d00491f..0cfbf08·100644␊
+ // ---·a/a·b├──┤␊
+ // +++·b/c·d├──┤␊
+ match s.strip_suffix("\t").unwrap_or(s) {
path if path == "/dev/null" => "/dev/null",
path if git_diff_name && DIFF_PREFIXES.iter().any(|s| path.starts_with(s)) => &path[2..],
path if git_diff_name => &path,
@@ -258,6 +273,30 @@ mod tests {
use super::*;
#[test]
+ fn test_get_repeated_file_path_from_diff_line() {
+ assert_eq!(
+ get_repeated_file_path_from_diff_line("diff --git a/src/main.rs b/src/main.rs"),
+ Some("src/main.rs".to_string())
+ );
+ assert_eq!(
+ get_repeated_file_path_from_diff_line("diff --git a/a b/a"),
+ Some("a".to_string())
+ );
+ assert_eq!(
+ get_repeated_file_path_from_diff_line("diff --git a/a b b/a b"),
+ Some("a b".to_string())
+ );
+ assert_eq!(
+ get_repeated_file_path_from_diff_line("diff --git a/a b/aa"),
+ None
+ );
+ assert_eq!(
+ get_repeated_file_path_from_diff_line("diff --git a/.config/Code - Insiders/User/settings.json b/.config/Code - Insiders/User/settings.json"),
+ Some(".config/Code - Insiders/User/settings.json".to_string())
+ );
+ }
+
+ #[test]
fn test_get_file_extension_from_marker_line() {
assert_eq!(
get_file_extension_from_marker_line(