Merge branch 'maint-1.7.7' into maint
[gitweb.git] / contrib / mw-to-git / git-remote-mediawiki
index 768b42dfe8767b66c836b55b09aeedabed64e102..c18bfa1f1515a8edb27c2d468a2982860a561939 100755 (executable)
@@ -76,8 +76,10 @@ my $wiki_login = run_git("config --get remote.". $remotename .".mwLogin");
 # inside a remote helper, so our stdin is connect to git, not to a
 # terminal.
 my $wiki_passwd = run_git("config --get remote.". $remotename .".mwPassword");
+my $wiki_domain = run_git("config --get remote.". $remotename .".mwDomain");
 chomp($wiki_login);
 chomp($wiki_passwd);
+chomp($wiki_domain);
 
 # Import only last revisions (both for clone and fetch)
 my $shallow_import = run_git("config --get --bool remote.". $remotename .".shallow");
@@ -107,6 +109,10 @@ $dumb_push = ($dumb_push eq "true");
 
 my $wiki_name = $url;
 $wiki_name =~ s/[^\/]*:\/\///;
+# If URL is like http://user:password@example.com/, we clearly don't
+# want the password in $wiki_name. While we're there, also remove user
+# and '@' sign, to avoid author like MWUser@HTTPUser@host.com
+$wiki_name =~ s/^.*@//;
 
 # Commands parser
 my $entry;
@@ -158,6 +164,7 @@ sub mw_connect_maybe {
                if (!$mediawiki->login({
                        lgname => $wiki_login,
                        lgpassword => $wiki_passwd,
+                       lgdomain => $wiki_domain,
                })) {
                        print STDERR "Failed to log in mediawiki user \"$wiki_login\" on $url\n";
                        print STDERR "(error " .
@@ -287,6 +294,9 @@ sub get_last_local_revision {
        return $lastrevision_number;
 }
 
+# Remember the timestamp corresponding to a revision id.
+my %basetimestamps;
+
 sub get_last_remote_revision {
        mw_connect_maybe();
 
@@ -300,7 +310,7 @@ sub get_last_remote_revision {
                my $query = {
                        action => 'query',
                        prop => 'revisions',
-                       rvprop => 'ids',
+                       rvprop => 'ids|timestamp',
                        pageids => $id,
                };
 
@@ -308,6 +318,8 @@ sub get_last_remote_revision {
 
                my $lastrev = pop(@{$result->{query}->{pages}->{$id}->{revisions}});
 
+               $basetimestamps{$lastrev->{revid}} = $lastrev->{timestamp};
+
                $max_rev_num = ($lastrev->{revid} > $max_rev_num ? $lastrev->{revid} : $max_rev_num);
        }
 
@@ -598,13 +610,16 @@ sub mw_import_ref {
 }
 
 sub error_non_fast_forward {
-       # Native git-push would show this after the summary.
-       # We can't ask it to display it cleanly, so print it
-       # ourselves before.
-       print STDERR "To prevent you from losing history, non-fast-forward updates were rejected\n";
-       print STDERR "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n";
-       print STDERR "'Note about fast-forwards' section of 'git push --help' for details.\n";
-
+       my $advice = run_git("config --bool advice.pushNonFastForward");
+       chomp($advice);
+       if ($advice ne "false") {
+               # Native git-push would show this after the summary.
+               # We can't ask it to display it cleanly, so print it
+               # ourselves before.
+               print STDERR "To prevent you from losing history, non-fast-forward updates were rejected\n";
+               print STDERR "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n";
+               print STDERR "'Note about fast-forwards' section of 'git push --help' for details.\n";
+       }
        print STDOUT "error $_[0] \"non-fast-forward\"\n";
        return 0;
 }
@@ -649,18 +664,32 @@ sub mw_push_file {
                        action => 'edit',
                        summary => $summary,
                        title => $title,
+                       basetimestamp => $basetimestamps{$newrevid},
                        text => mediawiki_clean($file_content, $page_created),
                                  }, {
                                          skip_encoding => 1 # Helps with names with accentuated characters
-                                 }) || die 'Fatal: Error ' .
-                                 $mediawiki->{error}->{code} .
-                                 ' from mediwiki: ' . $mediawiki->{error}->{details};
+                                 });
+               if (!$result) {
+                       if ($mediawiki->{error}->{code} == 3) {
+                               # edit conflicts, considered as non-fast-forward
+                               print STDERR 'Warning: Error ' .
+                                   $mediawiki->{error}->{code} .
+                                   ' from mediwiki: ' . $mediawiki->{error}->{details} .
+                                   ".\n";
+                               return ($newrevid, "non-fast-forward");
+                       } else {
+                               # Other errors. Shouldn't happen => just die()
+                               die 'Fatal: Error ' .
+                                   $mediawiki->{error}->{code} .
+                                   ' from mediwiki: ' . $mediawiki->{error}->{details};
+                       }
+               }
                $newrevid = $result->{edit}->{newrevid};
                print STDERR "Pushed file: $new_sha1 - $title\n";
        } else {
                print STDERR "$complete_file_name not a mediawiki file (Not pushable on this version of git-remote-mediawiki).\n"
        }
-       return $newrevid;
+       return ($newrevid, "ok");
 }
 
 sub mw_push {
@@ -767,13 +796,25 @@ sub mw_push_revision {
                chomp($commit_msg);
                # Push every blob
                while (@diff_info_list) {
+                       my $status;
                        # git diff-tree -z gives an output like
                        # <metadata>\0<filename1>\0
                        # <metadata>\0<filename2>\0
                        # and we've split on \0.
                        my $info = shift(@diff_info_list);
                        my $file = shift(@diff_info_list);
-                       $mw_revision = mw_push_file($info, $file, $commit_msg, $mw_revision);
+                       ($mw_revision, $status) = mw_push_file($info, $file, $commit_msg, $mw_revision);
+                       if ($status eq "non-fast-forward") {
+                               # we may already have sent part of the
+                               # commit to MediaWiki, but it's too
+                               # late to cancel it. Stop the push in
+                               # the middle, but still give an
+                               # accurate error message.
+                               return error_non_fast_forward($remote);
+                       }
+                       if ($status ne "ok") {
+                               die("Unknown error from mw_push_file()");
+                       }
                }
                unless ($dumb_push) {
                        run_git("notes --ref=$remotename/mediawiki add -m \"mediawiki_revision: $mw_revision\" $sha1_commit");