1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
use std::path::Path;
/// Given input like
/// "diff --git a/src/main.rs b/src/main.rs"
/// Return "rs", i.e. a single file extension consistent with both files.
pub fn get_file_extension_from_diff_line(line: &str) -> Option<&str> {
match get_file_extensions_from_diff_line(line) {
(Some(_ext1), Some(ext2)) => {
// If they differ then it's a rename; use the new extension.
Some(ext2)
}
(Some(ext1), None) => Some(ext1),
(None, Some(ext2)) => Some(ext2),
(None, None) => None,
}
}
pub fn get_file_path_from_file_meta_line(line: &str) -> String {
if line.starts_with("rename") {
match line.split(' ').nth(2) {
Some(path) => path,
_ => "",
}
.to_string()
} else {
match line.split(' ').nth(1) {
Some("/dev/null") => "/dev/null",
Some(path) => &path[2..],
_ => "",
}
.to_string()
}
}
pub fn get_file_change_description_from_file_paths(minus_file: &str, plus_file: &str) -> String {
match (minus_file, plus_file) {
(minus_file, plus_file) if minus_file == plus_file => minus_file.to_string(),
(minus_file, "/dev/null") => format!("deleted: {}", minus_file),
("/dev/null", plus_file) => format!("added: {}", plus_file),
(minus_file, plus_file) => format!("renamed: {} ⟶ {}", minus_file, plus_file),
}
}
/// Given input like
/// "@@ -74,15 +74,14 @@ pub fn delta("
/// Return " pub fn delta("
pub fn parse_hunk_metadata(line: &str) -> (&str, &str) {
let mut iter = line.split("@@").skip(1);
let line_number = iter
.next()
.and_then(|s| s.split('+').nth(1).and_then(|s| s.split(',').next()))
.unwrap_or("");
let code_fragment = iter.next().unwrap_or("");
(code_fragment, line_number)
}
/// Given input like "diff --git a/src/main.rs b/src/main.rs"
/// return ("rs", "rs").
fn get_file_extensions_from_diff_line(line: &str) -> (Option<&str>, Option<&str>) {
let mut iter = line.split(' ').skip(2);
(
iter.next().and_then(|s| get_extension(&s[2..])),
iter.next().and_then(|s| get_extension(&s[2..])),
)
}
/// Attempt to parse input as a file path and return extension as a &str.
fn get_extension(s: &str) -> Option<&str> {
let path = Path::new(s);
path.extension()
.and_then(|e| e.to_str())
// E.g. 'Makefile' is the file name and also the extension
.or_else(|| path.file_name().and_then(|s| s.to_str()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_file_extension_from_diff_line() {
assert_eq!(
get_file_extension_from_diff_line("diff --git a/src/main.rs b/src/main.rs"),
Some("rs")
);
}
#[test]
fn test_get_file_path_from_file_meta_line() {
assert_eq!(
get_file_path_from_file_meta_line("--- a/src/delta.rs"),
"src/delta.rs"
);
assert_eq!(
get_file_path_from_file_meta_line("+++ b/src/delta.rs"),
"src/delta.rs"
);
}
#[test]
fn test_parse_hunk_metadata() {
assert_eq!(
parse_hunk_metadata("@@ -74,15 +75,14 @@ pub fn delta(\n"),
(" pub fn delta(\n", "75")
);
}
}
|