@@ -92,7 +92,7 @@ sub print_tool_help
9292
9393sub setup_dir_diff
9494{
95- my ($repo , $workdir ) = @_ ;
95+ my ($repo , $workdir , $symlinks ) = @_ ;
9696
9797 # Run the diff; exit immediately if no diff found
9898 # 'Repository' and 'WorkingCopy' must be explicitly set to insure that
@@ -209,8 +209,13 @@ sub setup_dir_diff
209209 unless (-d " $rdir /$dir " ) {
210210 mkpath(" $rdir /$dir " ) or die $! ;
211211 }
212- copy(" $workdir /$file " , " $rdir /$file " ) or die $! ;
213- chmod (stat (" $workdir /$file " )-> mode, " $rdir /$file " ) or die $! ;
212+ if ($symlinks ) {
213+ symlink (" $workdir /$file " , " $rdir /$file " ) or die $! ;
214+ } else {
215+ copy(" $workdir /$file " , " $rdir /$file " ) or die $! ;
216+ my $mode = stat (" $workdir /$file " )-> mode;
217+ chmod ($mode , " $rdir /$file " ) or die $! ;
218+ }
214219 }
215220
216221 # Changes to submodules require special treatment. This loop writes a
@@ -271,13 +276,16 @@ sub main
271276 gui => undef ,
272277 help => undef ,
273278 prompt => undef ,
279+ symlinks => $^O ne ' MSWin32' && $^O ne ' msys' ,
274280 tool_help => undef ,
275281 );
276282 GetOptions(' g|gui!' => \$opts {gui },
277283 ' d|dir-diff' => \$opts {dirdiff },
278284 ' h' => \$opts {help },
279285 ' prompt!' => \$opts {prompt },
280286 ' y' => sub { $opts {prompt } = 0; },
287+ ' symlinks' => \$opts {symlinks },
288+ ' no-symlinks' => sub { $opts {symlinks } = 0; },
281289 ' t|tool:s' => \$opts {difftool_cmd },
282290 ' tool-help' => \$opts {tool_help },
283291 ' x|extcmd:s' => \$opts {extcmd });
@@ -316,21 +324,21 @@ sub main
316324 # will invoke a separate instance of 'git-difftool--helper' for
317325 # each file that changed.
318326 if (defined ($opts {dirdiff })) {
319- dir_diff($opts {extcmd });
327+ dir_diff($opts {extcmd }, $opts { symlinks } );
320328 } else {
321329 file_diff($opts {prompt });
322330 }
323331}
324332
325333sub dir_diff
326334{
327- my ($extcmd ) = @_ ;
335+ my ($extcmd , $symlinks ) = @_ ;
328336
329337 my $rc ;
330338 my $repo = Git-> repository();
331339
332340 my $workdir = find_worktree($repo );
333- my ($a , $b , @working_tree ) = setup_dir_diff($repo , $workdir );
341+ my ($a , $b , @worktree ) = setup_dir_diff($repo , $workdir , $symlinks );
334342 if (defined ($extcmd )) {
335343 $rc = system ($extcmd , $a , $b );
336344 } else {
@@ -342,13 +350,18 @@ sub dir_diff
342350
343351 # If the diff including working copy files and those
344352 # files were modified during the diff, then the changes
345- # should be copied back to the working tree
346- for my $file (@working_tree ) {
347- if (-e " $b /$file " && compare(" $b /$file " , " $workdir /$file " )) {
353+ # should be copied back to the working tree.
354+ # Do not copy back files when symlinks are used and the
355+ # external tool did not replace the original link with a file.
356+ for my $file (@worktree ) {
357+ next if $symlinks && -l " $b /$file " ;
358+ if (-f " $b /$file " && compare(" $b /$file " , " $workdir /$file " )) {
348359 copy(" $b /$file " , " $workdir /$file " ) or die $! ;
349- chmod (stat (" $b /$file " )-> mode, " $workdir /$file " ) or die $! ;
360+ my $mode = stat (" $b /$file " )-> mode;
361+ chmod ($mode , " $workdir /$file " ) or die $! ;
350362 }
351363 }
364+ exit (0);
352365}
353366
354367sub file_diff
0 commit comments