use Git.pm for efficient cat_blob if available
authorEric Wong <normalperson@yhbt.net>
Sun, 20 Apr 2014 19:18:19 +0000 (19:18 +0000)
committerEric Wong <normalperson@yhbt.net>
Sun, 20 Apr 2014 19:18:19 +0000 (19:18 +0000)
This reduces the amount of fork+exec and should improve performance
for large imports.

lib/Ssoma/Extractor.pm
lib/Ssoma/Git.pm

index 2589adb9a2c9ad75f92748d78acbb6799083fd68..9c93b43417c57b954af699c5978bccd8e1814dfd 100644 (file)
@@ -96,8 +96,9 @@ sub _extract {
 sub _deliver_each_msg {
        my ($self, $dest, $tip, $new) = @_;
        my $git = $self->{git};
+       my $git_pm = $git->try_git_pm;
        foreach my $path (@$new) {
-               _deliver_die($git->cat_blob("$tip:$path"), $dest);
+               _deliver_die($git->cat_blob("$tip:$path", $git_pm), $dest);
        }
 }
 
@@ -118,8 +119,9 @@ sub _imap_deliver_each_msg {
        my $git = $self->{git};
        require Ssoma::IMAP;
        my $imap = Ssoma::IMAP->new($git);
+       my $git_pm = $git->try_git_pm;
        foreach my $path (@$new) {
-               $imap->imap_deliver($git->cat_blob("$tip:$path"));
+               $imap->imap_deliver($git->cat_blob("$tip:$path", $git_pm));
        }
        $imap->quit;
 }
index 5cec7fb9fd4c93596d91aaccaf5dc40a63a71be2..5f5702bbcaf7cf281c0fe6aa1085e5e61b0725aa 100644 (file)
@@ -199,10 +199,20 @@ sub mid2path {
 }
 
 sub cat_blob {
-       my ($self, $blob_id) = @_;
-       my $cmd = "git cat-file blob $blob_id";
-       my $str = `$cmd`;
-       die "$cmd failed: $?\n" if $?;
+       my ($self, $blob_id, $git_pm) = @_;
+       my $str;
+       if ($git_pm) {
+               open my $fh, '>', \$str or
+                               die "failed to setup string handle: $!\n";
+               binmode $fh;
+               my $bytes = $git_pm->cat_blob($blob_id, $fh);
+               close $fh or die "failed to close string handle: $!\n";
+               die "$blob_id invalid\n" if $bytes <= 0;
+       } else {
+               my $cmd = "git cat-file blob $blob_id";
+               $str = `$cmd`;
+               die "$cmd failed: $?\n" if $?;
+       }
        $str;
 }
 
@@ -268,4 +278,13 @@ sub commit_index {
        system(@cmd) == 0 or die "command: ". join(' ', @cmd) . ": $?\n";
 }
 
+# keep Git.pm optional, not all installations of git have it
+sub try_git_pm {
+       my ($self) = @_;
+       eval {
+               require Git;
+               Git->repository(Directory => $self->{git_dir});
+       };
+}
+
 1;