git-remote-mediawiki: factoring code between git-remote-mediawiki and Git::Mediawiki

For now, Git::Mediawiki contains nothing. This first patch moves some of git-remote-mediawiki.perl's factorisable code into Git::Mediawiki. In the same time, it removes the side effects of that code and renames the fucntions and constants moved to expose a better API. Signed-off-by: Benoit Person <benoit.person@ensimag.fr> Signed-off-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Benoit Person committed Jul 4, 2013 at 22:38 UTC 192f7a080469ea3e7a702f04e08ba7e709c0b3c3
2 files changed +89 -73
contrib/mw-to-git/Git/Mediawiki.pm
+76 -1
@@ -18,7 +18,82 @@ require Exporter;
18 @EXPORT = ();
19
20 # Methods which can be called as standalone functions as well:
21 -@EXPORT_OK = ();
21 +@EXPORT_OK = qw(clean_filename smudge_filename connect_maybe
22 + EMPTY HTTP_CODE_OK);
23 +}
24 +
25 +# Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
26 +use constant SLASH_REPLACEMENT => '%2F';
27 +
28 +# Used to test for empty strings
29 +use constant EMPTY => q{};
30 +
31 +# HTTP codes
32 +use constant HTTP_CODE_OK => 200;
33 +
34 +sub clean_filename {
35 + my $filename = shift;
36 + $filename =~ s{@{[SLASH_REPLACEMENT]}}{/}g;
37 + # [, ], |, {, and } are forbidden by MediaWiki, even URL-encoded.
38 + # Do a variant of URL-encoding, i.e. looks like URL-encoding,
39 + # but with _ added to prevent MediaWiki from thinking this is
40 + # an actual special character.
41 + $filename =~ s/[\[\]\{\}\|]/sprintf("_%%_%x", ord($&))/ge;
42 + # If we use the uri escape before
43 + # we should unescape here, before anything
44 +
45 + return $filename;
46 +}
47 +
48 +sub smudge_filename {
49 + my $filename = shift;
50 + $filename =~ s{/}{@{[SLASH_REPLACEMENT]}}g;
51 + $filename =~ s/ /_/g;
52 + # Decode forbidden characters encoded in clean_filename
53 + $filename =~ s/_%_([0-9a-fA-F][0-9a-fA-F])/sprintf('%c', hex($1))/ge;
54 + return $filename;
55 +}
56 +
57 +sub connect_maybe {
58 + my $wiki = shift;
59 + if ($wiki) {
60 + return $wiki;
61 + }
62 +
63 + my $remote_name = shift;
64 + my $remote_url = shift;
65 + my ($wiki_login, $wiki_password, $wiki_domain);
66 +
67 + $wiki_login = Git::config("remote.${remote_name}.mwLogin");
68 + $wiki_password = Git::config("remote.${remote_name}.mwPassword");
69 + $wiki_domain = Git::config("remote.${remote_name}.mwDomain");
70 +
71 + $wiki = MediaWiki::API->new;
72 + $wiki->{config}->{api_url} = "${remote_url}/api.php";
73 + if ($wiki_login) {
74 + my %credential = (
75 + 'url' => $remote_url,
76 + 'username' => $wiki_login,
77 + 'password' => $wiki_password
78 + );
79 + Git::credential(\%credential);
80 + my $request = {lgname => $credential{username},
81 + lgpassword => $credential{password},
82 + lgdomain => $wiki_domain};
83 + if ($wiki->login($request)) {
84 + Git::credential(\%credential, 'approve');
85 + print {*STDERR} qq(Logged in mediawiki user "$credential{username}".\n);
86 + } else {
87 + print {*STDERR} qq(Failed to log in mediawiki user "$credential{username}" on ${remote_url}\n);
88 + print {*STDERR} ' (error ' .
89 + $wiki->{error}->{code} . ': ' .
90 + $wiki->{error}->{details} . ")\n";
91 + Git::credential(\%credential, 'reject');
92 + exit 1;
93 + }
94 + }
95 +
96 + return $wiki;
97 }
98
99 1; # Famous last words
contrib/mw-to-git/git-remote-mediawiki.perl
+13 -72
@@ -14,6 +14,8 @@
14 use strict;
15 use MediaWiki::API;
16 use Git;
17 +use Git::Mediawiki qw(clean_filename smudge_filename connect_maybe
18 + EMPTY HTTP_CODE_OK);
19 use DateTime::Format::ISO8601;
20 use warnings;
21
@@ -23,9 +25,6 @@ binmode STDOUT, ':encoding(UTF-8)';
25
26 use URI::Escape;
27
26 -# Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
27 -use constant SLASH_REPLACEMENT => '%2F';
28 -
28 # It's not always possible to delete pages (may require some
29 # privileges). Deleted pages are replaced with this content.
30 use constant DELETED_CONTENT => "[[Category:Deleted]]\n";
@@ -40,8 +39,6 @@ use constant NULL_SHA1 => '0000000000000000000000000000000000000000';
39 # Used on Git's side to reflect empty edit messages on the wiki
40 use constant EMPTY_MESSAGE => '*Empty MediaWiki Message*';
41
43 -use constant EMPTY => q{};
44 -
42 # Number of pages taken into account at once in submodule get_mw_page_list
43 use constant SLICE_SIZE => 50;
44
@@ -50,8 +47,6 @@ use constant SLICE_SIZE => 50;
47 # the number of links to be returned (500 links max).
48 use constant BATCH_SIZE => 10;
49
53 -use constant HTTP_CODE_OK => 200;
54 -
50 if (@ARGV != 2) {
51 exit_error_usage();
52 }
@@ -199,37 +194,6 @@ sub parse_command {
194 # MediaWiki API instance, created lazily.
195 my $mediawiki;
196
202 -sub mw_connect_maybe {
203 - if ($mediawiki) {
204 - return;
205 - }
206 - $mediawiki = MediaWiki::API->new;
207 - $mediawiki->{config}->{api_url} = "${url}/api.php";
208 - if ($wiki_login) {
209 - my %credential = (
210 - 'url' => $url,
211 - 'username' => $wiki_login,
212 - 'password' => $wiki_passwd
213 - );
214 - Git::credential(\%credential);
215 - my $request = {lgname => $credential{username},
216 - lgpassword => $credential{password},
217 - lgdomain => $wiki_domain};
218 - if ($mediawiki->login($request)) {
219 - Git::credential(\%credential, 'approve');
220 - print {*STDERR} qq(Logged in mediawiki user "$credential{username}".\n);
221 - } else {
222 - print {*STDERR} qq(Failed to log in mediawiki user "$credential{username}" on ${url}\n);
223 - print {*STDERR} ' (error ' .
224 - $mediawiki->{error}->{code} . ': ' .
225 - $mediawiki->{error}->{details} . ")\n";
226 - Git::credential(\%credential, 'reject');
227 - exit 1;
228 - }
229 - }
230 - return;
231 -}
232 -
197 sub fatal_mw_error {
198 my $action = shift;
199 print STDERR "fatal: could not $action.\n";
@@ -339,7 +303,7 @@ sub get_mw_first_pages {
303
304 # Get the list of pages to be fetched according to configuration.
305 sub get_mw_pages {
342 - mw_connect_maybe();
306 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
307
308 print {*STDERR} "Listing pages on remote wiki...\n";
309
@@ -529,7 +493,7 @@ sub get_last_local_revision {
493 # avoid a loop onto all tracked pages. This is useful for the fetch-by-rev
494 # option.
495 sub get_last_global_remote_rev {
532 - mw_connect_maybe();
496 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
497
498 my $query = {
499 action => 'query',
@@ -545,7 +509,7 @@ sub get_last_global_remote_rev {
509 # Get the last remote revision concerning the tracked pages and the tracked
510 # categories.
511 sub get_last_remote_revision {
548 - mw_connect_maybe();
512 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
513
514 my %pages_hash = get_mw_pages();
515 my @pages = values(%pages_hash);
@@ -601,29 +565,6 @@ sub mediawiki_smudge {
565 return "${string}\n";
566 }
567
604 -sub mediawiki_clean_filename {
605 - my $filename = shift;
606 - $filename =~ s{@{[SLASH_REPLACEMENT]}}{/}g;
607 - # [, ], |, {, and } are forbidden by MediaWiki, even URL-encoded.
608 - # Do a variant of URL-encoding, i.e. looks like URL-encoding,
609 - # but with _ added to prevent MediaWiki from thinking this is
610 - # an actual special character.
611 - $filename =~ s/[\[\]\{\}\|]/sprintf("_%%_%x", ord($&))/ge;
612 - # If we use the uri escape before
613 - # we should unescape here, before anything
614 -
615 - return $filename;
616 -}
617 -
618 -sub mediawiki_smudge_filename {
619 - my $filename = shift;
620 - $filename =~ s{/}{@{[SLASH_REPLACEMENT]}}g;
621 - $filename =~ s/ /_/g;
622 - # Decode forbidden characters encoded in mediawiki_clean_filename
623 - $filename =~ s/_%_([0-9a-fA-F][0-9a-fA-F])/sprintf('%c', hex($1))/ge;
624 - return $filename;
625 -}
626 -
568 sub literal_data {
569 my ($content) = @_;
570 print {*STDOUT} 'data ', bytes::length($content), "\n", $content;
@@ -831,7 +772,7 @@ sub mw_import_ref {
772 return;
773 }
774
834 - mw_connect_maybe();
775 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
776
777 print {*STDERR} "Searching revisions...\n";
778 my $last_local = get_last_local_revision();
@@ -945,7 +886,7 @@ sub mw_import_revids {
886 my %commit;
887 $commit{author} = $rev->{user} || 'Anonymous';
888 $commit{comment} = $rev->{comment} || EMPTY_MESSAGE;
948 - $commit{title} = mediawiki_smudge_filename($page_title);
889 + $commit{title} = smudge_filename($page_title);
890 $commit{mw_revision} = $rev->{revid};
891 $commit{content} = mediawiki_smudge($rev->{'*'});
892
@@ -1006,7 +947,7 @@ sub mw_upload_file {
947 }
948 # Deleting and uploading a file requires a priviledged user
949 if ($file_deleted) {
1009 - mw_connect_maybe();
950 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
951 my $query = {
952 action => 'delete',
953 title => $path,
@@ -1022,7 +963,7 @@ sub mw_upload_file {
963 # Don't let perl try to interpret file content as UTF-8 => use "raw"
964 my $content = run_git("cat-file blob ${new_sha1}", 'raw');
965 if ($content ne EMPTY) {
1025 - mw_connect_maybe();
966 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
967 $mediawiki->{config}->{upload_url} =
968 "${url}/index.php/Special:Upload";
969 $mediawiki->edit({
@@ -1070,7 +1011,7 @@ sub mw_push_file {
1011 my $old_sha1 = $diff_info_split[2];
1012 my $page_created = ($old_sha1 eq NULL_SHA1);
1013 my $page_deleted = ($new_sha1 eq NULL_SHA1);
1073 - $complete_file_name = mediawiki_clean_filename($complete_file_name);
1014 + $complete_file_name = clean_filename($complete_file_name);
1015
1016 my ($title, $extension) = $complete_file_name =~ /^(.*)\.([^\.]*)$/;
1017 if (!defined($extension)) {
@@ -1093,7 +1034,7 @@ sub mw_push_file {
1034 $file_content = run_git("cat-file blob ${new_sha1}");
1035 }
1036
1096 - mw_connect_maybe();
1037 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1038
1039 my $result = $mediawiki->edit( {
1040 action => 'edit',
@@ -1279,7 +1220,7 @@ sub mw_push_revision {
1220 }
1221
1222 sub get_allowed_file_extensions {
1282 - mw_connect_maybe();
1223 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1224
1225 my $query = {
1226 action => 'query',
@@ -1303,7 +1244,7 @@ my %cached_mw_namespace_id;
1244 # Return MediaWiki id for a canonical namespace name.
1245 # Ex.: "File", "Project".
1246 sub get_mw_namespace_id {
1306 - mw_connect_maybe();
1247 + $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1248 my $name = shift;
1249
1250 if (!exists $namespace_id{$name}) {