Skip to content

Commit a558332

Browse files
committed
Merge branch 'jk/difftool-in-subdir' into maint
Even though an fix was attempted in Git 2.9.3 days, but running "git difftool --dir-diff" from a subdirectory never worked. This has been fixed. * jk/difftool-in-subdir: difftool: rename variables for consistency difftool: chdir as early as possible difftool: sanitize $workdir as early as possible difftool: fix dir-diff index creation when in a subdirectory
2 parents aa83f7a + ce69269 commit a558332

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

git-difftool.perl

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ sub exit_cleanup
5959

6060
sub use_wt_file
6161
{
62-
my ($workdir, $file, $sha1) = @_;
62+
my ($file, $sha1) = @_;
6363
my $null_sha1 = '0' x 40;
6464

65-
if (-l "$workdir/$file" || ! -e _) {
65+
if (-l $file || ! -e _) {
6666
return (0, $null_sha1);
6767
}
6868

69-
my $wt_sha1 = Git::command_oneline('hash-object', "$workdir/$file");
69+
my $wt_sha1 = Git::command_oneline('hash-object', $file);
7070
my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1);
7171
return ($use, $wt_sha1);
7272
}
@@ -100,11 +100,17 @@ sub changed_files
100100

101101
sub setup_dir_diff
102102
{
103-
my ($workdir, $symlinks) = @_;
103+
my ($worktree, $symlinks) = @_;
104104
my @gitargs = ('diff', '--raw', '--no-abbrev', '-z', @ARGV);
105105
my $diffrtn = Git::command_oneline(@gitargs);
106106
exit(0) unless defined($diffrtn);
107107

108+
# Go to the root of the worktree now that we've captured the list of
109+
# changed files. The paths returned by diff --raw are relative to the
110+
# top-level of the repository, but we defer changing directories so
111+
# that @ARGV can perform pathspec limiting in the current directory.
112+
chdir($worktree);
113+
108114
# Build index info for left and right sides of the diff
109115
my $submodule_mode = '160000';
110116
my $symlink_mode = '120000';
@@ -115,7 +121,7 @@ sub setup_dir_diff
115121
my $wtindex = '';
116122
my %submodule;
117123
my %symlink;
118-
my @working_tree = ();
124+
my @files = ();
119125
my %working_tree_dups = ();
120126
my @rawdiff = split('\0', $diffrtn);
121127

@@ -167,14 +173,14 @@ sub setup_dir_diff
167173
}
168174

169175
if ($rmode ne $null_mode) {
170-
# Avoid duplicate working_tree entries
176+
# Avoid duplicate entries
171177
if ($working_tree_dups{$dst_path}++) {
172178
next;
173179
}
174180
my ($use, $wt_sha1) =
175-
use_wt_file($workdir, $dst_path, $rsha1);
181+
use_wt_file($dst_path, $rsha1);
176182
if ($use) {
177-
push @working_tree, $dst_path;
183+
push @files, $dst_path;
178184
$wtindex .= "$rmode $wt_sha1\t$dst_path\0";
179185
} else {
180186
$rindex .= "$rmode $rsha1\t$dst_path\0";
@@ -184,7 +190,7 @@ sub setup_dir_diff
184190

185191
# Go to the root of the worktree so that the left index files
186192
# are properly setup -- the index is toplevel-relative.
187-
chdir($workdir);
193+
chdir($worktree);
188194

189195
# Setup temp directories
190196
my $tmpdir = tempdir('git-difftool.XXXXX', CLEANUP => 0, TMPDIR => 1);
@@ -224,23 +230,21 @@ sub setup_dir_diff
224230
delete($ENV{GIT_INDEX_FILE});
225231

226232
# Changes in the working tree need special treatment since they are
227-
# not part of the index. Remove any trailing slash from $workdir
228-
# before starting to avoid double slashes in symlink targets.
229-
$workdir =~ s|/$||;
230-
for my $file (@working_tree) {
233+
# not part of the index.
234+
for my $file (@files) {
231235
my $dir = dirname($file);
232236
unless (-d "$rdir/$dir") {
233237
mkpath("$rdir/$dir") or
234238
exit_cleanup($tmpdir, 1);
235239
}
236240
if ($symlinks) {
237-
symlink("$workdir/$file", "$rdir/$file") or
241+
symlink("$worktree/$file", "$rdir/$file") or
238242
exit_cleanup($tmpdir, 1);
239243
} else {
240-
copy("$workdir/$file", "$rdir/$file") or
244+
copy($file, "$rdir/$file") or
241245
exit_cleanup($tmpdir, 1);
242246

243-
my $mode = stat("$workdir/$file")->mode;
247+
my $mode = stat($file)->mode;
244248
chmod($mode, "$rdir/$file") or
245249
exit_cleanup($tmpdir, 1);
246250
}
@@ -278,7 +282,7 @@ sub setup_dir_diff
278282
exit_cleanup($tmpdir, 1) if not $ok;
279283
}
280284

281-
return ($ldir, $rdir, $tmpdir, @working_tree);
285+
return ($ldir, $rdir, $tmpdir, @files);
282286
}
283287

284288
sub write_to_file
@@ -388,8 +392,9 @@ sub dir_diff
388392
my $error = 0;
389393
my $repo = Git->repository();
390394
my $repo_path = $repo->repo_path();
391-
my $workdir = $repo->wc_path();
392-
my ($a, $b, $tmpdir, @worktree) = setup_dir_diff($workdir, $symlinks);
395+
my $worktree = $repo->wc_path();
396+
$worktree =~ s|/$||; # Avoid double slashes in symlink targets
397+
my ($a, $b, $tmpdir, @files) = setup_dir_diff($worktree, $symlinks);
393398

394399
if (defined($extcmd)) {
395400
$rc = system($extcmd, $a, $b);
@@ -410,31 +415,31 @@ sub dir_diff
410415
my %tmp_modified;
411416
my $indices_loaded = 0;
412417

413-
for my $file (@worktree) {
418+
for my $file (@files) {
414419
next if $symlinks && -l "$b/$file";
415420
next if ! -f "$b/$file";
416421

417422
if (!$indices_loaded) {
418423
%wt_modified = changed_files(
419-
$repo_path, "$tmpdir/wtindex", $workdir);
424+
$repo_path, "$tmpdir/wtindex", $worktree);
420425
%tmp_modified = changed_files(
421426
$repo_path, "$tmpdir/wtindex", $b);
422427
$indices_loaded = 1;
423428
}
424429

425430
if (exists $wt_modified{$file} and exists $tmp_modified{$file}) {
426431
my $errmsg = "warning: Both files modified: ";
427-
$errmsg .= "'$workdir/$file' and '$b/$file'.\n";
432+
$errmsg .= "'$worktree/$file' and '$b/$file'.\n";
428433
$errmsg .= "warning: Working tree file has been left.\n";
429434
$errmsg .= "warning:\n";
430435
warn $errmsg;
431436
$error = 1;
432437
} elsif (exists $tmp_modified{$file}) {
433438
my $mode = stat("$b/$file")->mode;
434-
copy("$b/$file", "$workdir/$file") or
439+
copy("$b/$file", $file) or
435440
exit_cleanup($tmpdir, 1);
436441

437-
chmod($mode, "$workdir/$file") or
442+
chmod($mode, $file) or
438443
exit_cleanup($tmpdir, 1);
439444
}
440445
}

0 commit comments

Comments
 (0)