Skip to content

Commit

Permalink
cvsexportcommit: fix massive commits
Browse files Browse the repository at this point in the history
Because we feed the changed filenames to CVS on the command
line, it was possible for massive commits to overflow the
system exec limits. Instead, we now do an xargs-like split
of the arguments.

This means that we lose some of the atomicity of calling CVS
in one shot. Since CVS commits are not atomic, but the CVS
protocol is, the possible effects of this are not clear;
however, since CVS doesn't provide a different interface,
this is our only option for large commits (short of writing
a CVS client library).

The argument size limit is arbitrarily set to 64kB. This
should be high enough to trigger only in rare cases where it
is necessary, so normal-sized commits are not affected by
the atomicity change.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Dec 14, 2007
1 parent 71362bd commit 38a5b1d
Showing 1 changed file with 23 additions and 14 deletions.
37 changes: 23 additions & 14 deletions git-cvsexportcommit.perl
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,11 @@
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);
@cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles);
my $matchcount = 0;
foreach my $l (@cvsoutput) {
chomp $l;
Expand Down Expand Up @@ -295,7 +295,7 @@

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";
}
Expand Down Expand Up @@ -335,15 +335,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;
}

0 comments on commit 38a5b1d

Please sign in to comment.