Skip to content

Commit 456a265

Browse files
committed
diff: --no-index should ignore the worktree
The act of giving "--no-index" tells Git to pretend that the current directory is not under control of any Git index or repository, so even when you happen to be in a Git controlled working tree, where in that working tree should not matter. But the start-up sequence tries to discover the top of the working tree and chdir(2)'s there, even before Git passes control to the subcommand being run. When diff_no_index() starts running, it starts at a wrong (from the end-user's point of view who thinks "git diff --no-index" is merely a better version of GNU diff) directory, and the original directory the user started the command is at "prefix". Because the paths given from argv[] have already been adjusted to account for this path shuffling by prepending the prefix, and showing the resulting path by stripping the prefix, the effect of these nonsense operations (nonsense in the context of "--no-index", that is) is usually not observable. Except for special cases like "-", where it is not preprocessed by prepending the prefix. Instead of papering over by adding more special cases only to cater to the no-index codepath in the generic code, drive the diff machinery more faithfully to what is going on. If the user started "git diff --no-index" in directory X/Y/Z in a working tree controlled by Git, and the start up sequence of Git chdir(2)'ed up to directory X and left Y/Z in the prefix, revert the effect of the start up sequence by chdir'ing back to Y/Z and emptying the prefix. Reported-by: Gregoire Geis <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2c2ba49 commit 456a265

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

builtin/diff.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,20 @@ int cmd_diff(int argc,
487487

488488
init_diff_ui_defaults();
489489
repo_config(the_repository, git_diff_ui_config, NULL);
490+
491+
/*
492+
* If we are ignoring the fact that our current directory may
493+
* be part of a working tree controlled by a Git repository to
494+
* pretend to be a "better GNU diff", we should undo the
495+
* effect of the setup code that did a chdir() to the top of
496+
* the working tree. Where we came from is recorded in the
497+
* prefix.
498+
*/
499+
if (no_index && prefix) {
500+
chdir(prefix);
501+
prefix = NULL;
502+
}
503+
490504
prefix = precompose_argv_prefix(argc, argv, prefix);
491505

492506
repo_init_revisions(the_repository, &rev, prefix);

t/t4053-diff-no-index.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ test_expect_success 'git diff --no-index directories' '
2626
test_line_count = 14 cnt
2727
'
2828

29+
test_expect_success 'git diff --no-index with -' '
30+
cat >expect <<-\EOF &&
31+
diff --git a/- b/-
32+
new file mode 100644
33+
--- /dev/null
34+
+++ b/-
35+
@@ -0,0 +1 @@
36+
+frotz
37+
EOF
38+
(
39+
cd a &&
40+
echo frotz |
41+
test_expect_code 1 git diff --no-index /dev/null - >../actual
42+
) &&
43+
test_cmp expect actual
44+
'
45+
2946
test_expect_success 'git diff --no-index relative path outside repo' '
3047
(
3148
cd repo &&

0 commit comments

Comments
 (0)