git-remote-mediawiki: set 'basetimestamp' to let the wiki handle conflicts

We already have a check that no new revisions are on the wiki at the beginning of the push, but this didn't handle concurrent accesses to the wiki. Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Matthieu Moy committed Sep 27, 2011 at 19:54 UTC 3c1ed90ec3973404ffcff99103faa5b863889f98
1 file changed +37 -6
contrib/mw-to-git/git-remote-mediawiki
+37 -6
@@ -287,6 +287,9 @@ sub get_last_local_revision {
287 return $lastrevision_number;
288 }
289
290 +# Remember the timestamp corresponding to a revision id.
291 +my %basetimestamps;
292 +
293 sub get_last_remote_revision {
294 mw_connect_maybe();
295
@@ -300,7 +303,7 @@ sub get_last_remote_revision {
303 my $query = {
304 action => 'query',
305 prop => 'revisions',
303 - rvprop => 'ids',
306 + rvprop => 'ids|timestamp',
307 pageids => $id,
308 };
309
@@ -308,6 +311,8 @@ sub get_last_remote_revision {
311
312 my $lastrev = pop(@{$result->{query}->{pages}->{$id}->{revisions}});
313
314 + $basetimestamps{$lastrev->{revid}} = $lastrev->{timestamp};
315 +
316 $max_rev_num = ($lastrev->{revid} > $max_rev_num ? $lastrev->{revid} : $max_rev_num);
317 }
318
@@ -649,18 +654,32 @@ sub mw_push_file {
654 action => 'edit',
655 summary => $summary,
656 title => $title,
657 + basetimestamp => $basetimestamps{$newrevid},
658 text => mediawiki_clean($file_content, $page_created),
659 }, {
660 skip_encoding => 1 # Helps with names with accentuated characters
655 - }) || die 'Fatal: Error ' .
656 - $mediawiki->{error}->{code} .
657 - ' from mediwiki: ' . $mediawiki->{error}->{details};
661 + });
662 + if (!$result) {
663 + if ($mediawiki->{error}->{code} == 3) {
664 + # edit conflicts, considered as non-fast-forward
665 + print STDERR 'Warning: Error ' .
666 + $mediawiki->{error}->{code} .
667 + ' from mediwiki: ' . $mediawiki->{error}->{details} .
668 + ".\n";
669 + return ($newrevid, "non-fast-forward");
670 + } else {
671 + # Other errors. Shouldn't happen => just die()
672 + die 'Fatal: Error ' .
673 + $mediawiki->{error}->{code} .
674 + ' from mediwiki: ' . $mediawiki->{error}->{details};
675 + }
676 + }
677 $newrevid = $result->{edit}->{newrevid};
678 print STDERR "Pushed file: $new_sha1 - $title\n";
679 } else {
680 print STDERR "$complete_file_name not a mediawiki file (Not pushable on this version of git-remote-mediawiki).\n"
681 }
663 - return $newrevid;
682 + return ($newrevid, "ok");
683 }
684
685 sub mw_push {
@@ -767,13 +786,25 @@ sub mw_push_revision {
786 chomp($commit_msg);
787 # Push every blob
788 while (@diff_info_list) {
789 + my $status;
790 # git diff-tree -z gives an output like
791 # <metadata>\0<filename1>\0
792 # <metadata>\0<filename2>\0
793 # and we've split on \0.
794 my $info = shift(@diff_info_list);
795 my $file = shift(@diff_info_list);
776 - $mw_revision = mw_push_file($info, $file, $commit_msg, $mw_revision);
796 + ($mw_revision, $status) = mw_push_file($info, $file, $commit_msg, $mw_revision);
797 + if ($status eq "non-fast-forward") {
798 + # we may already have sent part of the
799 + # commit to MediaWiki, but it's too
800 + # late to cancel it. Stop the push in
801 + # the middle, but still give an
802 + # accurate error message.
803 + return error_non_fast_forward($remote);
804 + }
805 + if ($status ne "ok") {
806 + die("Unknown error from mw_push_file()");
807 + }
808 }
809 unless ($dumb_push) {
810 run_git("notes --ref=$remotename/mediawiki add -m \"mediawiki_revision: $mw_revision\" $sha1_commit");