On Mon, Aug 27, 2007 at 11:54:30PM -0400, Shawn O. Pearce wrote: > This would be much faster if it was in Perl/Python/Tcl as the script > could avoid two forks per file and instead just fork git-config > once/twice and git-fast-import once. I think those two per-file > forks is what is killing the performance. It's a bit faster, but you still get killed on passing all of the data through userspace and a pipe, rather than just having git-add hash it directly. Some timings importing git.git's contents: git-import-core real 0m0.839s user 0m0.504s sys 0m0.304s git-import-shell real 0m4.947s user 0m2.604s sys 0m2.912s git-import-perl real 0m1.400s user 0m1.144s sys 0m0.180s where 'git-import-core' is this: #!/bin/sh git-init git-add . git-commit -q -m "$1" 'git-import-shell' is Duy's script, and 'git-import-perl' is the script included below. I think having such a simple example in shell _and_ in perl (and in python, etc) is a nice starting point for people who want to hack together a fast-import frontend. I am queuing this to send to Junio after 1.5.3, and I will submit the shell version, as well, if Duy doesn't put it in patch format before then. The only notable difference is that the shell version will not add any files starting with dot (since it uses a glob to avoid adding .git). -Peff -- >8 -- contrib: add simple fast-import example This example just puts a directory under git control. It is a bit slower than using git tools directly, but hopefully shows a bit how fast-import works. --- contrib/fast-import/git-import.perl | 64 +++++++++++++++++++++++++++++++++++ 1 files changed, 64 insertions(+), 0 deletions(-) create mode 100755 contrib/fast-import/git-import.perl diff --git a/contrib/fast-import/git-import.perl b/contrib/fast-import/git-import.perl new file mode 100755 index 0000000..8ed56d0 --- /dev/null +++ b/contrib/fast-import/git-import.perl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# +# Performs an initial import of a directory. This is the equivalent +# of doing 'git init; git add .; git commit'. It's a little slower, +# but is meant to be a simple fast-import example. + +use strict; +use File::Find; + +my $USAGE = 'Usage: git-import branch import-message'; +my $branch = shift or die "$USAGE\n"; +my $message = shift or die "$USAGE\n"; + +chomp(my $username = `git config user.name`); +chomp(my $email = `git config user.email`); +die 'You need to set user name and email' + unless $username && $email; + +system('git init'); +open(my $fi, '|-', qw(git fast-import --date-format=now)) + or die "unable to spawn fast-import: $!"; + +print $fi <<EOF; +commit refs/heads/$branch +committer $username <$email> now +data <<MSGEOF +$message +MSGEOF + +EOF + +find( + sub { + if($File::Find::name eq './.git') { + $File::Find::prune = 1; + return; + } + return unless -f $_; + + my $fn = $File::Find::name; + $fn =~ s#^.\/##; + + open(my $in, '<', $_) + or die "unable to open $fn: $!"; + my @st = stat($in) + or die "unable to stat $fn: $!"; + my $len = $st[7]; + + print $fi "M 100644 inline $fn\n"; + print $fi "data $st[7]\n"; + while($len > 0) { + my $r = read($in, my $buf, $len < 4096 ? $len : 4096); + defined($r) or die "read error from $fn: $!"; + $r > 0 or die "premature EOF from $fn: $!"; + print $fi $buf; + $len -= $r; + } + print $fi "\n"; + + }, '.' +); + +close($fi); +exit $?; -- 1.5.3.rc6.843.g65809-dirty - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html