X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git-cvsexportcommit.perl;h=b6036bd4d305215b4a70b6fd0fe54d7607dbe068;hb=340814636dde3cbd2e461b12f9ae832d2100766a;hp=92e41620fd2a998e765a47c2c2ca7085834b14cc;hpb=c78a24986d4d3faff810e87dbcd0ac99f0eabbce;p=git.git diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 92e41620f..b6036bd4d 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -5,6 +5,7 @@ use Getopt::Std; use File::Temp qw(tempdir); use Data::Dumper; use File::Basename qw(basename dirname); +use File::Spec; our ($opt_h, $opt_P, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m, $opt_d, $opt_u, $opt_w); @@ -15,17 +16,15 @@ $opt_h && usage(); die "Need at least one commit identifier!" unless @ARGV; if ($opt_w) { + # Remember where GIT_DIR is before changing to CVS checkout unless ($ENV{GIT_DIR}) { - # Remember where our GIT_DIR is before changing to CVS checkout + # No GIT_DIR set. Figure it out for ourselves my $gd =`git-rev-parse --git-dir`; chomp($gd); - if ($gd eq '.git') { - my $wd = `pwd`; - chomp($wd); - $gd = $wd."/.git" ; - } $ENV{GIT_DIR} = $gd; } + # Make sure GIT_DIR is absolute + $ENV{GIT_DIR} = File::Spec->rel2abs($ENV{GIT_DIR}); if (! -d $opt_w."/CVS" ) { die "$opt_w is not a CVS checkout"; @@ -195,18 +194,42 @@ foreach my $f (@files) { my %cvsstat; if (@canstatusfiles) { if ($opt_u) { - my @updated = safe_pipe_capture(@cvs, 'update', @canstatusfiles); + my @updated = xargs_safe_pipe_capture([@cvs, 'update'], @canstatusfiles); print @updated; } - my @cvsoutput; - @cvsoutput= safe_pipe_capture(@cvs, 'status', @canstatusfiles); - my $matchcount = 0; - foreach my $l (@cvsoutput) { - chomp $l; - if ( $l =~ /^File:/ and $l =~ /Status: (.*)$/ ) { - $cvsstat{$canstatusfiles[$matchcount]} = $1; - $matchcount++; + # "cvs status" reorders the parameters, notably when there are multiple + # arguments with the same basename. So be precise here. + + my %added = map { $_ => 1 } @afiles; + my %todo = map { $_ => 1 } @canstatusfiles; + + while (%todo) { + my @canstatusfiles2 = (); + my %fullname = (); + foreach my $name (keys %todo) { + my $basename = basename($name); + + $basename = "no file " . $basename if (exists($added{$basename})); + chomp($basename); + + if (!exists($fullname{$basename})) { + $fullname{$basename} = $name; + push (@canstatusfiles2, $name); + delete($todo{$name}); } + } + my @cvsoutput; + @cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles2); + foreach my $l (@cvsoutput) { + chomp $l; + if ($l =~ /^File:\s+(.*\S)\s+Status: (.*)$/) { + if (!exists($fullname{$1})) { + print STDERR "Huh? Status reported for unexpected file '$1'\n"; + } else { + $cvsstat{$fullname{$1}} = $2; + } + } + } } } @@ -295,7 +318,7 @@ if ($dirtypatch) { if ($opt_c) { print "Autocommit\n $cmd\n"; - print safe_pipe_capture(@cvs, 'commit', '-F', '.msg', @files); + print xargs_safe_pipe_capture([@cvs, 'commit', '-F', '.msg'], @files); if ($?) { die "Exiting: The commit did not succeed"; } @@ -335,15 +358,24 @@ sub safe_pipe_capture { return wantarray ? @output : join('',@output); } -sub safe_pipe_capture_blob { - my $output; - if (my $pid = open my $child, '-|') { - local $/; - undef $/; - $output = (<$child>); - close $child or die join(' ',@_).": $! $?"; - } else { - exec(@_) or die "$! $?"; # exec() can fail the executable can't be found - } - return $output; +sub xargs_safe_pipe_capture { + my $MAX_ARG_LENGTH = 65536; + my $cmd = shift; + my @output; + my $output; + while(@_) { + my @args; + my $length = 0; + while(@_ && $length < $MAX_ARG_LENGTH) { + push @args, shift; + $length += length($args[$#args]); + } + if (wantarray) { + push @output, safe_pipe_capture(@$cmd, @args); + } + else { + $output .= safe_pipe_capture(@$cmd, @args); + } + } + return wantarray ? @output : $output; }