UNB/ CS/ David Bremner/ blog/ posts/ Fetching git bundles

Fourth in a series (git-sync-experiments, git-sync-experiments2, git-sync-experiments3) of completely unscientific experiments to try and figure out the best way to sync many git repos.

I wanted to see how bundles worked, and if there was some potential for speedup versus mr. The following unoptimized script is about twice as fast as mr in updating 10 repos. Of course is not really doing exactly the right thing (since it only looks at HEAD), but it is a start maybe. Of course, maybe the performance difference has nothing to do with bundles. Anyway IPC::PerlSSH is nifty.

#!/usr/bin/perl

use strict;
use File::Slurp;
use IPC::PerlSSH;
use Git;

my %config;
eval(read_file('config.pl'));
die $@ if $@;


my $ips= IPC::PerlSSH->new(Host=>$config{host});

$ips->eval("use Git; use File::Temp qw (tempdir); use File::Slurp;");
$ips->eval('${main::tempdir}=tempdir();');

$ips->store( "bundle", 
             q{my $prefix=shift;
               my $name=shift;
               my $ref=shift;
                chomp($ref);
               my $repo=Git->repository($prefix.$name.'.git');
               my $bfile="${main::tempdir}/${name}.bundle";
               eval {$repo->command('bundle','create',
                             $bfile,
                                $ref.'..HEAD'); 1} 
                or do { return undef };
                my $bits=read_file($bfile);
                print STDERR ("got ",length($bits),"\n");
                return $bits;
}
);


foreach my $pair  (@{$config{repos}}){
    my ($local,$remote)=@{$pair};
    my $bname=$local.'.bundle';

    $bname =~ s|/|_|;
    $bname =~ s|^\.|@|;
    
    my $repo=Git->repository($config{localprefix}.$local);
    # force some commit to be bundled, just for testing
    my $head=$repo->command('rev-list','--max-count=1', 'origin/HEAD^');
    
    my $bits=$ips->call('bundle',$config{remoteprefix},$remote,$head);
    write_file($bname, {binmode => ':raw'}, \$bits);
    $repo->command_noisy('fetch',$ENV{PWD}.'/'.$bname,'HEAD');
}

The config file is just a hash

%config=(
    host=>'hostname',
    localprefix=>'/path/',
    remoteprefix=>'/path/git/'
    repos=>[
        [qw(localdir remotedir)],
    ]
)