2222use Getopt::Long qw( :config pass_through) ;
2323use Git;
2424
25- my @working_tree ;
26- my $rc ;
27- my $repo = Git-> repository();
28- my $repo_path = $repo -> repo_path();
29-
3025sub usage
3126{
3227 my $exitcode = shift ;
@@ -43,6 +38,8 @@ sub usage
4338
4439sub find_worktree
4540{
41+ my ($repo ) = @_ ;
42+
4643 # Git->repository->wc_path() does not honor changes to the working
4744 # tree location made by $ENV{GIT_WORK_TREE} or the 'core.worktree'
4845 # config variable.
@@ -61,8 +58,6 @@ sub find_worktree
6158 return $worktree ;
6259}
6360
64- my $workdir = find_worktree();
65-
6661sub print_tool_help
6762{
6863 my ($cmd , @found , @notfound );
@@ -97,10 +92,13 @@ sub print_tool_help
9792
9893sub setup_dir_diff
9994{
95+ my ($repo , $workdir ) = @_ ;
96+
10097 # Run the diff; exit immediately if no diff found
10198 # 'Repository' and 'WorkingCopy' must be explicitly set to insure that
10299 # if $GIT_DIR and $GIT_WORK_TREE are set in ENV, they are actually used
103100 # by Git->repository->command*.
101+ my $repo_path = $repo -> repo_path();
104102 my $diffrepo = Git-> repository(Repository => $repo_path , WorkingCopy => $workdir );
105103 my $diffrtn = $diffrepo -> command_oneline(' diff' , ' --raw' , ' --no-abbrev' , ' -z' , @ARGV );
106104 exit (0) if (length ($diffrtn ) == 0);
@@ -121,6 +119,7 @@ sub setup_dir_diff
121119 my $rindex = ' ' ;
122120 my %submodule ;
123121 my %symlink ;
122+ my @working_tree = ();
124123 my @rawdiff = split (' \0' , $diffrtn );
125124
126125 my $i = 0;
@@ -188,7 +187,7 @@ sub setup_dir_diff
188187 ($inpipe , $ctx ) = $repo -> command_input_pipe(qw/ update-index -z --index-info/ );
189188 print ($inpipe $lindex );
190189 $repo -> command_close_pipe($inpipe , $ctx );
191- $rc = system (' git' , ' checkout-index' , ' --all' , " --prefix=$ldir /" );
190+ my $rc = system (' git' , ' checkout-index' , ' --all' , " --prefix=$ldir /" );
192191 exit ($rc | ($rc >> 8)) if ($rc != 0);
193192
194193 $ENV {GIT_INDEX_FILE } = " $tmpdir /rindex" ;
@@ -238,7 +237,7 @@ sub setup_dir_diff
238237 }
239238 }
240239
241- return ($ldir , $rdir );
240+ return ($ldir , $rdir , @working_tree );
242241}
243242
244243sub write_to_file
@@ -261,54 +260,70 @@ sub write_to_file
261260 close ($fh );
262261}
263262
264- # parse command-line options. all unrecognized options and arguments
265- # are passed through to the 'git diff' command.
266- my ($difftool_cmd , $dirdiff , $extcmd , $gui , $help , $prompt , $tool_help );
267- GetOptions(' g|gui!' => \$gui ,
268- ' d|dir-diff' => \$dirdiff ,
269- ' h' => \$help ,
270- ' prompt!' => \$prompt ,
271- ' y' => sub { $prompt = 0; },
272- ' t|tool:s' => \$difftool_cmd ,
273- ' tool-help' => \$tool_help ,
274- ' x|extcmd:s' => \$extcmd );
275-
276- if (defined ($help )) {
277- usage(0);
278- }
279- if (defined ($tool_help )) {
280- print_tool_help();
281- }
282- if (defined ($difftool_cmd )) {
283- if (length ($difftool_cmd ) > 0) {
284- $ENV {GIT_DIFF_TOOL } = $difftool_cmd ;
285- } else {
286- print " No <tool> given for --tool=<tool>\n " ;
287- usage(1);
263+ sub main
264+ {
265+ # parse command-line options. all unrecognized options and arguments
266+ # are passed through to the 'git diff' command.
267+ my ($difftool_cmd , $dirdiff , $extcmd , $gui , $help , $prompt , $tool_help );
268+ GetOptions(' g|gui!' => \$gui ,
269+ ' d|dir-diff' => \$dirdiff ,
270+ ' h' => \$help ,
271+ ' prompt!' => \$prompt ,
272+ ' y' => sub { $prompt = 0; },
273+ ' t|tool:s' => \$difftool_cmd ,
274+ ' tool-help' => \$tool_help ,
275+ ' x|extcmd:s' => \$extcmd );
276+
277+ if (defined ($help )) {
278+ usage(0);
288279 }
289- }
290- if (defined ($extcmd )) {
291- if (length ($extcmd ) > 0) {
292- $ENV {GIT_DIFFTOOL_EXTCMD } = $extcmd ;
293- } else {
294- print " No <cmd> given for --extcmd=<cmd>\n " ;
295- usage(1);
280+ if (defined ($tool_help )) {
281+ print_tool_help();
296282 }
297- }
298- if ($gui ) {
299- my $guitool = ' ' ;
300- $guitool = Git::config(' diff.guitool' );
301- if (length ($guitool ) > 0) {
302- $ENV {GIT_DIFF_TOOL } = $guitool ;
283+ if (defined ($difftool_cmd )) {
284+ if (length ($difftool_cmd ) > 0) {
285+ $ENV {GIT_DIFF_TOOL } = $difftool_cmd ;
286+ } else {
287+ print " No <tool> given for --tool=<tool>\n " ;
288+ usage(1);
289+ }
290+ }
291+ if (defined ($extcmd )) {
292+ if (length ($extcmd ) > 0) {
293+ $ENV {GIT_DIFFTOOL_EXTCMD } = $extcmd ;
294+ } else {
295+ print " No <cmd> given for --extcmd=<cmd>\n " ;
296+ usage(1);
297+ }
298+ }
299+ if ($gui ) {
300+ my $guitool = ' ' ;
301+ $guitool = Git::config(' diff.guitool' );
302+ if (length ($guitool ) > 0) {
303+ $ENV {GIT_DIFF_TOOL } = $guitool ;
304+ }
305+ }
306+
307+ # In directory diff mode, 'git-difftool--helper' is called once
308+ # to compare the a/b directories. In file diff mode, 'git diff'
309+ # will invoke a separate instance of 'git-difftool--helper' for
310+ # each file that changed.
311+ if (defined ($dirdiff )) {
312+ dir_diff($extcmd );
313+ } else {
314+ file_diff($prompt );
303315 }
304316}
305317
306- # In directory diff mode, 'git-difftool--helper' is called once
307- # to compare the a/b directories. In file diff mode, 'git diff'
308- # will invoke a separate instance of 'git-difftool--helper' for
309- # each file that changed.
310- if (defined ($dirdiff )) {
311- my ($a , $b ) = setup_dir_diff();
318+ sub dir_diff
319+ {
320+ my ($extcmd ) = @_ ;
321+
322+ my $rc ;
323+ my $repo = Git-> repository();
324+
325+ my $workdir = find_worktree($repo );
326+ my ($a , $b , @working_tree ) = setup_dir_diff($repo , $workdir );
312327 if (defined ($extcmd )) {
313328 $rc = system ($extcmd , $a , $b );
314329 } else {
@@ -327,7 +342,12 @@ sub write_to_file
327342 chmod (stat (" $b /$file " )-> mode, " $workdir /$file " ) or die $! ;
328343 }
329344 }
330- } else {
345+ }
346+
347+ sub file_diff
348+ {
349+ my ($prompt ) = @_ ;
350+
331351 if (defined ($prompt )) {
332352 if ($prompt ) {
333353 $ENV {GIT_DIFFTOOL_PROMPT } = ' true' ;
@@ -347,3 +367,5 @@ sub write_to_file
347367 my $rc = system (' git' , ' diff' , @ARGV );
348368 exit ($rc | ($rc >> 8));
349369}
370+
371+ main();
0 commit comments