From: Ian Jackson Date: Wed, 1 Feb 2012 18:33:33 +0000 (+0000) Subject: update wip - source sorting and selection done X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=topbloke.git;a=commitdiff_plain;h=0c4e7252eb9a9be00a1124a7d246434290bc73aa update wip - source sorting and selection done --- diff --git a/tb-update.pl b/tb-update.pl index 9cae816..767dcf8 100755 --- a/tb-update.pl +++ b/tb-update.pl @@ -14,6 +14,28 @@ die "bad usage\n" if @ARGV; 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) = @_; @@ -54,7 +76,11 @@ sub update_base ($) { } 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', + }; } } @@ -62,7 +88,11 @@ sub update_base ($) { 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 @@ -71,14 +101,25 @@ sub update_base ($) { # 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) {