During a merge conflict, "git diff --relative" in a subdirectory still prints paths from the repository root. Combined raw output does the same.
Strip the requested prefix when printing these paths. Keep the original paths for reading files from the working tree.
Make the known failure in t4045 a passing test, and cover explicit prefixes, --no-relative, raw and NUL-separated output, quoted filenames and renamed parent paths.
Signed-off-by: Muhammed Dilshad A <dilsheddilu123@gmail.com> --- combine-diff.c | 19 +++++++++--- t/t4038-diff-combined.sh | 22 ++++++++++++++ t/t4045-diff-relative.sh | 62 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 5 deletions(-)
Show changes to 3 files +98 −5
combine-diff.c, t/t4038-diff-combined.sh, t/t4045-diff-relative.sh
diff --git a/combine-diff.c b/combine-diff.c index 717d537688..78d2852cce 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -902,6 +902,14 @@ static void reuse_combine_diff(struct sline *sline, unsigned long cnt, sline->p_lno[i] = sline->p_lno[j]; } +static const char *strip_relative_prefix(const struct diff_options *opt, + const char *path) +{ + if (opt->prefix && skip_prefix(path, opt->prefix, &path) && *path == '/') + path++; + return path; +} + static void dump_quoted_path(const char *head, const char *prefix, const char *path, @@ -932,6 +940,7 @@ static void show_combined_header(struct combine_diff_path *elem, const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; const char *c_meta = diff_get_color_opt(opt, DIFF_METAINFO); const char *c_reset = diff_get_color_opt(opt, DIFF_RESET); + const char *name = strip_relative_prefix(opt, elem->path); const char *abb; int added = 0; int deleted = 0; @@ -942,7 +951,7 @@ static void show_combined_header(struct combine_diff_path *elem, show_log(rev); dump_quoted_path(dense ? "diff --cc " : "diff --combined ", - "", elem->path, line_prefix, c_meta, c_reset); + "", name, line_prefix, c_meta, c_reset); printf("%s%sindex ", line_prefix, c_meta); for (i = 0; i < num_parent; i++) { abb = repo_find_unique_abbrev(the_repository, @@ -987,6 +996,7 @@ static void show_combined_header(struct combine_diff_path *elem, const char *path = elem->parent[i].path ? elem->parent[i].path : elem->path; + path = strip_relative_prefix(opt, path); if (elem->parent[i].status == DIFF_STATUS_ADDED) dump_quoted_path("--- ", "", "/dev/null", line_prefix, c_meta, c_reset); @@ -999,14 +1009,14 @@ static void show_combined_header(struct combine_diff_path *elem, dump_quoted_path("--- ", "", "/dev/null", line_prefix, c_meta, c_reset); else - dump_quoted_path("--- ", a_prefix, elem->path, + dump_quoted_path("--- ", a_prefix, name, line_prefix, c_meta, c_reset); } if (deleted) dump_quoted_path("+++ ", "", "/dev/null", line_prefix, c_meta, c_reset); else - dump_quoted_path("+++ ", b_prefix, elem->path, + dump_quoted_path("+++ ", b_prefix, name, line_prefix, c_meta, c_reset); } @@ -1270,9 +1280,10 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re const char *path = p->parent[i].path ? p->parent[i].path : p->path; + path = strip_relative_prefix(opt, path); write_name_quoted(path, stdout, inter_name_termination); } - write_name_quoted(p->path, stdout, line_termination); + write_name_quoted(strip_relative_prefix(opt, p->path), stdout, line_termination); } /* diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh index e11b711388..2575c06360 100755 --- a/t/t4038-diff-combined.sh +++ b/t/t4038-diff-combined.sh @@ -492,6 +492,28 @@ test_expect_success '--combined-all-paths and --cc' ' test_cmp expect actual ' +test_expect_success '--combined-all-paths and --raw with relative renamed paths' ' + cat <<-EOF >expect && + ::100644 100644 100644 $side1cf $side2cf $mergedf RR side1c side2c merged + EOF + git diff-tree -c -M --raw --combined-all-paths \ + --relative=filename- HEAD >actual.tmp && + sed 1d <actual.tmp >actual && + test_cmp expect actual +' + +test_expect_success '--combined-all-paths and --cc with relative renamed paths' ' + cat <<-\EOF >expect && + --- a/side1c + --- a/side2c + +++ b/merged + EOF + git diff-tree --cc -M --combined-all-paths \ + --relative=filename- HEAD >actual.tmp && + grep ^[-+][-+][-+] <actual.tmp >actual && + test_cmp expect actual +' + test_expect_success FUNNYNAMES 'setup for --combined-all-paths with funny names' ' git branch side1d && git branch side2d && diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh index 167be0bdcc..f105ddcfd1 100755 --- a/t/t4045-diff-relative.sh +++ b/t/t4045-diff-relative.sh @@ -223,7 +223,7 @@ test_expect_success 'diff --relative --name-only with change in subdir' ' test_cmp expected out ' -test_expect_failure 'diff --relative with change in subdir' ' +test_expect_success 'diff --relative with change in subdir' ' git switch br3 && br1_blob=$(git rev-parse --short --verify br1:subdir/file0) && br3_blob=$(git rev-parse --short --verify br3:subdir/file0) && @@ -242,6 +242,44 @@ test_expect_failure 'diff --relative with change in subdir' ' ++>>>>>>> br1 EOF git -C subdir diff --relative >out && + test_cmp expected out && + git diff --relative=subdir >out && + test_cmp expected out && + git diff --relative=subdir/ >out && + test_cmp expected out && + sed "s,file0,dir/file0,g" expected >expected-short && + git diff --relative=sub >out && + test_cmp expected-short out && + sed "s,file0,subdir/file0,g" expected >expected-full && + git diff --relative=subdir --no-relative -- subdir/file0 >out && + test_cmp expected-full out +' + +test_expect_success 'combined raw diff with relative paths' ' + git switch br3 && + br1_blob=$(git rev-parse --short --verify br1:subdir/file0) && + br3_blob=$(git rev-parse --short --verify br3:subdir/file0) && + test_when_finished "git merge --abort" && + test_must_fail git merge br1 && + printf "::100644 100644 100644 %s %s 0000000 MM\tfile0\n" \ + "$br3_blob" "$br1_blob" >expected && + git -C subdir diff --cc --raw --relative >out && + test_cmp expected out && + printf "::100644 100644 100644 %s %s 0000000 MM\0file0\0" \ + "$br3_blob" "$br1_blob" >expected && + git diff --cc --raw -z --relative=subdir >out && + test_cmp expected out +' + +test_expect_success 'combined raw diff lists all relative paths' ' + git switch br3 && + br1_blob=$(git rev-parse --short --verify br1:subdir/file0) && + br3_blob=$(git rev-parse --short --verify br3:subdir/file0) && + test_when_finished "git merge --abort" && + test_must_fail git merge br1 && + printf "::100644 100644 100644 %s %s 0000000 MM\tfile0\tfile0\tfile0\n" \ + "$br3_blob" "$br1_blob" >expected && + git diff --cc --raw --combined-all-paths --relative=subdir >out && test_cmp expected out ' @@ -254,4 +292,26 @@ test_expect_success 'diff --relative --cached with change in subdir' ' test_cmp expected out ' +test_expect_success FUNNYNAMES 'combined diff quotes relative paths' ' + test_create_repo quoted && + ( + cd quoted && + mkdir subdir && + test_commit --no-tag base "subdir/quoted\"file" base && + git switch -c side && + test_commit --no-tag side "subdir/quoted\"file" side && + git switch -c other HEAD^ && + test_commit --no-tag other "subdir/quoted\"file" other && + test_must_fail git merge side && + cat >expected <<-\EOF && + diff --cc "quoted\"file" + --- "a/quoted\"file" + +++ "b/quoted\"file" + EOF + git -C subdir diff --relative >out && + sed -n "/^diff --cc /p; /^--- /p; /^+++ /p" out >actual && + test_cmp expected actual + ) +' + test_done base-commit: 6de20f6092dcf9bdb1c8efe03db4b70c82b423dd
-- 2.55.0