@@ -59,14 +59,14 @@ sub exit_cleanup
59
59
60
60
sub use_wt_file
61
61
{
62
- my ($workdir , $ file , $sha1 ) = @_ ;
62
+ my ($file , $sha1 ) = @_ ;
63
63
my $null_sha1 = ' 0' x 40 ;
64
64
65
- if (-l " $workdir / $ file" || ! -e _) {
65
+ if (-l $ file || ! -e _) {
66
66
return (0, $null_sha1 );
67
67
}
68
68
69
- my $wt_sha1 = Git::command_oneline(' hash-object' , " $workdir / $ file" );
69
+ my $wt_sha1 = Git::command_oneline(' hash-object' , $ file );
70
70
my $use = ($sha1 eq $null_sha1 ) || ($sha1 eq $wt_sha1 );
71
71
return ($use , $wt_sha1 );
72
72
}
@@ -100,11 +100,17 @@ sub changed_files
100
100
101
101
sub setup_dir_diff
102
102
{
103
- my ($workdir , $symlinks ) = @_ ;
103
+ my ($worktree , $symlinks ) = @_ ;
104
104
my @gitargs = (' diff' , ' --raw' , ' --no-abbrev' , ' -z' , @ARGV );
105
105
my $diffrtn = Git::command_oneline(@gitargs );
106
106
exit (0) unless defined ($diffrtn );
107
107
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
+
108
114
# Build index info for left and right sides of the diff
109
115
my $submodule_mode = ' 160000' ;
110
116
my $symlink_mode = ' 120000' ;
@@ -115,7 +121,7 @@ sub setup_dir_diff
115
121
my $wtindex = ' ' ;
116
122
my %submodule ;
117
123
my %symlink ;
118
- my @working_tree = ();
124
+ my @files = ();
119
125
my %working_tree_dups = ();
120
126
my @rawdiff = split (' \0' , $diffrtn );
121
127
@@ -167,14 +173,14 @@ sub setup_dir_diff
167
173
}
168
174
169
175
if ($rmode ne $null_mode ) {
170
- # Avoid duplicate working_tree entries
176
+ # Avoid duplicate entries
171
177
if ($working_tree_dups {$dst_path }++) {
172
178
next ;
173
179
}
174
180
my ($use , $wt_sha1 ) =
175
- use_wt_file($workdir , $ dst_path , $rsha1 );
181
+ use_wt_file($dst_path , $rsha1 );
176
182
if ($use ) {
177
- push @working_tree , $dst_path ;
183
+ push @files , $dst_path ;
178
184
$wtindex .= " $rmode $wt_sha1 \t $dst_path \0 " ;
179
185
} else {
180
186
$rindex .= " $rmode $rsha1 \t $dst_path \0 " ;
@@ -184,7 +190,7 @@ sub setup_dir_diff
184
190
185
191
# Go to the root of the worktree so that the left index files
186
192
# are properly setup -- the index is toplevel-relative.
187
- chdir ($workdir );
193
+ chdir ($worktree );
188
194
189
195
# Setup temp directories
190
196
my $tmpdir = tempdir(' git-difftool.XXXXX' , CLEANUP => 0, TMPDIR => 1);
@@ -224,23 +230,21 @@ sub setup_dir_diff
224
230
delete ($ENV {GIT_INDEX_FILE });
225
231
226
232
# 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 ) {
231
235
my $dir = dirname($file );
232
236
unless (-d " $rdir /$dir " ) {
233
237
mkpath(" $rdir /$dir " ) or
234
238
exit_cleanup($tmpdir , 1);
235
239
}
236
240
if ($symlinks ) {
237
- symlink (" $workdir /$file " , " $rdir /$file " ) or
241
+ symlink (" $worktree /$file " , " $rdir /$file " ) or
238
242
exit_cleanup($tmpdir , 1);
239
243
} else {
240
- copy(" $workdir / $ file" , " $rdir /$file " ) or
244
+ copy($ file , " $rdir /$file " ) or
241
245
exit_cleanup($tmpdir , 1);
242
246
243
- my $mode = stat (" $workdir / $ file" )-> mode;
247
+ my $mode = stat ($ file )-> mode;
244
248
chmod ($mode , " $rdir /$file " ) or
245
249
exit_cleanup($tmpdir , 1);
246
250
}
@@ -278,7 +282,7 @@ sub setup_dir_diff
278
282
exit_cleanup($tmpdir , 1) if not $ok ;
279
283
}
280
284
281
- return ($ldir , $rdir , $tmpdir , @working_tree );
285
+ return ($ldir , $rdir , $tmpdir , @files );
282
286
}
283
287
284
288
sub write_to_file
@@ -388,8 +392,9 @@ sub dir_diff
388
392
my $error = 0;
389
393
my $repo = Git-> repository();
390
394
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 );
393
398
394
399
if (defined ($extcmd )) {
395
400
$rc = system ($extcmd , $a , $b );
@@ -410,31 +415,31 @@ sub dir_diff
410
415
my %tmp_modified ;
411
416
my $indices_loaded = 0;
412
417
413
- for my $file (@worktree ) {
418
+ for my $file (@files ) {
414
419
next if $symlinks && -l " $b /$file " ;
415
420
next if ! -f " $b /$file " ;
416
421
417
422
if (!$indices_loaded ) {
418
423
%wt_modified = changed_files(
419
- $repo_path , " $tmpdir /wtindex" , $workdir );
424
+ $repo_path , " $tmpdir /wtindex" , $worktree );
420
425
%tmp_modified = changed_files(
421
426
$repo_path , " $tmpdir /wtindex" , $b );
422
427
$indices_loaded = 1;
423
428
}
424
429
425
430
if (exists $wt_modified {$file } and exists $tmp_modified {$file }) {
426
431
my $errmsg = " warning: Both files modified: " ;
427
- $errmsg .= " '$workdir /$file ' and '$b /$file '.\n " ;
432
+ $errmsg .= " '$worktree /$file ' and '$b /$file '.\n " ;
428
433
$errmsg .= " warning: Working tree file has been left.\n " ;
429
434
$errmsg .= " warning:\n " ;
430
435
warn $errmsg ;
431
436
$error = 1;
432
437
} elsif (exists $tmp_modified {$file }) {
433
438
my $mode = stat (" $b /$file " )-> mode;
434
- copy(" $b /$file " , " $workdir / $ file" ) or
439
+ copy(" $b /$file " , $ file ) or
435
440
exit_cleanup($tmpdir , 1);
436
441
437
- chmod ($mode , " $workdir / $ file" ) or
442
+ chmod ($mode , $ file ) or
438
443
exit_cleanup($tmpdir , 1);
439
444
}
440
445
}
0 commit comments