# License: GPL v2 or later
# Gateway between Git and MediaWiki.
-# https://github.com/Bibzball/Git-Mediawiki/wiki
-#
-# Known limitations:
-#
-# - Several strategies are provided to fetch modifications from the
-# wiki, but no automatic heuristics is provided, the user has
-# to understand and chose which strategy is appropriate for him.
-#
-# - Git renames could be turned into MediaWiki renames (see TODO
-# below)
-#
-# - No way to import "one page, and all pages included in it"
-#
-# - Multiple remote MediaWikis have not been very well tested.
+# Documentation & bugtracker: https://github.com/moy/Git-Mediawiki/
use strict;
use MediaWiki::API;
## credential API management (generic functions)
-sub credential_from_url {
- my $url = shift;
- my $parsed = URI->new($url);
- my %credential;
-
- if ($parsed->scheme) {
- $credential{protocol} = $parsed->scheme;
- }
- if ($parsed->host) {
- $credential{host} = $parsed->host;
- }
- if ($parsed->path) {
- $credential{path} = $parsed->path;
- }
- if ($parsed->userinfo) {
- if ($parsed->userinfo =~ /([^:]*):(.*)/) {
- $credential{username} = $1;
- $credential{password} = $2;
- } else {
- $credential{username} = $parsed->userinfo;
- }
- }
-
- return %credential;
-}
-
sub credential_read {
my %credential;
my $reader = shift;
sub credential_write {
my $credential = shift;
my $writer = shift;
+ # url overwrites other fields, so it must come first
+ print $writer "url=$credential->{url}\n" if exists $credential->{url};
while (my ($key, $value) = each(%$credential) ) {
- if ($value) {
+ if (length $value && $key ne 'url') {
print $writer "$key=$value\n";
}
}
$mediawiki = MediaWiki::API->new;
$mediawiki->{config}->{api_url} = "$url/api.php";
if ($wiki_login) {
- my %credential = credential_from_url($url);
+ my %credential = (url => $url);
$credential{username} = $wiki_login;
$credential{password} = $wiki_passwd;
credential_run("fill", \%credential);
my $last_timestamp = 0; # Placeholer in case $rev->timestamp is undefined
foreach my $pagerevid (@$revision_ids) {
+ # Count page even if we skip it, since we display
+ # $n/$total and $total includes skipped pages.
+ $n++;
+
# fetch the content of the pages
my $query = {
action => 'query',
die "Failed to retrieve modified page for revision $pagerevid";
}
+ if (defined($result->{query}->{badrevids}->{$pagerevid})) {
+ # The revision id does not exist on the remote wiki.
+ next;
+ }
+
if (!defined($result->{query}->{pages})) {
die "Invalid revision $pagerevid.";
}
my $result_page = $result_pages[0];
my $rev = $result_pages[0]->{revisions}->[0];
- # Count page even if we skip it, since we display
- # $n/$total and $total includes skipped pages.
- $n++;
-
my $page_title = $result_page->{title};
if (!exists($pages->{$page_title})) {
# Differentiates classic pages and media files.
my ($namespace, $filename) = $page_title =~ /^([^:]*):(.*)$/;
my %mediafile;
- if ($namespace && get_mw_namespace_id($namespace) == get_mw_namespace_id("File")) {
- %mediafile = get_mw_mediafile_for_page_revision($filename, $rev->{timestamp});
+ if ($namespace) {
+ my $id = get_mw_namespace_id($namespace);
+ if ($id && $id == get_mw_namespace_id("File")) {
+ %mediafile = get_mw_mediafile_for_page_revision($filename, $rev->{timestamp});
+ }
}
# If this is a revision of the media page for new version
# of a file do one common commit for both file and media page.
chomp(@temp);
foreach my $ns (@temp) {
my ($n, $id) = split(/:/, $ns);
- $namespace_id{$n} = $id;
+ if ($id eq 'notANameSpace') {
+ $namespace_id{$n} = {is_namespace => 0};
+ } else {
+ $namespace_id{$n} = {is_namespace => 1, id => $id};
+ }
$cached_mw_namespace_id{$n} = 1;
}
}
while (my ($id, $ns) = each(%{$result->{query}->{namespaces}})) {
if (defined($ns->{id}) && defined($ns->{canonical})) {
- $namespace_id{$ns->{canonical}} = $ns->{id};
+ $namespace_id{$ns->{canonical}} = {is_namespace => 1, id => $ns->{id}};
if ($ns->{'*'}) {
# alias (e.g. french Fichier: as alias for canonical File:)
- $namespace_id{$ns->{'*'}} = $ns->{id};
+ $namespace_id{$ns->{'*'}} = {is_namespace => 1, id => $ns->{id}};
}
}
}
}
- my $id = $namespace_id{$name};
+ my $ns = $namespace_id{$name};
+ my $id;
- if (defined $id) {
- # Store explicitely requested namespaces on disk
- if (!exists $cached_mw_namespace_id{$name}) {
- run_git("config --add remote.". $remotename
- .".namespaceCache \"". $name .":". $id ."\"");
- $cached_mw_namespace_id{$name} = 1;
- }
- return $id;
- } else {
- die "No such namespace $name on MediaWiki.";
+ unless (defined $ns) {
+ print STDERR "No such namespace $name on MediaWiki.\n";
+ $ns = {is_namespace => 0};
+ $namespace_id{$name} = $ns;
+ }
+
+ if ($ns->{is_namespace}) {
+ $id = $ns->{id};
+ }
+
+ # Store "notANameSpace" as special value for inexisting namespaces
+ my $store_id = ($id || 'notANameSpace');
+
+ # Store explicitely requested namespaces on disk
+ if (!exists $cached_mw_namespace_id{$name}) {
+ run_git("config --add remote.". $remotename
+ .".namespaceCache \"". $name .":". $store_id ."\"");
+ $cached_mw_namespace_id{$name} = 1;
}
+ return $id;
}
sub get_mw_namespace_id_for_page {