Git fork

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 <opensource@gregoirege.is>
Helped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

+32
+15
builtin/diff.c
··· 487 487 488 488 init_diff_ui_defaults(); 489 489 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 + if (chdir(prefix)) 501 + die(_("cannot come back to cwd")); 502 + prefix = NULL; 503 + } 504 + 490 505 prefix = precompose_argv_prefix(argc, argv, prefix); 491 506 492 507 repo_init_revisions(the_repository, &rev, prefix);
+17
t/t4053-diff-no-index.sh
··· 26 26 test_line_count = 14 cnt 27 27 ' 28 28 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 + 29 46 test_expect_success 'git diff --no-index relative path outside repo' ' 30 47 ( 31 48 cd repo &&