difftool: avoid $GIT_DIR and $GIT_WORK_TREE

Environment variables are global and hard to reason about. Use the `--git-dir` and `--work-tree` arguments when invoking `git` instead of relying on the environment. Add a test to ensure that difftool's dir-diff feature works when these variables are present in the environment. Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Aguilar committed Jul 18, 2016 at 20:57 UTC 98f917ed421a477e0575c58f801ac25f0e261b9d
2 files changed +20 -21
git-difftool.perl
+6 -21
@@ -83,20 +83,17 @@ sub changed_files
83 {
84 my ($repo_path, $index, $worktree) = @_;
85 $ENV{GIT_INDEX_FILE} = $index;
86 - $ENV{GIT_WORK_TREE} = $worktree;
87 - my $must_unset_git_dir = 0;
88 - if (not defined($ENV{GIT_DIR})) {
89 - $must_unset_git_dir = 1;
90 - $ENV{GIT_DIR} = $repo_path;
91 - }
86
93 - my @refreshargs = qw/update-index --really-refresh -q --unmerged/;
94 - my @gitargs = qw/diff-files --name-only -z/;
87 + my @gitargs = ('--git-dir', $repo_path, '--work-tree', $worktree);
88 + my @refreshargs = (
89 + @gitargs, 'update-index',
90 + '--really-refresh', '-q', '--unmerged');
91 try {
92 Git::command_oneline(@refreshargs);
93 } catch Git::Error::Command with {};
94
99 - my $line = Git::command_oneline(@gitargs);
95 + my @diffargs = (@gitargs, 'diff-files', '--name-only', '-z');
96 + my $line = Git::command_oneline(@diffargs);
97 my @files;
98 if (defined $line) {
99 @files = split('\0', $line);
@@ -105,8 +102,6 @@ sub changed_files
102 }
103
104 delete($ENV{GIT_INDEX_FILE});
108 - delete($ENV{GIT_WORK_TREE});
109 - delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
105
106 return map { $_ => 1 } @files;
107 }
@@ -204,15 +199,6 @@ EOF
199 mkpath($ldir) or exit_cleanup($tmpdir, 1);
200 mkpath($rdir) or exit_cleanup($tmpdir, 1);
201
207 - # If $GIT_DIR is not set prior to calling 'git update-index' and
208 - # 'git checkout-index', then those commands will fail if difftool
209 - # is called from a directory other than the repo root.
210 - my $must_unset_git_dir = 0;
211 - if (not defined($ENV{GIT_DIR})) {
212 - $must_unset_git_dir = 1;
213 - $ENV{GIT_DIR} = $repo_path;
214 - }
215 -
202 # Populate the left and right directories based on each index file
203 my ($inpipe, $ctx);
204 $ENV{GIT_INDEX_FILE} = "$tmpdir/lindex";
@@ -241,7 +227,6 @@ EOF
227
228 # If $GIT_DIR was explicitly set just for the update/checkout
229 # commands, then it should be unset before continuing.
244 - delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
230 delete($ENV{GIT_INDEX_FILE});
231
232 # Changes in the working tree need special treatment since they are
t/t7800-difftool.sh
+14
@@ -412,6 +412,20 @@ run_dir_diff_test 'difftool --dir-diff from subdirectory' '
412 )
413 '
414
415 +run_dir_diff_test 'difftool --dir-diff from subdirectory with GIT_DIR set' '
416 + (
417 + GIT_DIR=$(pwd)/.git &&
418 + export GIT_DIR &&
419 + GIT_WORK_TREE=$(pwd) &&
420 + export GIT_WORK_TREE &&
421 + cd sub &&
422 + git difftool --dir-diff $symlinks --extcmd ls \
423 + branch -- sub >output &&
424 + grep sub output &&
425 + ! grep file output
426 + )
427 +'
428 +
429 run_dir_diff_test 'difftool --dir-diff when worktree file is missing' '
430 test_when_finished git reset --hard &&
431 rm file2 &&