Merge branch 'master' into next

* master:
  Add git-quiltimport to .gitignore.
  cvsimport: introduce _fetchfile() method and used a 1M buffer to read()
  cvsimport: cleanup commit function
  cvsimport: use git-update-index --index-info
  git status: skip empty directories, and add -u to show all untracked files
  cvsimport: repack every kilo-commits.
  cvsimport: introduce -L<imit> option to workaround memory leaks
This commit is contained in:
Junio C Hamano 2006-05-23 01:26:34 -07:00
commit 646881a156
3 changed files with 121 additions and 131 deletions

1
.gitignore vendored
View File

@ -77,6 +77,7 @@ git-prune
git-prune-packed git-prune-packed
git-pull git-pull
git-push git-push
git-quiltimport
git-read-tree git-read-tree
git-rebase git-rebase
git-receive-pack git-receive-pack

View File

@ -3,7 +3,7 @@
# Copyright (c) 2005 Linus Torvalds # Copyright (c) 2005 Linus Torvalds
# Copyright (c) 2006 Junio C Hamano # Copyright (c) 2006 Junio C Hamano
USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>) [--amend] [-e] [--author <author>] [[-i | -o] <path>...]' USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-u] [--amend] [-e] [--author <author>] [[-i | -o] <path>...]'
SUBDIRECTORY_OK=Yes SUBDIRECTORY_OK=Yes
. git-sh-setup . git-sh-setup
@ -134,13 +134,17 @@ run_status () {
report "Changed but not updated" \ report "Changed but not updated" \
"use git-update-index to mark for commit" "use git-update-index to mark for commit"
option=""
if test -z "$untracked_files"; then
option="--directory --no-empty-directory"
fi
if test -f "$GIT_DIR/info/exclude" if test -f "$GIT_DIR/info/exclude"
then then
git-ls-files -z --others --directory \ git-ls-files -z --others $option \
--exclude-from="$GIT_DIR/info/exclude" \ --exclude-from="$GIT_DIR/info/exclude" \
--exclude-per-directory=.gitignore --exclude-per-directory=.gitignore
else else
git-ls-files -z --others --directory \ git-ls-files -z --others $option \
--exclude-per-directory=.gitignore --exclude-per-directory=.gitignore
fi | fi |
perl -e '$/ = "\0"; perl -e '$/ = "\0";
@ -203,6 +207,7 @@ verbose=
signoff= signoff=
force_author= force_author=
only_include_assumed= only_include_assumed=
untracked_files=
while case "$#" in 0) break;; esac while case "$#" in 0) break;; esac
do do
case "$1" in case "$1" in
@ -340,6 +345,12 @@ do
verbose=t verbose=t
shift shift
;; ;;
-u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|--untracked|\
--untracked-|--untracked-f|--untracked-fi|--untracked-fil|--untracked-file|\
--untracked-files)
untracked_files=t
shift
;;
--) --)
shift shift
break break

View File

@ -23,13 +23,13 @@ use File::Basename qw(basename dirname);
use Time::Local; use Time::Local;
use IO::Socket; use IO::Socket;
use IO::Pipe; use IO::Pipe;
use POSIX qw(strftime dup2); use POSIX qw(strftime dup2 :errno_h);
use IPC::Open2; use IPC::Open2;
$SIG{'PIPE'}="IGNORE"; $SIG{'PIPE'}="IGNORE";
$ENV{'TZ'}="UTC"; $ENV{'TZ'}="UTC";
our($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,$opt_M,$opt_A,$opt_S); our($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,$opt_M,$opt_A,$opt_S,$opt_L);
my (%conv_author_name, %conv_author_email); my (%conv_author_name, %conv_author_email);
sub usage() { sub usage() {
@ -85,7 +85,7 @@ sub write_author_info($) {
close ($f); close ($f);
} }
getopts("hivmkuo:d:p:C:z:s:M:P:A:S:") or usage(); getopts("hivmkuo:d:p:C:z:s:M:P:A:S:L:") or usage();
usage if $opt_h; usage if $opt_h;
@ARGV <= 1 or usage(); @ARGV <= 1 or usage();
@ -315,15 +315,7 @@ sub _line {
chomp $cnt; chomp $cnt;
die "Duh: Filesize $cnt" if $cnt !~ /^\d+$/; die "Duh: Filesize $cnt" if $cnt !~ /^\d+$/;
$line=""; $line="";
$res=0; $res = $self->_fetchfile($fh, $cnt);
while($cnt) {
my $buf;
my $num = $self->{'socketi'}->read($buf,$cnt);
die "Server: Filesize $cnt: $num: $!\n" if not defined $num or $num<=0;
print $fh $buf;
$res += $num;
$cnt -= $num;
}
} elsif($line =~ s/^ //) { } elsif($line =~ s/^ //) {
print $fh $line; print $fh $line;
$res += length($line); $res += length($line);
@ -335,14 +327,7 @@ sub _line {
chomp $cnt; chomp $cnt;
die "Duh: Mbinary $cnt" if $cnt !~ /^\d+$/ or $cnt<1; die "Duh: Mbinary $cnt" if $cnt !~ /^\d+$/ or $cnt<1;
$line=""; $line="";
while($cnt) { $res += $self->_fetchfile($fh, $cnt);
my $buf;
my $num = $self->{'socketi'}->read($buf,$cnt);
die "S: Mbinary $cnt: $num: $!\n" if not defined $num or $num<=0;
print $fh $buf;
$res += $num;
$cnt -= $num;
}
} else { } else {
chomp $line; chomp $line;
if($line eq "ok") { if($line eq "ok") {
@ -384,6 +369,23 @@ sub file {
return ($name, $res); return ($name, $res);
} }
sub _fetchfile {
my ($self, $fh, $cnt) = @_;
my $res;
my $bufsize = 1024 * 1024;
while($cnt) {
if ($bufsize > $cnt) {
$bufsize = $cnt;
}
my $buf;
my $num = $self->{'socketi'}->read($buf,$bufsize);
die "Server: Filesize $cnt: $num: $!\n" if not defined $num or $num<=0;
print $fh $buf;
$res += $num;
$cnt -= $num;
}
return $res;
}
package main; package main;
@ -429,21 +431,24 @@ sub getwd() {
return $pwd; return $pwd;
} }
sub is_sha1 {
sub get_headref($$) { my $s = shift;
my $name = shift; return $s =~ /^[a-f0-9]{40}$/;
my $git_dir = shift;
my $sha;
if (open(C,"$git_dir/refs/heads/$name")) {
chomp($sha = <C>);
close(C);
length($sha) == 40
or die "Cannot get head id for $name ($sha): $!\n";
}
return $sha;
} }
sub get_headref ($$) {
my $name = shift;
my $git_dir = shift;
my $f = "$git_dir/refs/heads/$name";
if(open(my $fh, $f)) {
chomp(my $r = <$fh>);
is_sha1($r) or die "Cannot get head id for $name ($r): $!";
return $r;
}
die "unable to open $f: $!" unless $! == POSIX::ENOENT;
return undef;
}
-d $git_tree -d $git_tree
or mkdir($git_tree,0777) or mkdir($git_tree,0777)
@ -561,100 +566,67 @@ unless($pid) {
my $state = 0; my $state = 0;
sub update_index (\@\@) {
my $old = shift;
my $new = shift;
open(my $fh, '|-', qw(git-update-index -z --index-info))
or die "unable to open git-update-index: $!";
print $fh
(map { "0 0000000000000000000000000000000000000000\t$_\0" }
@$old),
(map { '100' . sprintf('%o', $_->[0]) . " $_->[1]\t$_->[2]\0" }
@$new)
or die "unable to write to git-update-index: $!";
close $fh
or die "unable to write to git-update-index: $!";
$? and die "git-update-index reported error: $?";
}
sub write_tree () {
open(my $fh, '-|', qw(git-write-tree))
or die "unable to open git-write-tree: $!";
chomp(my $tree = <$fh>);
is_sha1($tree)
or die "Cannot get tree id ($tree): $!";
close($fh)
or die "Error running git-write-tree: $?\n";
print "Tree ID $tree\n" if $opt_v;
return $tree;
}
my($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg); my($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg);
my(@old,@new,@skipped); my(@old,@new,@skipped);
sub commit { sub commit {
my $pid; update_index(@old, @new);
while(@old) { @old = @new = ();
my @o2; my $tree = write_tree();
if(@old > 55) { my $parent = get_headref($last_branch, $git_dir);
@o2 = splice(@old,0,50); print "Parent ID " . ($parent ? $parent : "(empty)") . "\n" if $opt_v;
} else {
@o2 = @old; my @commit_args;
@old = (); push @commit_args, ("-p", $parent) if $parent;
# loose detection of merges
# based on the commit msg
foreach my $rx (@mergerx) {
next unless $logmsg =~ $rx && $1;
my $mparent = $1 eq 'HEAD' ? $opt_o : $1;
if(my $sha1 = get_headref($mparent, $git_dir)) {
push @commit_args, '-p', $mparent;
print "Merge parent branch: $mparent\n" if $opt_v;
} }
system("git-update-index","--force-remove","--",@o2);
die "Cannot remove files: $?\n" if $?;
}
while(@new) {
my @n2;
if(@new > 12) {
@n2 = splice(@new,0,10);
} else {
@n2 = @new;
@new = ();
}
system("git-update-index","--add",
(map { ('--cacheinfo', @$_) } @n2));
die "Cannot add files: $?\n" if $?;
} }
$pid = open(C,"-|"); my $commit_date = strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date));
die "Cannot fork: $!" unless defined $pid; my $pid = open2(my $commit_read, my $commit_write,
unless($pid) { 'env',
exec("git-write-tree"); "GIT_AUTHOR_NAME=$author_name",
die "Cannot exec git-write-tree: $!\n"; "GIT_AUTHOR_EMAIL=$author_email",
} "GIT_AUTHOR_DATE=$commit_date",
chomp(my $tree = <C>); "GIT_COMMITTER_NAME=$author_name",
length($tree) == 40 "GIT_COMMITTER_EMAIL=$author_email",
or die "Cannot get tree id ($tree): $!\n"; "GIT_COMMITTER_DATE=$commit_date",
close(C) 'git-commit-tree', $tree, @commit_args);
or die "Error running git-write-tree: $?\n";
print "Tree ID $tree\n" if $opt_v;
my $parent = "";
if(open(C,"$git_dir/refs/heads/$last_branch")) {
chomp($parent = <C>);
close(C);
length($parent) == 40
or die "Cannot get parent id ($parent): $!\n";
print "Parent ID $parent\n" if $opt_v;
}
my $pr = IO::Pipe->new() or die "Cannot open pipe: $!\n";
my $pw = IO::Pipe->new() or die "Cannot open pipe: $!\n";
$pid = fork();
die "Fork: $!\n" unless defined $pid;
unless($pid) {
$pr->writer();
$pw->reader();
open(OUT,">&STDOUT");
dup2($pw->fileno(),0);
dup2($pr->fileno(),1);
$pr->close();
$pw->close();
my @par = ();
@par = ("-p",$parent) if $parent;
# loose detection of merges
# based on the commit msg
foreach my $rx (@mergerx) {
if ($logmsg =~ $rx) {
my $mparent = $1;
if ($mparent eq 'HEAD') { $mparent = $opt_o };
if ( -e "$git_dir/refs/heads/$mparent") {
$mparent = get_headref($mparent, $git_dir);
push @par, '-p', $mparent;
print OUT "Merge parent branch: $mparent\n" if $opt_v;
}
}
}
exec("env",
"GIT_AUTHOR_NAME=$author_name",
"GIT_AUTHOR_EMAIL=$author_email",
"GIT_AUTHOR_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)),
"GIT_COMMITTER_NAME=$author_name",
"GIT_COMMITTER_EMAIL=$author_email",
"GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)),
"git-commit-tree", $tree,@par);
die "Cannot exec git-commit-tree: $!\n";
close OUT;
}
$pw->writer();
$pr->reader();
# compatibility with git2cvs # compatibility with git2cvs
substr($logmsg,32767) = "" if length($logmsg) > 32767; substr($logmsg,32767) = "" if length($logmsg) > 32767;
@ -666,16 +638,14 @@ sub commit {
@skipped = (); @skipped = ();
} }
print $pw "$logmsg\n" print($commit_write "$logmsg\n") && close($commit_write)
or die "Error writing to git-commit-tree: $!\n"; or die "Error writing to git-commit-tree: $!\n";
$pw->close();
print "Committed patch $patchset ($branch ".strftime("%Y-%m-%d %H:%M:%S",gmtime($date)).")\n" if $opt_v; print "Committed patch $patchset ($branch $commit_date)\n" if $opt_v;
chomp(my $cid = <$pr>); chomp(my $cid = <$commit_read>);
length($cid) == 40 is_sha1($cid) or die "Cannot get commit id ($cid): $!\n";
or die "Cannot get commit id ($cid): $!\n";
print "Commit ID $cid\n" if $opt_v; print "Commit ID $cid\n" if $opt_v;
$pr->close(); close($commit_read);
waitpid($pid,0); waitpid($pid,0);
die "Error running git-commit-tree: $?\n" if $?; die "Error running git-commit-tree: $?\n" if $?;
@ -719,6 +689,7 @@ sub commit {
} }
}; };
my $commitcount = 1;
while(<CVS>) { while(<CVS>) {
chomp; chomp;
if($state == 0 and /^-+$/) { if($state == 0 and /^-+$/) {
@ -852,7 +823,14 @@ while(<CVS>) {
} elsif($state == 9 and /^\s*$/) { } elsif($state == 9 and /^\s*$/) {
$state = 10; $state = 10;
} elsif(($state == 9 or $state == 10) and /^-+$/) { } elsif(($state == 9 or $state == 10) and /^-+$/) {
$commitcount++;
if ($opt_L && $commitcount > $opt_L) {
last;
}
commit(); commit();
if (($commitcount & 1023) == 0) {
system("git repack -a -d");
}
$state = 1; $state = 1;
} elsif($state == 11 and /^-+$/) { } elsif($state == 11 and /^-+$/) {
$state = 1; $state = 1;