check_clean_tree();
+sub memo ($$$) {
+ my ($memos,$key,$code) = @_;
+ return $memos->{$key} if exists $memos->{$key};
+ debug("----- $key");
+ $memos->{$key} = $code->();
+}
+
+sub merge_base ($$) {
+ my ($r,$s) = @_; # refs, ideally
+ our %memos;
+ return memo(\%memos, "$r $s", sub {
+ run_git_1line(qw(merge-base), $r, $s);
+ });
+}
+
+sub committ_date ($) {
+ my ($ref) = @_;
+ my $l = run_git_1line(qw(git-log --date=raw -n1 --pretty=format:%cd), $ref);
+ $l =~ m/^(\d+)\s/ or die;
+ return $l;
+}
+
sub update_base ($) {
my ($patch) = @_;
} elsif ($depline =~ m/^-/) {
die "$depline ?"; # should have failed earlier
} else {
- push @sources, { Ref => "$tiprefs/$depline", Kind => 'tb' };
+ push @sources, {
+ Name => $depline,
+ Ref => "$tiprefs/$depline",
+ Kind => 'tb',
+ };
}
}
if ($obk ne 'missing') {
$obj eq 'blob' or die "$patch $obk ??";
chomp $tg or die "$patch ??";
- push @sources, { Ref => "refs/top-bases/$tg", Kind => 'topgit' };
+ push @sources, {
+ Name => "-topgit $tg",
+ Ref => "refs/top-bases/$tg",
+ Kind => 'topgit',
+ };
}
# This bit involves rather too much history walking
# Find the merge base for each source
foreach my $source (@sources) {
$source->{Head} = run_git_1line(qw(rev-parse), $source->{Ref});
- $source->{MergeBase} =
- run_git_1line(qw(merge-base), $head, "$baserefs/$patch");
+ $source->{MergeBase} = merge_base($head, "$baserefs/$patch");
}
# The merge base is contained in $head, so if it is equal
# to the source's head, the source is contained in $head -
# ie we are ahead of the source. Skip those sources.
@sources = grep { $source->{MergeBase} ne $source->{Head} } @sources;
+ our %cmp_memos;
+ @sources = sort {
+ memo(\%cmp_memos, "$a->{Name} $b->{Name}", sub {
+ my $mb = merge_base($a->{Ref}, $b->{Ref});
+ return -($mb eq $a->{Ref}) cmp ($mb eq $b->{Ref})
+ # if merge base is $a then $a must be before $b
+ # ie the commit equal to the merge base is earlier
+ or (committ_date($a->{Ref}) cmp committ_date($b->{Ref}));
+ })
+ } @sources;
+
+
# Now we run git-rev-list to walk the graph back to those
# sources so we can tell which is the most recent.
foreach my $source (@sources) {