Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/Git/FastExport.pm
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ sub next_block {
( $block->{date} )
= $block->{committer}[0] =~ /^committer [^>]*> (\d+) [-+]\d+$/g;
}
if ( $block->{type} eq 'commit' ) {
( $block->{authored_date} )
= $block->{author}[0] =~ /^author [^>]*> (\d+) [-+]\d+$/g;
}

return $block;
}
Expand Down
64 changes: 43 additions & 21 deletions lib/Git/FastExport/Stitch.pm
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,21 @@ sub new {

# default options
select => 'last',
datetype => 'commit_date',

}, $class;

# set the options
for my $key (qw( select )) {
for my $key (qw( select datetype )) {
$self->{$key} = $options->{$key} if exists $options->{$key};
}
croak "Invalid value for 'select' option: '$self->{select}'"
if $self->{select} !~ /^(?:first|last|random)$/;

croak "Invalid value for 'datetype' option: '$self->{datetype}'"
if $self->{datetype} !~ /^(?:authored_date|commit_date)$/;

$self->{datetype} = 'date' if ($self->{datetype} eq "commit_date");
# process the remaining args
$self->stitch( splice @args, 0, 2 ) while @args;

Expand All @@ -41,7 +46,7 @@ sub new {

# add a new repo to stich in
sub stitch {
my ( $self, $repo, $dir ) = @_;
my ( $self, $repo, $dir, $name ) = @_;

my $export
= blessed($repo) && $repo->isa('Git::FastExport')
Expand All @@ -62,7 +67,7 @@ sub stitch {
$self->{repo}{$repo}{repo} = $repo;
$self->{repo}{$repo}{dir} = $dir;
$self->{repo}{$repo}{parser} = $export;
$self->{repo}{$repo}{name} = $self->{name}++;
$self->{repo}{$repo}{name} = $name || $self->{name}++;
$self->{repo}{$repo}{block} = $export->next_block();
$self->_translate_block( $repo );

Expand Down Expand Up @@ -93,9 +98,10 @@ sub next_block {

# select the oldest available commit
my ($next) = keys %$repo;
$next
= $repo->{$next}{block}{date} < $repo->{$_}{block}{date} ? $next : $_
for keys %$repo;
for ( keys %$repo ) {
$next
= $repo->{$next}{block}{$self->{datetype}} < $repo->{$_}{block}{$self->{datetype}} ? $next : $_ ;
}
my $commit = $repo->{$next}{block};

# fetch the next block
Expand Down Expand Up @@ -131,6 +137,32 @@ sub next_block {
my @parents = map {/:(\d+)/g} @{ $commit->{from} || [] },
@{ $commit->{merge} || [] };

#Call out to build the parents rewrite map
my %parent_map = $self->_map_parents($node, \@parents);

# map parent marks
for ( @{ $commit->{from} || [] }, @{ $commit->{merge} || [] } ) {
s/:(\d+)/:$parent_map{$1}/g;
}

# update the parents information
for my $parent ( map { $commits->{ $parent_map{$_} } } @parents ) {
push @{ $parent->{children} }, $node->{name};
push @{ $node->{parents}{ $parent->{repo} } }, $parent->{name};
}

# dump the commit
return $commit;
}

sub _map_parents {
my ( $self, $node , $parents_ary) = @_;
my @parents = @$parents_ary;
my $commits = $self->{commits};
my $branch = $node->{branch};
my $repo = $node->{repo};


# get the reference parent list used by _last_alien_child()
my $parents = {};
for my $parent (@parents) {
Expand All @@ -148,25 +180,13 @@ sub next_block {
}

# map each parent to its last "alien" commit
my %parent_map = map {
return map {
$_ => $self->_last_alien_child( $commits->{$_}, $branch, $parents )->{name}
} @parents;

# map parent marks
for ( @{ $commit->{from} || [] }, @{ $commit->{merge} || [] } ) {
s/:(\d+)/:$parent_map{$1}/g;
}

# update the parents information
for my $parent ( map { $commits->{ $parent_map{$_} } } @parents ) {
push @{ $parent->{children} }, $node->{name};
push @{ $node->{parents}{ $parent->{repo} } }, $parent->{name};
}

# dump the commit
return $commit;
}


sub _translate_block {
my ( $self, $repo ) = @_;
my $mark_map = $self->{mark_map};
Expand Down Expand Up @@ -313,7 +333,7 @@ See L<STITCHING ALGORITHM> for details about what these options really mean.
The remaining parameters (if any) are taken to be parameters (passed by
pairs) to the C<stitch()> method.

=item stitch( $repo, $dir )
=item stitch( $repo, $dir , $name )

Add the given C<$repo> to the list of repositories to stitch in.

Expand All @@ -325,6 +345,8 @@ The optional C<$dir> parameter will be used as the relative directory
under which the trees of the source repository will be stored in the
stitched repository.

And further optional parameter C<$name> set the internal name for C<$repo>
which is used as a suffix on refs copied from C<$repo>
=item next_block()

Return the next block of the stitched repository, as a
Expand Down
6 changes: 4 additions & 2 deletions script/git-stitch-repo
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ use Pod::Usage;
use Getopt::Long;
use Git::FastExport::Stitch;
use File::Spec::Functions qw( rel2abs );
use File::Basename;

our $VERSION = $Git::FastExport::Stitch::VERSION;

# basic command-line options
my %option;
GetOptions( \%option, 'help', 'manual', 'version', 'select=s' )
GetOptions( \%option, 'help', 'manual', 'version', 'select=s' , 'datetype=s' )
or pod2usage( -verbose => 0 );
print "git-stitch-repo version $VERSION\n" and exit if $option{version};
pod2usage( -verbose => 1 ) if $option{help};
Expand All @@ -26,7 +27,8 @@ while (@ARGV) {
$dir ||= '';

# add the repository to the list of repositories to stitch
$export->stitch( $repo => $dir );
# using the src directory as the tag suffix.
$export->stitch( $repo => $dir, basename($repo) );
}

# run the stitching algorithm
Expand Down
8 changes: 8 additions & 0 deletions t/10fast-export.t
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ my @blocks = (
],
files => ['M 0100644 :1 loremipsum.txt'],
date => 1213115458,
authored_date => 1213115458,
footer => "\012",
},
{ type => 'blob',
Expand All @@ -89,6 +90,7 @@ my @blocks = (
from => ['from :2'],
files => ['M 0100644 :3 loremipsum.txt'],
date => 1213115469,
authored_date => 1213115469,
footer => "\012",
},
{ type => 'blob',
Expand All @@ -113,6 +115,7 @@ my @blocks = (
from => ['from :4'],
files => ['M 0100644 :5 loremipsum.txt'],
date => 1213115504,
authored_date => 1213115504,
footer => "\012",
},
{ type => 'blob',
Expand All @@ -134,6 +137,7 @@ my @blocks = (
from => ['from :4'],
files => ['M 0100644 :7 loremipsum.txt'],
date => 1213115522,
authored_date => 1213115522,
footer => "\012",
},
{ type => 'blob',
Expand All @@ -155,6 +159,7 @@ my @blocks = (
from => ['from :8'],
files => ['M 0100644 :9 loremipsum.txt'],
date => 1213115555,
authored_date => 1213115555,
footer => "\012",
},
{ type => 'progress',
Expand All @@ -179,6 +184,7 @@ my @blocks = (
from => ['from :6'],
files => ['M 0100644 :11 loremipsum.txt'],
date => 1213115577,
authored_date => 1213115577,
footer => "\012",
},
{ type => 'blob',
Expand All @@ -201,6 +207,7 @@ my @blocks = (
merge => ['merge :10'],
files => ['M 0100644 :13 loremipsum.txt'],
date => 1213115620,
authored_date => 1213115620,
footer => "\012",
},
{ type => 'blob',
Expand All @@ -225,6 +232,7 @@ my @blocks = (
from => ['from :14'],
files => ['M 0100644 :15 loremipsum.txt'],
date => 1213115889,
authored_date => 1213115889,
footer => "\012",
},
{ type => 'reset',
Expand Down
6 changes: 5 additions & 1 deletion t/20stitch.t
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ has_git('1.5.4');
my @valid_args = map {
my %o = %$_;
( \%o, map { my %h = %o; $h{select} = $_; \%h } qw( first last random ) )
} ( {}, { cached => '' }, { cached => 1 } );
} map {
my %o = %$_;
( \%o, map { my %h = %o; $h{datetype} = $_; \%h } qw( authored_date commit_date ) )
}( {}, { cached => '' }, { cached => 1 } );

my @tests = (

Expand All @@ -22,6 +25,7 @@ my @tests = (

# error cases
[ [ { select => 'bam' } ], qr/Invalid value for 'select' option: 'bam'/ ],
[ [ { datetype => 'bam' } ], qr/Invalid value for 'datetype' option: 'bam'/ ],
[ [ {}, 'bonk' ], qr/^Can't chdir to .*bonk: / ],
);

Expand Down
Loading