git-remote-mediawiki: get rid of O(N^2) loop

The algorithm to find a path from the local revision to the remote one was calling "git rev-list" and parsing its output N times. Run rev-list only once, and fill a hashtable with the result to optimize the body of the loop. Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Matthieu Moy committed Jul 16, 2012 at 21:46 UTC 93e92d4d7c8883b346c8975c636286d6f6479142
1 file changed +17 -7
contrib/mw-to-git/git-remote-mediawiki
+17 -7
@@ -1196,16 +1196,26 @@ sub mw_push_revision {
1196 if ($last_local_revid > 0) {
1197 my $parsed_sha1 = $remoteorigin_sha1;
1198 # Find a path from last MediaWiki commit to pushed commit
1199 + print STDERR "Computing path from local to remote ...\n";
1200 + my @local_ancestry = split(/\n/, run_git("rev-list --boundary --parents $local ^$parsed_sha1"));
1201 + my %local_ancestry;
1202 + foreach my $line (@local_ancestry) {
1203 + if (my ($child, $parents) = $line =~ m/^-?([a-f0-9]+) ([a-f0-9 ]+)/) {
1204 + foreach my $parent (split(' ', $parents)) {
1205 + $local_ancestry{$parent} = $child;
1206 + }
1207 + } elsif (!$line =~ m/^([a-f0-9]+)/) {
1208 + die "Unexpected output from git rev-list: $line";
1209 + }
1210 + }
1211 while ($parsed_sha1 ne $HEAD_sha1) {
1200 - my @commit_info = grep(/^$parsed_sha1/, split(/\n/, run_git("rev-list --children $local")));
1201 - if (!@commit_info) {
1212 + my $child = $local_ancestry{$parsed_sha1};
1213 + if (!$child) {
1214 + printf STDERR "Cannot find a path in history from remote commit to last commit\n";
1215 return error_non_fast_forward($remote);
1216 }
1204 - my @commit_info_split = split(/ |\n/, $commit_info[0]);
1205 - # $commit_info_split[1] is the sha1 of the commit to export
1206 - # $commit_info_split[0] is the sha1 of its direct child
1207 - push(@commit_pairs, \@commit_info_split);
1208 - $parsed_sha1 = $commit_info_split[1];
1217 + push(@commit_pairs, [$parsed_sha1, $child]);
1218 + $parsed_sha1 = $child;
1219 }
1220 } else {
1221 # No remote mediawiki revision. Export the whole