@@ -60,14 +60,14 @@ sub exit_cleanup
6060
6161sub use_wt_file
6262{
63- my ($workdir , $ file , $sha1 ) = @_ ;
63+ my ($file , $sha1 ) = @_ ;
6464 my $null_sha1 = ' 0' x 40 ;
6565
66- if (-l " $workdir / $ file" || ! -e _) {
66+ if (-l $ file || ! -e _) {
6767 return (0, $null_sha1 );
6868 }
6969
70- my $wt_sha1 = Git::command_oneline(' hash-object' , " $workdir / $ file" );
70+ my $wt_sha1 = Git::command_oneline(' hash-object' , $ file );
7171 my $use = ($sha1 eq $null_sha1 ) || ($sha1 eq $wt_sha1 );
7272 return ($use , $wt_sha1 );
7373}
@@ -101,11 +101,17 @@ sub changed_files
101101
102102sub setup_dir_diff
103103{
104- my ($workdir , $symlinks ) = @_ ;
104+ my ($worktree , $symlinks ) = @_ ;
105105 my @gitargs = (' diff' , ' --raw' , ' --no-abbrev' , ' -z' , @ARGV );
106106 my $diffrtn = Git::command_oneline(@gitargs );
107107 exit (0) unless defined ($diffrtn );
108108
109+ # Go to the root of the worktree now that we've captured the list of
110+ # changed files. The paths returned by diff --raw are relative to the
111+ # top-level of the repository, but we defer changing directories so
112+ # that @ARGV can perform pathspec limiting in the current directory.
113+ chdir ($worktree );
114+
109115 # Build index info for left and right sides of the diff
110116 my $submodule_mode = ' 160000' ;
111117 my $symlink_mode = ' 120000' ;
@@ -116,7 +122,7 @@ sub setup_dir_diff
116122 my $wtindex = ' ' ;
117123 my %submodule ;
118124 my %symlink ;
119- my @working_tree = ();
125+ my @files = ();
120126 my %working_tree_dups = ();
121127 my @rawdiff = split (' \0' , $diffrtn );
122128
@@ -168,14 +174,14 @@ sub setup_dir_diff
168174 }
169175
170176 if ($rmode ne $null_mode ) {
171- # Avoid duplicate working_tree entries
177+ # Avoid duplicate entries
172178 if ($working_tree_dups {$dst_path }++) {
173179 next ;
174180 }
175181 my ($use , $wt_sha1 ) =
176- use_wt_file($workdir , $ dst_path , $rsha1 );
182+ use_wt_file($dst_path , $rsha1 );
177183 if ($use ) {
178- push @working_tree , $dst_path ;
184+ push @files , $dst_path ;
179185 $wtindex .= " $rmode $wt_sha1 \t $dst_path \0 " ;
180186 } else {
181187 $rindex .= " $rmode $rsha1 \t $dst_path \0 " ;
@@ -185,7 +191,7 @@ sub setup_dir_diff
185191
186192 # Go to the root of the worktree so that the left index files
187193 # are properly setup -- the index is toplevel-relative.
188- chdir ($workdir );
194+ chdir ($worktree );
189195
190196 # Setup temp directories
191197 my $tmpdir = tempdir(' git-difftool.XXXXX' , CLEANUP => 0, TMPDIR => 1);
@@ -225,23 +231,21 @@ sub setup_dir_diff
225231 delete ($ENV {GIT_INDEX_FILE });
226232
227233 # Changes in the working tree need special treatment since they are
228- # not part of the index. Remove any trailing slash from $workdir
229- # before starting to avoid double slashes in symlink targets.
230- $workdir =~ s | /$|| ;
231- for my $file (@working_tree ) {
234+ # not part of the index.
235+ for my $file (@files ) {
232236 my $dir = dirname($file );
233237 unless (-d " $rdir /$dir " ) {
234238 mkpath(" $rdir /$dir " ) or
235239 exit_cleanup($tmpdir , 1);
236240 }
237241 if ($symlinks ) {
238- symlink (" $workdir /$file " , " $rdir /$file " ) or
242+ symlink (" $worktree /$file " , " $rdir /$file " ) or
239243 exit_cleanup($tmpdir , 1);
240244 } else {
241- copy(" $workdir / $ file" , " $rdir /$file " ) or
245+ copy($ file , " $rdir /$file " ) or
242246 exit_cleanup($tmpdir , 1);
243247
244- my $mode = stat (" $workdir / $ file" )-> mode;
248+ my $mode = stat ($ file )-> mode;
245249 chmod ($mode , " $rdir /$file " ) or
246250 exit_cleanup($tmpdir , 1);
247251 }
@@ -279,7 +283,7 @@ sub setup_dir_diff
279283 exit_cleanup($tmpdir , 1) if not $ok ;
280284 }
281285
282- return ($ldir , $rdir , $tmpdir , @working_tree );
286+ return ($ldir , $rdir , $tmpdir , @files );
283287}
284288
285289sub write_to_file
@@ -389,8 +393,9 @@ sub dir_diff
389393 my $error = 0;
390394 my $repo = Git-> repository();
391395 my $repo_path = $repo -> repo_path();
392- my $workdir = $repo -> wc_path();
393- my ($a , $b , $tmpdir , @worktree ) = setup_dir_diff($workdir , $symlinks );
396+ my $worktree = $repo -> wc_path();
397+ $worktree =~ s | /$|| ; # Avoid double slashes in symlink targets
398+ my ($a , $b , $tmpdir , @files ) = setup_dir_diff($worktree , $symlinks );
394399
395400 if (defined ($extcmd )) {
396401 $rc = system ($extcmd , $a , $b );
@@ -411,13 +416,13 @@ sub dir_diff
411416 my %tmp_modified ;
412417 my $indices_loaded = 0;
413418
414- for my $file (@worktree ) {
419+ for my $file (@files ) {
415420 next if $symlinks && -l " $b /$file " ;
416421 next if ! -f " $b /$file " ;
417422
418423 if (!$indices_loaded ) {
419424 %wt_modified = changed_files(
420- $repo_path , " $tmpdir /wtindex" , $workdir );
425+ $repo_path , " $tmpdir /wtindex" , $worktree );
421426 %tmp_modified = changed_files(
422427 $repo_path , " $tmpdir /wtindex" , $b );
423428 $indices_loaded = 1;
@@ -428,14 +433,14 @@ sub dir_diff
428433 " warning: Both files modified:\n " .
429434 " '%s /%s ' and '%s /%s '.\n " .
430435 " warning: Working tree file has been left.\n " .
431- " warning:\n " ), $workdir , $file , $b , $file );
436+ " warning:\n " ), $worktree , $file , $b , $file );
432437 $error = 1;
433438 } elsif (exists $tmp_modified {$file }) {
434439 my $mode = stat (" $b /$file " )-> mode;
435- copy(" $b /$file " , " $workdir / $ file" ) or
440+ copy(" $b /$file " , $ file ) or
436441 exit_cleanup($tmpdir , 1);
437442
438- chmod ($mode , " $workdir / $ file" ) or
443+ chmod ($mode , $ file ) or
439444 exit_cleanup($tmpdir , 1);
440445 }
441446 }
0 commit comments