From 5e02d340a8b3f3184f84a34434d7ad170988331f Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sun, 22 Aug 2021 11:25:39 -0700 Subject: 662 submodule diffs (#699) --- etc/examples/662-submodules | 45 ++++++++++++++++++++++++++++ src/config.rs | 1 + src/delta.rs | 12 ++++---- src/tests/test_example_diffs.rs | 66 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 5 deletions(-) create mode 100755 etc/examples/662-submodules diff --git a/etc/examples/662-submodules b/etc/examples/662-submodules new file mode 100755 index 00000000..1f4a5189 --- /dev/null +++ b/etc/examples/662-submodules @@ -0,0 +1,45 @@ +#!/bin/bash +REPO_ROOT=/tmp/submodule-diff-example +REPO_DATE_FMT=%H:%M:%S.%N +mkdir ${REPO_ROOT} && git -C ${REPO_ROOT} init && cd ${REPO_ROOT} +date +${REPO_DATE_FMT} >> baserepo && git add baserepo && git commit -m "Base repo commit 1" + +for sub in A B C; do + git init submodule${sub} + for iter in $(seq 1 4); do + date +${REPO_DATE_FMT} >> submodule${sub}/subcontent + git -C submodule${sub} add subcontent && git -C submodule${sub} commit -m "Submodule ${sub} initial commit $iter" + done + # Add initial submodule, message of "Submodule submoduleX 0000000...xxxxxxx (new submodule)", no individual commits + git submodule add ../bogus-url-${sub} submodule${sub} && \ + git commit -m "Add submodule${sub}" # the diff handling for this is correct in delta + + # Create additional submodule commits + for iter in $(seq 1 2); do + date +${REPO_DATE_FMT} >> submodule${sub}/subcontent + git -C submodule${sub} add subcontent && git -C submodule${sub} commit -m "Submodule ${sub} extra change ${iter}" + done + git add submodule${sub} && git commit -m "Update submodule${sub}" +done + +git -C submoduleA reset --hard HEAD~4 +git -C submoduleC reset --hard HEAD~2 + +for sub in B C; do + for iter in $(seq 1 3); do + date +${REPO_DATE_FMT} >> submodule${sub}/subcontent + git -C submodule${sub} add subcontent && git -C submodule${sub} commit -m "Submodule ${sub} stage change ${iter}" + done +done + +# Add all submodule updates in single commit to test multiple submodule updates in single commit +git add submodule[A-C] && git commit -m "Update all submodules" + +# submoduleA end state is only removed commits +# submoduleB end state is only added commits +# submoduleC is a mixture of removed and added commits (e.g. different branch) + +# Manual, inspect superproject history via: +# "git -c diff.submodule=short log -p | delta --no-gitconfig" +# "git -c diff.submodule=log log -p | delta --no-gitconfig" +# "git -c diff.submodule=diff log -p | delta --no-gitconfig" diff --git a/src/config.rs b/src/config.rs index b0a8cb3c..acf7d0c9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -100,6 +100,7 @@ impl Config { State::CommitMeta => &self.commit_style, State::FileMeta => &self.file_style, State::HunkHeader => &self.hunk_header_style, + State::Submodule => &self.file_style, _ => delta_unreachable("Unreachable code reached in get_style."), } } diff --git a/src/delta.rs b/src/delta.rs index e1770b7e..c42ba9f1 100644 --- a/src/delta.rs +++ b/src/delta.rs @@ -24,6 +24,7 @@ pub enum State { HunkZero, // In hunk; unchanged line HunkMinus(Option), // In hunk; removed line (raw_line) HunkPlus(Option), // In hunk; added line (raw_line) + Submodule, Unknown, } @@ -140,10 +141,11 @@ impl<'a> StateMachine<'a> { } else if line.starts_with("@@") { self.handle_hunk_header_line()? } else if self.source == Source::DiffUnified && line.starts_with("Only in ") - || line.starts_with("Submodule ") || line.starts_with("Binary files ") { - self.handle_additional_file_meta_cases()? + self.handle_additional_cases(State::FileMeta)? + } else if line.starts_with("Submodule ") { + self.handle_additional_cases(State::Submodule)? } else if self.state.is_in_hunk() { // A true hunk line should start with one of: '+', '-', ' '. However, handle_hunk_line // handles all lines until the state transitions away from the hunk states. @@ -381,10 +383,10 @@ impl<'a> StateMachine<'a> { _write_generic_file_meta_header_line(&line, &line, &mut self.painter, self.config) } - fn handle_additional_file_meta_cases(&mut self) -> std::io::Result { + fn handle_additional_cases(&mut self, to_state: State) -> std::io::Result { let mut handled_line = false; - // Additional FileMeta cases: + // Additional cases: // // 1. When comparing directories with diff -u, if filenames match between the // directories, the files themselves will be compared. However, if an equivalent @@ -398,7 +400,7 @@ impl<'a> StateMachine<'a> { // proposal for more robust parsing logic. self.painter.paint_buffered_minus_and_plus_lines(); - self.state = State::FileMeta; + self.state = to_state; if self.should_handle() { self.painter.emit()?; _write_generic_file_meta_header_line( diff --git a/src/tests/test_example_diffs.rs b/src/tests/test_example_diffs.rs index 3f28d200..3b249eff 100644 --- a/src/tests/test_example_diffs.rs +++ b/src/tests/test_example_diffs.rs @@ -200,6 +200,16 @@ mod tests { assert_eq!(strip_ansi_codes(&output), DIFF_WITH_MERGE_CONFLICT); } + #[test] + fn test_submodule_diff_log() { + // See etc/examples/662-submodules + // diff.submodule = log + let config = integration_test_utils::make_config_from_args(&["--width", "49"]); + let output = integration_test_utils::run_delta(SUBMODULE_DIFF_LOG, &config); + let output = strip_ansi_codes(&output); + assert_eq!(output, SUBMODULE_DIFF_LOG_EXPECTED_OUTPUT); + } + #[test] fn test_submodule_contains_untracked_content() { let config = integration_test_utils::make_config_from_args(&[]); @@ -1902,6 +1912,62 @@ This is a regular file that contains: +Some text with a plus "; + // See etc/examples/662-submodules + // diff.submodule = log + const SUBMODULE_DIFF_LOG: &str = "\ +commit ccb444baa861fdcb14d411b471a74614ed28776d +Author: Dan Davison +Date: Sat Aug 21 18:56:34 2021 -0700 + + Update all submodules + +Submodule submoduleA f4f55af..310b551 (rewind): + < Submodule A extra change 2 + < Submodule A extra change 1 + < Submodule A initial commit 4 + < Submodule A initial commit 3 +Submodule submoduleB 0ffa700..0c8b00d: + > Submodule B stage change 3 + > Submodule B stage change 2 + > Submodule B stage change 1 +Submodule submoduleC 9f3b744...e04f848: + > Submodule C stage change 3 + > Submodule C stage change 2 + < Submodule C extra change 2 + > Submodule C stage change 1 + < Submodule C extra change 1 +"; + + const SUBMODULE_DIFF_LOG_EXPECTED_OUTPUT: &str = "\ +commit ccb444baa861fdcb14d411b471a74614ed28776d +Author: Dan Davison +Date: Sat Aug 21 18:56:34 2021 -0700 + + Update all submodules + + +Submodule submoduleA f4f55af..310b551 (rewind): +───────────────────────────────────────────────── + < Submodule A extra change 2 + < Submodule A extra change 1 + < Submodule A initial commit 4 + < Submodule A initial commit 3 + +Submodule submoduleB 0ffa700..0c8b00d: +───────────────────────────────────────────────── + > Submodule B stage change 3 + > Submodule B stage change 2 + > Submodule B stage change 1 + +Submodule submoduleC 9f3b744...e04f848: +───────────────────────────────────────────────── + > Submodule C stage change 3 + > Submodule C stage change 2 + < Submodule C extra change 2 + > Submodule C stage change 1 + < Submodule C extra change 1 +"; + const SUBMODULE_CONTAINS_UNTRACKED_CONTENT_INPUT: &str = "\ --- a +++ b -- cgit v1.2.3