aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2007-12-14 04:15:47 -0500
committerJunio C Hamano <gitster@pobox.com>2007-12-14 12:06:04 -0800
commit38a5b1d6ed2ba632504be7748e63f1441c93976d (patch)
tree557ba97485246ff7fd626221928c81a06b9b549f
parent71362bd55280bb0f4aa67f89435308a4b26213b5 (diff)
downloadgit-38a5b1d6ed2ba632504be7748e63f1441c93976d.tar.gz
git-38a5b1d6ed2ba632504be7748e63f1441c93976d.tar.xz
cvsexportcommit: fix massive commits
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>
-rwxr-xr-xgit-cvsexportcommit.perl37
1 files changed, 23 insertions, 14 deletions
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index 92e41620f..d2e50c342 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -195,11 +195,11 @@ 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);
+ @cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles);
my $matchcount = 0;
foreach my $l (@cvsoutput) {
chomp $l;
@@ -295,7 +295,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 +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;
}