summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-05-20 10:37:21 -0400
committerGitHub <noreply@github.com>2021-05-20 10:37:21 -0400
commitfe16f7533deb55e83ed0d736e1cd826ad8ae7522 (patch)
tree53570ae23091cd454d64ebf6c6dd714012cd0452
parent5ece1944f1a7df30d342452d7a85d4871c16a42c (diff)
Emit description of file mode change (#605)
Fixes #583
-rw-r--r--src/delta.rs41
-rw-r--r--src/parse.rs49
-rw-r--r--src/tests/test_example_diffs.rs14
3 files changed, 84 insertions, 20 deletions
diff --git a/src/delta.rs b/src/delta.rs
index 56114f76..cfafe3dc 100644
--- a/src/delta.rs
+++ b/src/delta.rs
@@ -62,7 +62,9 @@ struct StateMachine<'a> {
source: Source,
minus_file: String,
plus_file: String,
- file_event: parse::FileEvent,
+ minus_file_event: parse::FileEvent,
+ plus_file_event: parse::FileEvent,
+ file_paths_from_diff_line: (Option<String>, Option<String>),
painter: Painter<'a>,
config: &'a Config,
@@ -91,7 +93,9 @@ impl<'a> StateMachine<'a> {
source: Source::Unknown,
minus_file: "".to_string(),
plus_file: "".to_string(),
- file_event: parse::FileEvent::NoEvent,
+ minus_file_event: parse::FileEvent::NoEvent,
+ plus_file_event: parse::FileEvent::NoEvent,
+ file_paths_from_diff_line: (None, None),
current_file_pair: None,
handled_file_meta_header_line_file_pair: None,
painter: Painter::new(writer, config),
@@ -122,13 +126,15 @@ impl<'a> StateMachine<'a> {
} else if (self.state == State::FileMeta || self.source == Source::DiffUnified)
&& (line.starts_with("--- ")
|| line.starts_with("rename from ")
- || line.starts_with("copy from "))
+ || line.starts_with("copy from ")
+ || line.starts_with("old mode "))
{
self.handle_file_meta_minus_line()?
} else if (self.state == State::FileMeta || self.source == Source::DiffUnified)
&& (line.starts_with("+++ ")
|| line.starts_with("rename to ")
- || line.starts_with("copy to "))
+ || line.starts_with("copy to ")
+ || line.starts_with("new mode "))
{
self.handle_file_meta_plus_line()?
} else if line.starts_with("@@") {
@@ -253,13 +259,14 @@ impl<'a> StateMachine<'a> {
self.painter.paint_buffered_minus_and_plus_lines();
self.state = State::FileMeta;
self.handled_file_meta_header_line_file_pair = None;
+ self.file_paths_from_diff_line = parse::get_file_paths_from_diff_line(&self.line);
Ok(false)
}
fn handle_file_meta_minus_line(&mut self) -> std::io::Result<bool> {
let mut handled_line = false;
- let parsed_file_meta_line = parse::parse_file_meta_line(
+ let (path_or_mode, file_event) = parse::parse_file_meta_line(
&self.line,
self.source == Source::GitDiff,
if self.config.relative_paths {
@@ -268,8 +275,14 @@ impl<'a> StateMachine<'a> {
None
},
);
- self.minus_file = parsed_file_meta_line.0;
- self.file_event = parsed_file_meta_line.1;
+ // In the case of ModeChange only, the file path is taken from the diff
+ // --git line (since that is the only place the file path occurs);
+ // otherwise it is taken from the --- / +++ line.
+ self.minus_file = match (&file_event, &self.file_paths_from_diff_line) {
+ (parse::FileEvent::ModeChange(_), (Some(file), _)) => file.clone(),
+ _ => path_or_mode,
+ };
+ self.minus_file_event = file_event;
if self.source == Source::DiffUnified {
self.state = State::FileMeta;
@@ -300,7 +313,7 @@ impl<'a> StateMachine<'a> {
fn handle_file_meta_plus_line(&mut self) -> std::io::Result<bool> {
let mut handled_line = false;
- let parsed_file_meta_line = parse::parse_file_meta_line(
+ let (path_or_mode, file_event) = parse::parse_file_meta_line(
&self.line,
self.source == Source::GitDiff,
if self.config.relative_paths {
@@ -309,7 +322,14 @@ impl<'a> StateMachine<'a> {
None
},
);
- self.plus_file = parsed_file_meta_line.0;
+ // In the case of ModeChange only, the file path is taken from the diff
+ // --git line (since that is the only place the file path occurs);
+ // otherwise it is taken from the --- / +++ line.
+ self.plus_file = match (&file_event, &self.file_paths_from_diff_line) {
+ (parse::FileEvent::ModeChange(_), (_, Some(file))) => file.clone(),
+ _ => path_or_mode,
+ };
+ self.plus_file_event = file_event;
self.painter
.set_syntax(parse::get_file_extension_from_file_meta_line_file_path(
&self.plus_file,
@@ -344,7 +364,8 @@ impl<'a> StateMachine<'a> {
&self.minus_file,
&self.plus_file,
comparing,
- &self.file_event,
+ &self.minus_file_event,
+ &self.plus_file_event,
self.config,
);
// FIXME: no support for 'raw'
diff --git a/src/parse.rs b/src/parse.rs
index ab51702e..3329248b 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -25,6 +25,7 @@ pub enum FileEvent {
Change,
Copy,
Rename,
+ ModeChange(String),
NoEvent,
}
@@ -33,7 +34,7 @@ pub fn parse_file_meta_line(
git_diff_name: bool,
relative_path_base: Option<&str>,
) -> (String, FileEvent) {
- let (mut path, file_event) = match line {
+ let (mut path_or_mode, file_event) = match line {
line if line.starts_with("--- ") || line.starts_with("+++ ") => {
let offset = 4;
let file = _parse_file_path(&line[offset..], git_diff_name);
@@ -51,18 +52,35 @@ pub fn parse_file_meta_line(
line if line.starts_with("copy to ") => {
(line[8..].to_string(), FileEvent::Copy) // "copy to ".len()
}
+ line if line.starts_with("old mode ") => {
+ ("".to_string(), FileEvent::ModeChange(line[9..].to_string())) // "old mode ".len()
+ }
+ line if line.starts_with("new mode ") => {
+ ("".to_string(), FileEvent::ModeChange(line[9..].to_string())) // "new mode ".len()
+ }
_ => ("".to_string(), FileEvent::NoEvent),
};
if let Some(base) = relative_path_base {
- if let Some(relative_path) = pathdiff::diff_paths(&path, base) {
+ if let FileEvent::ModeChange(_) = file_event {
+ } else if let Some(relative_path) = pathdiff::diff_paths(&path_or_mode, base) {
if let Some(relative_path) = relative_path.to_str() {
- path = relative_path.to_owned();
+ path_or_mode = relative_path.to_owned();
}
}
}
- (path, file_event)
+ (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)),
+ )
}
fn _parse_file_path(s: &str, git_diff_name: bool) -> String {
@@ -117,7 +135,8 @@ pub fn get_file_change_description_from_file_paths(
minus_file: &str,
plus_file: &str,
comparing: bool,
- file_event: &FileEvent,
+ minus_file_event: &FileEvent,
+ plus_file_event: &FileEvent,
config: &Config,
) -> String {
if comparing {
@@ -137,23 +156,33 @@ pub fn get_file_change_description_from_file_paths(
Cow::from(file)
}
};
- match (minus_file, plus_file) {
- (minus_file, plus_file) if minus_file == plus_file => format!(
+ match (minus_file, plus_file, minus_file_event, plus_file_event) {
+ (
+ minus_file,
+ plus_file,
+ FileEvent::ModeChange(old_mode),
+ FileEvent::ModeChange(new_mode),
+ ) if minus_file == plus_file => {
+ format!("{}: {} ⟶ {}", plus_file, old_mode, new_mode)
+ }
+ (minus_file, plus_file, _, _) if minus_file == plus_file => format!(
"{}{}",
format_label(&config.file_modified_label),
format_file(minus_file)
),
- (minus_file, "/dev/null") => format!(
+ (minus_file, "/dev/null", _, _) => format!(
"{}{}",
format_label(&config.file_removed_label),
format_file(minus_file)
),
- ("/dev/null", plus_file) => format!(
+ ("/dev/null", plus_file, _, _) => format!(
"{}{}",
format_label(&config.file_added_label),
format_file(plus_file)
),
- (minus_file, plus_file) => format!(
+ // minus_file_event == plus_file_event, except in the ModeChange
+ // case above.
+ (minus_file, plus_file, file_event, _) => format!(
"{}{} ⟶ {}",
format_label(match file_event {
FileEvent::Rename => &config.file_renamed_label,
diff --git a/src/tests/test_example_diffs.rs b/src/tests/test_example_diffs.rs
index de35535a..a4d0b854 100644
--- a/src/tests/test_example_diffs.rs
+++ b/src/tests/test_example_diffs.rs
@@ -1569,6 +1569,14 @@ src/align.rs:71: impl<'a> Alignment<'a> { │
));
}
+ #[test]
+ fn test_file_mode_change() {
+ let config = integration_test_utils::make_config_from_args(&[]);
+ let output = integration_test_utils::run_delta(GIT_DIFF_FILE_MODE_CHANGE, &config);
+ let output = strip_ansi_codes(&output);
+ assert!(output.contains(r"src/delta.rs: 100644 ⟶ 100755"));
+ }
+
const GIT_DIFF_SINGLE_HUNK: &str = "\
commit 94907c0f136f46dc46ffae2dc92dca9af7eb7c2e
Author: Dan Davison <dandavison7@gmail.com>
@@ -2172,4 +2180,10 @@ Date: Sun Nov 1 15:28:53 2020 -0500
\ No newline at end of file
+]
"#;
+
+ const GIT_DIFF_FILE_MODE_CHANGE: &str = "
+diff --git a/src/delta.rs b/src/delta.rs
+old mode 100644
+new mode 100755
+";
}