contrib: remove "mw-to-git"

The "mw-to-git" directory contains tools for accessing MediaWiki via Git. The scripts are essentially unmaintained in Git: despite a couple of global cleanups, the last changes were a couple of security-related issues part of 9a8606465e8 (remote-mediawiki: use "sh" to eliminate unquoted commands, 2020-09-21) and its parents. We don't ever run any of the tests so it is more likely than not that many of the tests have been bitrotting, like e.g. documented in f8ab018dafc (remote-mediawiki tests: annotate failing tests, 2020-09-21). According to Matthieu Moy [1], one of the original developers of this tool, it didn't receive any attention recently and there is no motivation to keep maintaining it anymore in the community. The project has been spun out of Git [2] and thus has a new official home, but did not receive much attention over there, either. As such, it seems like the MediaWiki transport helper is slowly fading away. But given that there is a new home, it doesn't make sense to have it as part of Git anymore only to let it rot. Remove the directory. [1]: <108f297a-b415-4742-80e4-51ea02af18e9@matthieu-moy.fr> [2]: https://github.com/Git-Mediawiki/Git-Mediawiki Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed May 12, 2025 at 11:19 UTC 21b4f9009dd5a03e8c16d2c9473c896cff791001
22 files changed -3911
contrib/mw-to-git/.gitignore deleted
-2
@@ -1,2 +0,0 @@
1 -git-remote-mediawiki
2 -git-mw
contrib/mw-to-git/.perlcriticrc deleted
-28
@@ -1,28 +0,0 @@
1 -# These 3 rules demand to add the s, m and x flag to *every* regexp. This is
2 -# overkill and would be harmful for readability.
3 -[-RegularExpressions::RequireExtendedFormatting]
4 -[-RegularExpressions::RequireDotMatchAnything]
5 -[-RegularExpressions::RequireLineBoundaryMatching]
6 -
7 -# This rule says that builtin functions should not be called with parentheses
8 -# e.g.: (taken from CPAN's documentation)
9 -# open($handle, '>', $filename); #not ok
10 -# open $handle, '>', $filename; #ok
11 -# Applying such a rule would mean modifying a huge number of lines for a
12 -# question of style.
13 -[-CodeLayout::ProhibitParensWithBuiltins]
14 -
15 -# This rule states that each system call should have its return value checked
16 -# The problem is that it includes the print call. Checking every print call's
17 -# return value would be harmful to the code readability.
18 -# This configuration keeps all default function but print.
19 -[InputOutput::RequireCheckedSyscalls]
20 -functions = open say close
21 -
22 -# This rule demands to add a dependency for the Readonly module. This is not
23 -# wished.
24 -[-ValuesAndExpressions::ProhibitConstantPragma]
25 -
26 -# This rule is not really useful (rather a question of style) and produces many
27 -# warnings among the code.
28 -[-ValuesAndExpressions::ProhibitNoisyQuotes]
contrib/mw-to-git/Git/Mediawiki.pm deleted
-101
@@ -1,101 +0,0 @@
1 -package Git::Mediawiki;
2 -
3 -require v5.26;
4 -use strict;
5 -use POSIX;
6 -use Git;
7 -
8 -BEGIN {
9 -
10 -our ($VERSION, @ISA, @EXPORT, @EXPORT_OK);
11 -
12 -# Totally unstable API.
13 -$VERSION = '0.01';
14 -
15 -require Exporter;
16 -
17 -@ISA = qw(Exporter);
18 -
19 -@EXPORT = ();
20 -
21 -# Methods which can be called as standalone functions as well:
22 -@EXPORT_OK = qw(clean_filename smudge_filename connect_maybe
23 - EMPTY HTTP_CODE_OK HTTP_CODE_PAGE_NOT_FOUND);
24 -}
25 -
26 -# Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
27 -use constant SLASH_REPLACEMENT => '%2F';
28 -
29 -# Used to test for empty strings
30 -use constant EMPTY => q{};
31 -
32 -# HTTP codes
33 -use constant HTTP_CODE_OK => 200;
34 -use constant HTTP_CODE_PAGE_NOT_FOUND => 404;
35 -
36 -sub clean_filename {
37 - my $filename = shift;
38 - $filename =~ s{@{[SLASH_REPLACEMENT]}}{/}g;
39 - # [, ], |, {, and } are forbidden by MediaWiki, even URL-encoded.
40 - # Do a variant of URL-encoding, i.e. looks like URL-encoding,
41 - # but with _ added to prevent MediaWiki from thinking this is
42 - # an actual special character.
43 - $filename =~ s/[\[\]\{\}\|]/sprintf("_%%_%x", ord($&))/ge;
44 - # If we use the uri escape before
45 - # we should unescape here, before anything
46 -
47 - return $filename;
48 -}
49 -
50 -sub smudge_filename {
51 - my $filename = shift;
52 - $filename =~ s{/}{@{[SLASH_REPLACEMENT]}}g;
53 - $filename =~ s/ /_/g;
54 - # Decode forbidden characters encoded in clean_filename
55 - $filename =~ s/_%_([0-9a-fA-F][0-9a-fA-F])/sprintf('%c', hex($1))/ge;
56 - return substr($filename, 0, NAME_MAX-length('.mw'));
57 -}
58 -
59 -sub connect_maybe {
60 - my $wiki = shift;
61 - if ($wiki) {
62 - return $wiki;
63 - }
64 -
65 - my $remote_name = shift;
66 - my $remote_url = shift;
67 - my ($wiki_login, $wiki_password, $wiki_domain);
68 -
69 - $wiki_login = Git::config("remote.${remote_name}.mwLogin");
70 - $wiki_password = Git::config("remote.${remote_name}.mwPassword");
71 - $wiki_domain = Git::config("remote.${remote_name}.mwDomain");
72 -
73 - $wiki = MediaWiki::API->new;
74 - $wiki->{config}->{api_url} = "${remote_url}/api.php";
75 - if ($wiki_login) {
76 - my %credential = (
77 - 'url' => $remote_url,
78 - 'username' => $wiki_login,
79 - 'password' => $wiki_password
80 - );
81 - Git::credential(\%credential);
82 - my $request = {lgname => $credential{username},
83 - lgpassword => $credential{password},
84 - lgdomain => $wiki_domain};
85 - if ($wiki->login($request)) {
86 - Git::credential(\%credential, 'approve');
87 - print {*STDERR} qq(Logged in mediawiki user "$credential{username}".\n);
88 - } else {
89 - print {*STDERR} qq(Failed to log in mediawiki user "$credential{username}" on ${remote_url}\n);
90 - print {*STDERR} ' (error ' .
91 - $wiki->{error}->{code} . ': ' .
92 - $wiki->{error}->{details} . ")\n";
93 - Git::credential(\%credential, 'reject');
94 - exit 1;
95 - }
96 - }
97 -
98 - return $wiki;
99 -}
100 -
101 -1; # Famous last words
contrib/mw-to-git/Makefile deleted
-61
@@ -1,61 +0,0 @@
1 -#
2 -# Copyright (C) 2013
3 -# Matthieu Moy <Matthieu.Moy@imag.fr>
4 -#
5 -# To build and test:
6 -#
7 -# make
8 -# bin-wrapper/git mw preview Some_page.mw
9 -# bin-wrapper/git clone mediawiki::http://example.com/wiki/
10 -#
11 -# To install, run Git's toplevel 'make install' then run:
12 -#
13 -# make install
14 -
15 -# The default target of this Makefile is...
16 -all::
17 -
18 -GIT_MEDIAWIKI_PM=Git/Mediawiki.pm
19 -SCRIPT_PERL=git-remote-mediawiki.perl
20 -SCRIPT_PERL+=git-mw.perl
21 -GIT_ROOT_DIR=../..
22 -HERE=contrib/mw-to-git/
23 -
24 -INSTALL = install
25 -
26 -SCRIPT_PERL_FULL=$(patsubst %,$(HERE)/%,$(SCRIPT_PERL))
27 -INSTLIBDIR=$(shell $(MAKE) -C $(GIT_ROOT_DIR)/ \
28 - -s --no-print-directory prefix=$(prefix) \
29 - perllibdir=$(perllibdir) perllibdir)
30 -DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
31 -INSTLIBDIR_SQ = $(subst ','\'',$(INSTLIBDIR))
32 -
33 -all:: build
34 -
35 -test: all
36 - $(MAKE) -C t
37 -
38 -check: perlcritic test
39 -
40 -install_pm:
41 - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(INSTLIBDIR_SQ)/Git'
42 - $(INSTALL) -m 644 $(GIT_MEDIAWIKI_PM) \
43 - '$(DESTDIR_SQ)$(INSTLIBDIR_SQ)/$(GIT_MEDIAWIKI_PM)'
44 -
45 -build:
46 - $(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \
47 - build-perl-script
48 -
49 -install: install_pm
50 - $(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \
51 - install-perl-script
52 -
53 -clean:
54 - $(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \
55 - clean-perl-script
56 -
57 -perlcritic:
58 - perlcritic -5 $(SCRIPT_PERL)
59 - -perlcritic -2 $(SCRIPT_PERL)
60 -
61 -.PHONY: all test check install_pm install clean perlcritic
contrib/mw-to-git/bin-wrapper/git deleted
-14
@@ -1,14 +0,0 @@
1 -#!/bin/sh
2 -
3 -# git executable wrapper script for Git-Mediawiki to run tests without
4 -# installing all the scripts and perl packages.
5 -
6 -GIT_ROOT_DIR=../../..
7 -GIT_EXEC_PATH=$(cd "$(dirname "$0")" && cd ${GIT_ROOT_DIR} && pwd)
8 -
9 -GITPERLLIB="$GIT_EXEC_PATH"'/contrib/mw-to-git'"${GITPERLLIB:+:$GITPERLLIB}"
10 -PATH="$GIT_EXEC_PATH"'/contrib/mw-to-git:'"$PATH"
11 -
12 -export GITPERLLIB PATH
13 -
14 -exec "${GIT_EXEC_PATH}/bin-wrappers/git" "$@"
contrib/mw-to-git/git-mw.perl deleted
-368
@@ -1,368 +0,0 @@
1 -#!/usr/bin/perl
2 -
3 -# Copyright (C) 2013
4 -# Benoit Person <benoit.person@ensimag.imag.fr>
5 -# Celestin Matte <celestin.matte@ensimag.imag.fr>
6 -# License: GPL v2 or later
7 -
8 -# Set of tools for git repo with a mediawiki remote.
9 -# Documentation & bugtracker: https://github.com/Git-Mediawiki/Git-Mediawiki
10 -
11 -use strict;
12 -use warnings;
13 -
14 -use Getopt::Long;
15 -use URI::URL qw(url);
16 -use LWP::UserAgent;
17 -use HTML::TreeBuilder;
18 -
19 -use Git;
20 -use MediaWiki::API;
21 -use Git::Mediawiki qw(clean_filename connect_maybe
22 - EMPTY HTTP_CODE_PAGE_NOT_FOUND);
23 -
24 -# By default, use UTF-8 to communicate with Git and the user
25 -binmode STDERR, ':encoding(UTF-8)';
26 -binmode STDOUT, ':encoding(UTF-8)';
27 -
28 -# Global parameters
29 -my $verbose = 0;
30 -sub v_print {
31 - if ($verbose) {
32 - return print {*STDERR} @_;
33 - }
34 - return;
35 -}
36 -
37 -# Preview parameters
38 -my $file_name = EMPTY;
39 -my $remote_name = EMPTY;
40 -my $preview_file_name = EMPTY;
41 -my $autoload = 0;
42 -sub file {
43 - $file_name = shift;
44 - return $file_name;
45 -}
46 -
47 -my %commands = (
48 - 'help' =>
49 - [\&help, {}, \&help],
50 - 'preview' =>
51 - [\&preview, {
52 - '<>' => \&file,
53 - 'output|o=s' => \$preview_file_name,
54 - 'remote|r=s' => \$remote_name,
55 - 'autoload|a' => \$autoload
56 - }, \&preview_help]
57 -);
58 -
59 -# Search for sub-command
60 -my $cmd = $commands{'help'};
61 -for (0..@ARGV-1) {
62 - if (defined $commands{$ARGV[$_]}) {
63 - $cmd = $commands{$ARGV[$_]};
64 - splice @ARGV, $_, 1;
65 - last;
66 - }
67 -};
68 -GetOptions( %{$cmd->[1]},
69 - 'help|h' => \&{$cmd->[2]},
70 - 'verbose|v' => \$verbose);
71 -
72 -# Launch command
73 -&{$cmd->[0]};
74 -
75 -############################# Preview Functions ################################
76 -
77 -sub preview_help {
78 - print {*STDOUT} <<'END';
79 -USAGE: git mw preview [--remote|-r <remote name>] [--autoload|-a]
80 - [--output|-o <output filename>] [--verbose|-v]
81 - <blob> | <filename>
82 -
83 -DESCRIPTION:
84 -Preview is an utiliy to preview local content of a mediawiki repo as if it was
85 -pushed on the remote.
86 -
87 -For that, preview searches for the remote name of the current branch's
88 -upstream if --remote is not set. If that remote is not found or if it
89 -is not a mediawiki, it lists all mediawiki remotes configured and asks
90 -you to replay your command with the --remote option set properly.
91 -
92 -Then, it searches for a file named 'filename'. If it's not found in
93 -the current dir, it will assume it's a blob.
94 -
95 -The content retrieved in the file (or in the blob) will then be parsed
96 -by the remote mediawiki and combined with a template retrieved from
97 -the mediawiki.
98 -
99 -Finally, preview will save the HTML result in a file. and autoload it
100 -in your default web browser if the option --autoload is present.
101 -
102 -OPTIONS:
103 - -r <remote name>, --remote <remote name>
104 - If the remote is a mediawiki, the template and the parse engine
105 - used for the preview will be those of that remote.
106 - If not, a list of valid remotes will be shown.
107 -
108 - -a, --autoload
109 - Try to load the HTML output in a new tab (or new window) of your
110 - default web browser.
111 -
112 - -o <output filename>, --output <output filename>
113 - Change the HTML output filename. Default filename is based on the
114 - input filename with its extension replaced by '.html'.
115 -
116 - -v, --verbose
117 - Show more information on what's going on under the hood.
118 -END
119 - exit;
120 -}
121 -
122 -sub preview {
123 - my $wiki;
124 - my ($remote_url, $wiki_page_name);
125 - my ($new_content, $template);
126 - my $file_content;
127 -
128 - if ($file_name eq EMPTY) {
129 - die "Missing file argument, see `git mw help`\n";
130 - }
131 -
132 - v_print("### Selecting remote\n");
133 - if ($remote_name eq EMPTY) {
134 - $remote_name = find_upstream_remote_name();
135 - if ($remote_name) {
136 - $remote_url = mediawiki_remote_url_maybe($remote_name);
137 - }
138 -
139 - if (! $remote_url) {
140 - my @valid_remotes = find_mediawiki_remotes();
141 -
142 - if ($#valid_remotes == 0) {
143 - print {*STDERR} "No mediawiki remote in this repo. \n";
144 - exit 1;
145 - } else {
146 - my $remotes_list = join("\n\t", @valid_remotes);
147 - print {*STDERR} <<"MESSAGE";
148 -There are multiple mediawiki remotes, which of:
149 - ${remotes_list}
150 -do you want ? Use the -r option to specify the remote.
151 -MESSAGE
152 - }
153 -
154 - exit 1;
155 - }
156 - } else {
157 - if (!is_valid_remote($remote_name)) {
158 - die "${remote_name} is not a remote\n";
159 - }
160 -
161 - $remote_url = mediawiki_remote_url_maybe($remote_name);
162 - if (! $remote_url) {
163 - die "${remote_name} is not a mediawiki remote\n";
164 - }
165 - }
166 - v_print("selected remote:\n\tname: ${remote_name}\n\turl: ${remote_url}\n");
167 -
168 - $wiki = connect_maybe($wiki, $remote_name, $remote_url);
169 -
170 - # Read file content
171 - if (! -e $file_name) {
172 - $file_content = git_cmd_try {
173 - Git::command('cat-file', 'blob', $file_name); }
174 - "%s failed w/ code %d";
175 -
176 - if ($file_name =~ /(.+):(.+)/) {
177 - $file_name = $2;
178 - }
179 - } else {
180 - open my $read_fh, "<", $file_name
181 - or die "could not open ${file_name}: $!\n";
182 - $file_content = do { local $/ = undef; <$read_fh> };
183 - close $read_fh
184 - or die "unable to close: $!\n";
185 - }
186 -
187 - v_print("### Retrieving template\n");
188 - ($wiki_page_name = clean_filename($file_name)) =~ s/\.[^.]+$//;
189 - $template = get_template($remote_url, $wiki_page_name);
190 -
191 - v_print("### Parsing local content\n");
192 - $new_content = $wiki->api({
193 - action => 'parse',
194 - text => $file_content,
195 - title => $wiki_page_name
196 - }, {
197 - skip_encoding => 1
198 - }) or die "No response from remote mediawiki\n";
199 - $new_content = $new_content->{'parse'}->{'text'}->{'*'};
200 -
201 - v_print("### Merging contents\n");
202 - if ($preview_file_name eq EMPTY) {
203 - ($preview_file_name = $file_name) =~ s/\.[^.]+$/.html/;
204 - }
205 - open(my $save_fh, '>:encoding(UTF-8)', $preview_file_name)
206 - or die "Could not open: $!\n";
207 - print {$save_fh} merge_contents($template, $new_content, $remote_url);
208 - close($save_fh)
209 - or die "Could not close: $!\n";
210 -
211 - v_print("### Results\n");
212 - if ($autoload) {
213 - v_print("Launching browser w/ file: ${preview_file_name}");
214 - system('git', 'web--browse', $preview_file_name);
215 - } else {
216 - print {*STDERR} "Preview file saved as: ${preview_file_name}\n";
217 - }
218 -
219 - exit;
220 -}
221 -
222 -# uses global scope variable: $remote_name
223 -sub merge_contents {
224 - my $template = shift;
225 - my $content = shift;
226 - my $remote_url = shift;
227 - my ($content_tree, $html_tree, $mw_content_text);
228 - my $template_content_id = 'bodyContent';
229 -
230 - $html_tree = HTML::TreeBuilder->new;
231 - $html_tree->parse($template);
232 -
233 - $content_tree = HTML::TreeBuilder->new;
234 - $content_tree->parse($content);
235 -
236 - $template_content_id = Git::config("remote.${remote_name}.mwIDcontent")
237 - || $template_content_id;
238 - v_print("Using '${template_content_id}' as the content ID\n");
239 -
240 - $mw_content_text = $html_tree->look_down('id', $template_content_id);
241 - if (!defined $mw_content_text) {
242 - print {*STDERR} <<"CONFIG";
243 -Could not combine the new content with the template. You might want to
244 -configure `mediawiki.IDContent` in your config:
245 - git config --add remote.${remote_name}.mwIDcontent <id>
246 -and re-run the command afterward.
247 -CONFIG
248 - exit 1;
249 - }
250 - $mw_content_text->delete_content();
251 - $mw_content_text->push_content($content_tree);
252 -
253 - make_links_absolute($html_tree, $remote_url);
254 -
255 - return $html_tree->as_HTML;
256 -}
257 -
258 -sub make_links_absolute {
259 - my $html_tree = shift;
260 - my $remote_url = shift;
261 - for (@{ $html_tree->extract_links() }) {
262 - my ($link, $element, $attr) = @{ $_ };
263 - my $url = url($link)->canonical;
264 - if ($url !~ /#/) {
265 - $element->attr($attr, URI->new_abs($url, $remote_url));
266 - }
267 - }
268 - return $html_tree;
269 -}
270 -
271 -sub is_valid_remote {
272 - my $remote = shift;
273 - my @remotes = git_cmd_try {
274 - Git::command('remote') }
275 - "%s failed w/ code %d";
276 - my $found_remote = 0;
277 - foreach my $remote (@remotes) {
278 - if ($remote eq $remote) {
279 - $found_remote = 1;
280 - last;
281 - }
282 - }
283 - return $found_remote;
284 -}
285 -
286 -sub find_mediawiki_remotes {
287 - my @remotes = git_cmd_try {
288 - Git::command('remote'); }
289 - "%s failed w/ code %d";
290 - my $remote_url;
291 - my @valid_remotes = ();
292 - foreach my $remote (@remotes) {
293 - $remote_url = mediawiki_remote_url_maybe($remote);
294 - if ($remote_url) {
295 - push(@valid_remotes, $remote);
296 - }
297 - }
298 - return @valid_remotes;
299 -}
300 -
301 -sub find_upstream_remote_name {
302 - my $current_branch = git_cmd_try {
303 - Git::command_oneline('symbolic-ref', '--short', 'HEAD') }
304 - "%s failed w/ code %d";
305 - return Git::config("branch.${current_branch}.remote");
306 -}
307 -
308 -sub mediawiki_remote_url_maybe {
309 - my $remote = shift;
310 -
311 - # Find remote url
312 - my $remote_url = Git::config("remote.${remote}.url");
313 - if ($remote_url =~ s/mediawiki::(.*)/$1/) {
314 - return url($remote_url)->canonical;
315 - }
316 -
317 - return;
318 -}
319 -
320 -sub get_template {
321 - my $url = shift;
322 - my $page_name = shift;
323 - my ($req, $res, $code, $url_after);
324 -
325 - $req = LWP::UserAgent->new;
326 - if ($verbose) {
327 - $req->show_progress(1);
328 - }
329 -
330 - $res = $req->get("${url}/index.php?title=${page_name}");
331 - if (!$res->is_success) {
332 - $code = $res->code;
333 - $url_after = $res->request()->uri(); # resolve all redirections
334 - if ($code == HTTP_CODE_PAGE_NOT_FOUND) {
335 - if ($verbose) {
336 - print {*STDERR} <<"WARNING";
337 -Warning: Failed to retrieve '$page_name'. Create it on the mediawiki if you want
338 -all the links to work properly.
339 -Trying to use the mediawiki homepage as a fallback template ...
340 -WARNING
341 - }
342 -
343 - # LWP automatically redirects GET request
344 - $res = $req->get("${url}/index.php");
345 - if (!$res->is_success) {
346 - $url_after = $res->request()->uri(); # resolve all redirections
347 - die "Failed to get homepage @ ${url_after} w/ code ${code}\n";
348 - }
349 - } else {
350 - die "Failed to get '${page_name}' @ ${url_after} w/ code ${code}\n";
351 - }
352 - }
353 -
354 - return $res->decoded_content;
355 -}
356 -
357 -############################## Help Functions ##################################
358 -
359 -sub help {
360 - print {*STDOUT} <<'END';
361 -usage: git mw <command> <args>
362 -
363 -git mw commands are:
364 - help Display help information about git mw
365 - preview Parse and render local file into HTML
366 -END
367 - exit;
368 -}
contrib/mw-to-git/git-remote-mediawiki.perl deleted
-1390
@@ -1,1390 +0,0 @@
1 -#! /usr/bin/perl
2 -
3 -# Copyright (C) 2011
4 -# Jérémie Nikaes <jeremie.nikaes@ensimag.imag.fr>
5 -# Arnaud Lacurie <arnaud.lacurie@ensimag.imag.fr>
6 -# Claire Fousse <claire.fousse@ensimag.imag.fr>
7 -# David Amouyal <david.amouyal@ensimag.imag.fr>
8 -# Matthieu Moy <matthieu.moy@grenoble-inp.fr>
9 -# License: GPL v2 or later
10 -
11 -# Gateway between Git and MediaWiki.
12 -# Documentation & bugtracker: https://github.com/Git-Mediawiki/Git-Mediawiki
13 -
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 -
22 -# By default, use UTF-8 to communicate with Git and the user
23 -binmode STDERR, ':encoding(UTF-8)';
24 -binmode STDOUT, ':encoding(UTF-8)';
25 -
26 -use URI::Escape;
27 -
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";
31 -
32 -# It's not possible to create empty pages. New empty files in Git are
33 -# sent with this content instead.
34 -use constant EMPTY_CONTENT => "<!-- empty page -->\n";
35 -
36 -# used to reflect file creation or deletion in diff.
37 -use constant NULL_SHA1 => '0000000000000000000000000000000000000000';
38 -
39 -# Used on Git's side to reflect empty edit messages on the wiki
40 -use constant EMPTY_MESSAGE => '*Empty MediaWiki Message*';
41 -
42 -# Number of pages taken into account at once in submodule get_mw_page_list
43 -use constant SLICE_SIZE => 50;
44 -
45 -# Number of linked mediafile to get at once in get_linked_mediafiles
46 -# The query is split in small batches because of the MW API limit of
47 -# the number of links to be returned (500 links max).
48 -use constant BATCH_SIZE => 10;
49 -
50 -if (@ARGV != 2) {
51 - exit_error_usage();
52 -}
53 -
54 -my $remotename = $ARGV[0];
55 -my $url = $ARGV[1];
56 -
57 -# Accept both space-separated and multiple keys in config file.
58 -# Spaces should be written as _ anyway because we'll use chomp.
59 -my @tracked_pages = split(/[ \n]/, run_git_quoted(["config", "--get-all", "remote.${remotename}.pages"]));
60 -chomp(@tracked_pages);
61 -
62 -# Just like @tracked_pages, but for MediaWiki categories.
63 -my @tracked_categories = split(/[ \n]/, run_git_quoted(["config", "--get-all", "remote.${remotename}.categories"]));
64 -chomp(@tracked_categories);
65 -
66 -# Just like @tracked_categories, but for MediaWiki namespaces.
67 -my @tracked_namespaces = split(/[ \n]/, run_git_quoted(["config", "--get-all", "remote.${remotename}.namespaces"]));
68 -for (@tracked_namespaces) { s/_/ /g; }
69 -chomp(@tracked_namespaces);
70 -
71 -# Import media files on pull
72 -my $import_media = run_git_quoted(["config", "--get", "--bool", "remote.${remotename}.mediaimport"]);
73 -chomp($import_media);
74 -$import_media = ($import_media eq 'true');
75 -
76 -# Export media files on push
77 -my $export_media = run_git_quoted(["config", "--get", "--bool", "remote.${remotename}.mediaexport"]);
78 -chomp($export_media);
79 -$export_media = !($export_media eq 'false');
80 -
81 -my $wiki_login = run_git_quoted(["config", "--get", "remote.${remotename}.mwLogin"]);
82 -# Note: mwPassword is discouraged. Use the credential system instead.
83 -my $wiki_passwd = run_git_quoted(["config", "--get", "remote.${remotename}.mwPassword"]);
84 -my $wiki_domain = run_git_quoted(["config", "--get", "remote.${remotename}.mwDomain"]);
85 -chomp($wiki_login);
86 -chomp($wiki_passwd);
87 -chomp($wiki_domain);
88 -
89 -# Import only last revisions (both for clone and fetch)
90 -my $shallow_import = run_git_quoted(["config", "--get", "--bool", "remote.${remotename}.shallow"]);
91 -chomp($shallow_import);
92 -$shallow_import = ($shallow_import eq 'true');
93 -
94 -# Fetch (clone and pull) by revisions instead of by pages. This behavior
95 -# is more efficient when we have a wiki with lots of pages and we fetch
96 -# the revisions quite often so that they concern only few pages.
97 -# Possible values:
98 -# - by_rev: perform one query per new revision on the remote wiki
99 -# - by_page: query each tracked page for new revision
100 -my $fetch_strategy = run_git_quoted(["config", "--get", "remote.${remotename}.fetchStrategy"]);
101 -if (!$fetch_strategy) {
102 - $fetch_strategy = run_git_quoted(["config", "--get", "mediawiki.fetchStrategy"]);
103 -}
104 -chomp($fetch_strategy);
105 -if (!$fetch_strategy) {
106 - $fetch_strategy = 'by_page';
107 -}
108 -
109 -# Remember the timestamp corresponding to a revision id.
110 -my %basetimestamps;
111 -
112 -# Dumb push: don't update notes and mediawiki ref to reflect the last push.
113 -#
114 -# Configurable with mediawiki.dumbPush, or per-remote with
115 -# remote.<remotename>.dumbPush.
116 -#
117 -# This means the user will have to re-import the just-pushed
118 -# revisions. On the other hand, this means that the Git revisions
119 -# corresponding to MediaWiki revisions are all imported from the wiki,
120 -# regardless of whether they were initially created in Git or from the
121 -# web interface, hence all users will get the same history (i.e. if
122 -# the push from Git to MediaWiki loses some information, everybody
123 -# will get the history with information lost). If the import is
124 -# deterministic, this means everybody gets the same sha1 for each
125 -# MediaWiki revision.
126 -my $dumb_push = run_git_quoted(["config", "--get", "--bool", "remote.${remotename}.dumbPush"]);
127 -if (!$dumb_push) {
128 - $dumb_push = run_git_quoted(["config", "--get", "--bool", "mediawiki.dumbPush"]);
129 -}
130 -chomp($dumb_push);
131 -$dumb_push = ($dumb_push eq 'true');
132 -
133 -my $wiki_name = $url;
134 -$wiki_name =~ s{[^/]*://}{};
135 -# If URL is like http://user:password@example.com/, we clearly don't
136 -# want the password in $wiki_name. While we're there, also remove user
137 -# and '@' sign, to avoid author like MWUser@HTTPUser@host.com
138 -$wiki_name =~ s/^.*@//;
139 -
140 -# Commands parser
141 -while (<STDIN>) {
142 - chomp;
143 -
144 - if (!parse_command($_)) {
145 - last;
146 - }
147 -
148 - BEGIN { $| = 1 } # flush STDOUT, to make sure the previous
149 - # command is fully processed.
150 -}
151 -
152 -########################## Functions ##############################
153 -
154 -## error handling
155 -sub exit_error_usage {
156 - die "ERROR: git-remote-mediawiki module was not called with a correct number of\n" .
157 - "parameters\n" .
158 - "You may obtain this error because you attempted to run the git-remote-mediawiki\n" .
159 - "module directly.\n" .
160 - "This module can be used the following way:\n" .
161 - "\tgit clone mediawiki://<address of a mediawiki>\n" .
162 - "Then, use git commit, push and pull as with every normal git repository.\n";
163 -}
164 -
165 -sub parse_command {
166 - my ($line) = @_;
167 - my @cmd = split(/ /, $line);
168 - if (!defined $cmd[0]) {
169 - return 0;
170 - }
171 - if ($cmd[0] eq 'capabilities') {
172 - die("Too many arguments for capabilities\n")
173 - if (defined($cmd[1]));
174 - mw_capabilities();
175 - } elsif ($cmd[0] eq 'list') {
176 - die("Too many arguments for list\n") if (defined($cmd[2]));
177 - mw_list($cmd[1]);
178 - } elsif ($cmd[0] eq 'import') {
179 - die("Invalid argument for import\n")
180 - if ($cmd[1] eq EMPTY);
181 - die("Too many arguments for import\n")
182 - if (defined($cmd[2]));
183 - mw_import($cmd[1]);
184 - } elsif ($cmd[0] eq 'option') {
185 - die("Invalid arguments for option\n")
186 - if ($cmd[1] eq EMPTY || $cmd[2] eq EMPTY);
187 - die("Too many arguments for option\n")
188 - if (defined($cmd[3]));
189 - mw_option($cmd[1],$cmd[2]);
190 - } elsif ($cmd[0] eq 'push') {
191 - mw_push($cmd[1]);
192 - } else {
193 - print {*STDERR} "Unknown command. Aborting...\n";
194 - return 0;
195 - }
196 - return 1;
197 -}
198 -
199 -# MediaWiki API instance, created lazily.
200 -my $mediawiki;
201 -
202 -sub fatal_mw_error {
203 - my $action = shift;
204 - print STDERR "fatal: could not $action.\n";
205 - print STDERR "fatal: '$url' does not appear to be a mediawiki\n";
206 - if ($url =~ /^https/) {
207 - print STDERR "fatal: make sure '$url/api.php' is a valid page\n";
208 - print STDERR "fatal: and the SSL certificate is correct.\n";
209 - } else {
210 - print STDERR "fatal: make sure '$url/api.php' is a valid page.\n";
211 - }
212 - print STDERR "fatal: (error " .
213 - $mediawiki->{error}->{code} . ': ' .
214 - $mediawiki->{error}->{details} . ")\n";
215 - exit 1;
216 -}
217 -
218 -## Functions for listing pages on the remote wiki
219 -sub get_mw_tracked_pages {
220 - my $pages = shift;
221 - get_mw_page_list(\@tracked_pages, $pages);
222 - return;
223 -}
224 -
225 -sub get_mw_page_list {
226 - my $page_list = shift;
227 - my $pages = shift;
228 - my @some_pages = @{$page_list};
229 - while (@some_pages) {
230 - my $last_page = SLICE_SIZE;
231 - if ($#some_pages < $last_page) {
232 - $last_page = $#some_pages;
233 - }
234 - my @slice = @some_pages[0..$last_page];
235 - get_mw_first_pages(\@slice, $pages);
236 - @some_pages = @some_pages[(SLICE_SIZE + 1)..$#some_pages];
237 - }
238 - return;
239 -}
240 -
241 -sub get_mw_tracked_categories {
242 - my $pages = shift;
243 - foreach my $category (@tracked_categories) {
244 - if (index($category, ':') < 0) {
245 - # Mediawiki requires the Category
246 - # prefix, but let's not force the user
247 - # to specify it.
248 - $category = "Category:${category}";
249 - }
250 - my $mw_pages = $mediawiki->list( {
251 - action => 'query',
252 - list => 'categorymembers',
253 - cmtitle => $category,
254 - cmlimit => 'max' } )
255 - || die $mediawiki->{error}->{code} . ': '
256 - . $mediawiki->{error}->{details} . "\n";
257 - foreach my $page (@{$mw_pages}) {
258 - $pages->{$page->{title}} = $page;
259 - }
260 - }
261 - return;
262 -}
263 -
264 -sub get_mw_tracked_namespaces {
265 - my $pages = shift;
266 - foreach my $local_namespace (sort @tracked_namespaces) {
267 - my $namespace_id;
268 - if ($local_namespace eq "(Main)") {
269 - $namespace_id = 0;
270 - } else {
271 - $namespace_id = get_mw_namespace_id($local_namespace);
272 - }
273 - # virtual namespaces don't support allpages
274 - next if !defined($namespace_id) || $namespace_id < 0;
275 - my $mw_pages = $mediawiki->list( {
276 - action => 'query',
277 - list => 'allpages',
278 - apnamespace => $namespace_id,
279 - aplimit => 'max' } )
280 - || die $mediawiki->{error}->{code} . ': '
281 - . $mediawiki->{error}->{details} . "\n";
282 - print {*STDERR} "$#{$mw_pages} found in namespace $local_namespace ($namespace_id)\n";
283 - foreach my $page (@{$mw_pages}) {
284 - $pages->{$page->{title}} = $page;
285 - }
286 - }
287 - return;
288 -}
289 -
290 -sub get_mw_all_pages {
291 - my $pages = shift;
292 - # No user-provided list, get the list of pages from the API.
293 - my $mw_pages = $mediawiki->list({
294 - action => 'query',
295 - list => 'allpages',
296 - aplimit => 'max'
297 - });
298 - if (!defined($mw_pages)) {
299 - fatal_mw_error("get the list of wiki pages");
300 - }
301 - foreach my $page (@{$mw_pages}) {
302 - $pages->{$page->{title}} = $page;
303 - }
304 - return;
305 -}
306 -
307 -# queries the wiki for a set of pages. Meant to be used within a loop
308 -# querying the wiki for slices of page list.
309 -sub get_mw_first_pages {
310 - my $some_pages = shift;
311 - my @some_pages = @{$some_pages};
312 -
313 - my $pages = shift;
314 -
315 - # pattern 'page1|page2|...' required by the API
316 - my $titles = join('|', @some_pages);
317 -
318 - my $mw_pages = $mediawiki->api({
319 - action => 'query',
320 - titles => $titles,
321 - });
322 - if (!defined($mw_pages)) {
323 - fatal_mw_error("query the list of wiki pages");
324 - }
325 - while (my ($id, $page) = each(%{$mw_pages->{query}->{pages}})) {
326 - if ($id < 0) {
327 - print {*STDERR} "Warning: page $page->{title} not found on wiki\n";
328 - } else {
329 - $pages->{$page->{title}} = $page;
330 - }
331 - }
332 - return;
333 -}
334 -
335 -# Get the list of pages to be fetched according to configuration.
336 -sub get_mw_pages {
337 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
338 -
339 - print {*STDERR} "Listing pages on remote wiki...\n";
340 -
341 - my %pages; # hash on page titles to avoid duplicates
342 - my $user_defined;
343 - if (@tracked_pages) {
344 - $user_defined = 1;
345 - # The user provided a list of pages titles, but we
346 - # still need to query the API to get the page IDs.
347 - get_mw_tracked_pages(\%pages);
348 - }
349 - if (@tracked_categories) {
350 - $user_defined = 1;
351 - get_mw_tracked_categories(\%pages);
352 - }
353 - if (@tracked_namespaces) {
354 - $user_defined = 1;
355 - get_mw_tracked_namespaces(\%pages);
356 - }
357 - if (!$user_defined) {
358 - get_mw_all_pages(\%pages);
359 - }
360 - if ($import_media) {
361 - print {*STDERR} "Getting media files for selected pages...\n";
362 - if ($user_defined) {
363 - get_linked_mediafiles(\%pages);
364 - } else {
365 - get_all_mediafiles(\%pages);
366 - }
367 - }
368 - print {*STDERR} (scalar keys %pages) . " pages found.\n";
369 - return %pages;
370 -}
371 -
372 -# usage: $out = run_git_quoted(["command", "args", ...]);
373 -# $out = run_git_quoted(["command", "args", ...], "raw"); # don't interpret output as UTF-8.
374 -# $out = run_git_quoted_nostderr(["command", "args", ...]); # discard stderr
375 -# $out = run_git_quoted_nostderr(["command", "args", ...], "raw"); # ditto but raw instead of UTF-8 as above
376 -sub _run_git {
377 - my $args = shift;
378 - my $encoding = (shift || 'encoding(UTF-8)');
379 - open(my $git, "-|:${encoding}", @$args)
380 - or die "Unable to fork: $!\n";
381 - my $res = do {
382 - local $/ = undef;
383 - <$git>
384 - };
385 - close($git);
386 -
387 - return $res;
388 -}
389 -
390 -sub run_git_quoted {
391 - _run_git(["git", @{$_[0]}], $_[1]);
392 -}
393 -
394 -sub run_git_quoted_nostderr {
395 - _run_git(['sh', '-c', 'git "$@" 2>/dev/null', '--', @{$_[0]}], $_[1]);
396 -}
397 -
398 -sub get_all_mediafiles {
399 - my $pages = shift;
400 - # Attach list of all pages for media files from the API,
401 - # they are in a different namespace, only one namespace
402 - # can be queried at the same moment
403 - my $mw_pages = $mediawiki->list({
404 - action => 'query',
405 - list => 'allpages',
406 - apnamespace => get_mw_namespace_id('File'),
407 - aplimit => 'max'
408 - });
409 - if (!defined($mw_pages)) {
410 - print {*STDERR} "fatal: could not get the list of pages for media files.\n";
411 - print {*STDERR} "fatal: '$url' does not appear to be a mediawiki\n";
412 - print {*STDERR} "fatal: make sure '$url/api.php' is a valid page.\n";
413 - exit 1;
414 - }
415 - foreach my $page (@{$mw_pages}) {
416 - $pages->{$page->{title}} = $page;
417 - }
418 - return;
419 -}
420 -
421 -sub get_linked_mediafiles {
422 - my $pages = shift;
423 - my @titles = map { $_->{title} } values(%{$pages});
424 -
425 - my $batch = BATCH_SIZE;
426 - while (@titles) {
427 - if ($#titles < $batch) {
428 - $batch = $#titles;
429 - }
430 - my @slice = @titles[0..$batch];
431 -
432 - # pattern 'page1|page2|...' required by the API
433 - my $mw_titles = join('|', @slice);
434 -
435 - # Media files could be included or linked from
436 - # a page, get all related
437 - my $query = {
438 - action => 'query',
439 - prop => 'links|images',
440 - titles => $mw_titles,
441 - plnamespace => get_mw_namespace_id('File'),
442 - pllimit => 'max'
443 - };
444 - my $result = $mediawiki->api($query);
445 -
446 - while (my ($id, $page) = each(%{$result->{query}->{pages}})) {
447 - my @media_titles;
448 - if (defined($page->{links})) {
449 - my @link_titles
450 - = map { $_->{title} } @{$page->{links}};
451 - push(@media_titles, @link_titles);
452 - }
453 - if (defined($page->{images})) {
454 - my @image_titles
455 - = map { $_->{title} } @{$page->{images}};
456 - push(@media_titles, @image_titles);
457 - }
458 - if (@media_titles) {
459 - get_mw_page_list(\@media_titles, $pages);
460 - }
461 - }
462 -
463 - @titles = @titles[($batch+1)..$#titles];
464 - }
465 - return;
466 -}
467 -
468 -sub get_mw_mediafile_for_page_revision {
469 - # Name of the file on Wiki, with the prefix.
470 - my $filename = shift;
471 - my $timestamp = shift;
472 - my %mediafile;
473 -
474 - # Search if on a media file with given timestamp exists on
475 - # MediaWiki. In that case download the file.
476 - my $query = {
477 - action => 'query',
478 - prop => 'imageinfo',
479 - titles => "File:${filename}",
480 - iistart => $timestamp,
481 - iiend => $timestamp,
482 - iiprop => 'timestamp|archivename|url',
483 - iilimit => 1
484 - };
485 - my $result = $mediawiki->api($query);
486 -
487 - my ($fileid, $file) = each( %{$result->{query}->{pages}} );
488 - # If not defined it means there is no revision of the file for
489 - # given timestamp.
490 - if (defined($file->{imageinfo})) {
491 - $mediafile{title} = $filename;
492 -
493 - my $fileinfo = pop(@{$file->{imageinfo}});
494 - $mediafile{timestamp} = $fileinfo->{timestamp};
495 - # Mediawiki::API's download function doesn't support https URLs
496 - # and can't download old versions of files.
497 - print {*STDERR} "\tDownloading file $mediafile{title}, version $mediafile{timestamp}\n";
498 - $mediafile{content} = download_mw_mediafile($fileinfo->{url});
499 - }
500 - return %mediafile;
501 -}
502 -
503 -sub download_mw_mediafile {
504 - my $download_url = shift;
505 -
506 - my $response = $mediawiki->{ua}->get($download_url);
507 - if ($response->code == HTTP_CODE_OK) {
508 - # It is tempting to return
509 - # $response->decoded_content({charset => "none"}), but
510 - # when doing so, utf8::downgrade($content) fails with
511 - # "Wide character in subroutine entry".
512 - $response->decode();
513 - return $response->content();
514 - } else {
515 - print {*STDERR} "Error downloading mediafile from :\n";
516 - print {*STDERR} "URL: ${download_url}\n";
517 - print {*STDERR} 'Server response: ' . $response->code . q{ } . $response->message . "\n";
518 - exit 1;
519 - }
520 -}
521 -
522 -sub get_last_local_revision {
523 - # Get note regarding last mediawiki revision.
524 - my $note = run_git_quoted_nostderr(["notes", "--ref=${remotename}/mediawiki",
525 - "show", "refs/mediawiki/${remotename}/master"]);
526 - my @note_info = split(/ /, $note);
527 -
528 - my $lastrevision_number;
529 - if (!(defined($note_info[0]) && $note_info[0] eq 'mediawiki_revision:')) {
530 - print {*STDERR} 'No previous mediawiki revision found';
531 - $lastrevision_number = 0;
532 - } else {
533 - # Notes are formatted : mediawiki_revision: #number
534 - $lastrevision_number = $note_info[1];
535 - chomp($lastrevision_number);
536 - print {*STDERR} "Last local mediawiki revision found is ${lastrevision_number}";
537 - }
538 - return $lastrevision_number;
539 -}
540 -
541 -# Get the last remote revision without taking in account which pages are
542 -# tracked or not. This function makes a single request to the wiki thus
543 -# avoid a loop onto all tracked pages. This is useful for the fetch-by-rev
544 -# option.
545 -sub get_last_global_remote_rev {
546 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
547 -
548 - my $query = {
549 - action => 'query',
550 - list => 'recentchanges',
551 - prop => 'revisions',
552 - rclimit => '1',
553 - rcdir => 'older',
554 - };
555 - my $result = $mediawiki->api($query);
556 - return $result->{query}->{recentchanges}[0]->{revid};
557 -}
558 -
559 -# Get the last remote revision concerning the tracked pages and the tracked
560 -# categories.
561 -sub get_last_remote_revision {
562 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
563 -
564 - my %pages_hash = get_mw_pages();
565 - my @pages = values(%pages_hash);
566 -
567 - my $max_rev_num = 0;
568 -
569 - print {*STDERR} "Getting last revision id on tracked pages...\n";
570 -
571 - foreach my $page (@pages) {
572 - my $id = $page->{pageid};
573 -
574 - my $query = {
575 - action => 'query',
576 - prop => 'revisions',
577 - rvprop => 'ids|timestamp',
578 - pageids => $id,
579 - };
580 -
581 - my $result = $mediawiki->api($query);
582 -
583 - my $lastrev = pop(@{$result->{query}->{pages}->{$id}->{revisions}});
584 -
585 - $basetimestamps{$lastrev->{revid}} = $lastrev->{timestamp};
586 -
587 - $max_rev_num = ($lastrev->{revid} > $max_rev_num ? $lastrev->{revid} : $max_rev_num);
588 - }
589 -
590 - print {*STDERR} "Last remote revision found is $max_rev_num.\n";
591 - return $max_rev_num;
592 -}
593 -
594 -# Clean content before sending it to MediaWiki
595 -sub mediawiki_clean {
596 - my $string = shift;
597 - my $page_created = shift;
598 - # Mediawiki does not allow blank space at the end of a page and ends with a single \n.
599 - # This function right trims a string and adds a \n at the end to follow this rule
600 - $string =~ s/\s+$//;
601 - if ($string eq EMPTY && $page_created) {
602 - # Creating empty pages is forbidden.
603 - $string = EMPTY_CONTENT;
604 - }
605 - return $string."\n";
606 -}
607 -
608 -# Filter applied on MediaWiki data before adding them to Git
609 -sub mediawiki_smudge {
610 - my $string = shift;
611 - if ($string eq EMPTY_CONTENT) {
612 - $string = EMPTY;
613 - }
614 - # This \n is important. This is due to mediawiki's way to handle end of files.
615 - return "${string}\n";
616 -}
617 -
618 -sub literal_data {
619 - my ($content) = @_;
620 - print {*STDOUT} 'data ', bytes::length($content), "\n", $content;
621 - return;
622 -}
623 -
624 -sub literal_data_raw {
625 - # Output possibly binary content.
626 - my ($content) = @_;
627 - # Avoid confusion between size in bytes and in characters
628 - utf8::downgrade($content);
629 - binmode STDOUT, ':raw';
630 - print {*STDOUT} 'data ', bytes::length($content), "\n", $content;
631 - binmode STDOUT, ':encoding(UTF-8)';
632 - return;
633 -}
634 -
635 -sub mw_capabilities {
636 - # Revisions are imported to the private namespace
637 - # refs/mediawiki/$remotename/ by the helper and fetched into
638 - # refs/remotes/$remotename later by fetch.
639 - print {*STDOUT} "refspec refs/heads/*:refs/mediawiki/${remotename}/*\n";
640 - print {*STDOUT} "import\n";
641 - print {*STDOUT} "list\n";
642 - print {*STDOUT} "push\n";
643 - if ($dumb_push) {
644 - print {*STDOUT} "no-private-update\n";
645 - }
646 - print {*STDOUT} "\n";
647 - return;
648 -}
649 -
650 -sub mw_list {
651 - # MediaWiki do not have branches, we consider one branch arbitrarily
652 - # called master, and HEAD pointing to it.
653 - print {*STDOUT} "? refs/heads/master\n";
654 - print {*STDOUT} "\@refs/heads/master HEAD\n";
655 - print {*STDOUT} "\n";
656 - return;
657 -}
658 -
659 -sub mw_option {
660 - print {*STDERR} "remote-helper command 'option $_[0]' not yet implemented\n";
661 - print {*STDOUT} "unsupported\n";
662 - return;
663 -}
664 -
665 -sub fetch_mw_revisions_for_page {
666 - my $page = shift;
667 - my $id = shift;
668 - my $fetch_from = shift;
669 - my @page_revs = ();
670 - my $query = {
671 - action => 'query',
672 - prop => 'revisions',
673 - rvprop => 'ids',
674 - rvdir => 'newer',
675 - rvstartid => $fetch_from,
676 - rvlimit => 500,
677 - pageids => $id,
678 -
679 - # Let MediaWiki know that we support the latest API.
680 - continue => '',
681 - };
682 -
683 - my $revnum = 0;
684 - # Get 500 revisions at a time due to the mediawiki api limit
685 - while (1) {
686 - my $result = $mediawiki->api($query);
687 -
688 - # Parse each of those 500 revisions
689 - foreach my $revision (@{$result->{query}->{pages}->{$id}->{revisions}}) {
690 - my $page_rev_ids;
691 - $page_rev_ids->{pageid} = $page->{pageid};
692 - $page_rev_ids->{revid} = $revision->{revid};
693 - push(@page_revs, $page_rev_ids);
694 - $revnum++;
695 - }
696 -
697 - if ($result->{'query-continue'}) { # For legacy APIs
698 - $query->{rvstartid} = $result->{'query-continue'}->{revisions}->{rvstartid};
699 - } elsif ($result->{continue}) { # For newer APIs
700 - $query->{rvstartid} = $result->{continue}->{rvcontinue};
701 - $query->{continue} = $result->{continue}->{continue};
702 - } else {
703 - last;
704 - }
705 - }
706 - if ($shallow_import && @page_revs) {
707 - print {*STDERR} " Found 1 revision (shallow import).\n";
708 - @page_revs = sort {$b->{revid} <=> $a->{revid}} (@page_revs);
709 - return $page_revs[0];
710 - }
711 - print {*STDERR} " Found ${revnum} revision(s).\n";
712 - return @page_revs;
713 -}
714 -
715 -sub fetch_mw_revisions {
716 - my $pages = shift; my @pages = @{$pages};
717 - my $fetch_from = shift;
718 -
719 - my @revisions = ();
720 - my $n = 1;
721 - foreach my $page (@pages) {
722 - my $id = $page->{pageid};
723 - print {*STDERR} "page ${n}/", scalar(@pages), ': ', $page->{title}, "\n";
724 - $n++;
725 - my @page_revs = fetch_mw_revisions_for_page($page, $id, $fetch_from);
726 - @revisions = (@page_revs, @revisions);
727 - }
728 -
729 - return ($n, @revisions);
730 -}
731 -
732 -sub fe_escape_path {
733 - my $path = shift;
734 - $path =~ s/\\/\\\\/g;
735 - $path =~ s/"/\\"/g;
736 - $path =~ s/\n/\\n/g;
737 - return qq("${path}");
738 -}
739 -
740 -sub import_file_revision {
741 - my $commit = shift;
742 - my %commit = %{$commit};
743 - my $full_import = shift;
744 - my $n = shift;
745 - my $mediafile = shift;
746 - my %mediafile;
747 - if ($mediafile) {
748 - %mediafile = %{$mediafile};
749 - }
750 -
751 - my $title = $commit{title};
752 - my $comment = $commit{comment};
753 - my $content = $commit{content};
754 - my $author = $commit{author};
755 - my $date = $commit{date};
756 -
757 - print {*STDOUT} "commit refs/mediawiki/${remotename}/master\n";
758 - print {*STDOUT} "mark :${n}\n";
759 - print {*STDOUT} "committer ${author} <${author}\@${wiki_name}> " . $date->epoch . " +0000\n";
760 - literal_data($comment);
761 -
762 - # If it's not a clone, we need to know where to start from
763 - if (!$full_import && $n == 1) {
764 - print {*STDOUT} "from refs/mediawiki/${remotename}/master^0\n";
765 - }
766 - if ($content ne DELETED_CONTENT) {
767 - print {*STDOUT} 'M 644 inline ' .
768 - fe_escape_path("${title}.mw") . "\n";
769 - literal_data($content);
770 - if (%mediafile) {
771 - print {*STDOUT} 'M 644 inline '
772 - . fe_escape_path($mediafile{title}) . "\n";
773 - literal_data_raw($mediafile{content});
774 - }
775 - print {*STDOUT} "\n\n";
776 - } else {
777 - print {*STDOUT} 'D ' . fe_escape_path("${title}.mw") . "\n";
778 - }
779 -
780 - # mediawiki revision number in the git note
781 - if ($full_import && $n == 1) {
782 - print {*STDOUT} "reset refs/notes/${remotename}/mediawiki\n";
783 - }
784 - print {*STDOUT} "commit refs/notes/${remotename}/mediawiki\n";
785 - print {*STDOUT} "committer ${author} <${author}\@${wiki_name}> " . $date->epoch . " +0000\n";
786 - literal_data('Note added by git-mediawiki during import');
787 - if (!$full_import && $n == 1) {
788 - print {*STDOUT} "from refs/notes/${remotename}/mediawiki^0\n";
789 - }
790 - print {*STDOUT} "N inline :${n}\n";
791 - literal_data("mediawiki_revision: $commit{mw_revision}");
792 - print {*STDOUT} "\n\n";
793 - return;
794 -}
795 -
796 -# parse a sequence of
797 -# <cmd> <arg1>
798 -# <cmd> <arg2>
799 -# \n
800 -# (like batch sequence of import and sequence of push statements)
801 -sub get_more_refs {
802 - my $cmd = shift;
803 - my @refs;
804 - while (1) {
805 - my $line = <STDIN>;
806 - if ($line =~ /^$cmd (.*)$/) {
807 - push(@refs, $1);
808 - } elsif ($line eq "\n") {
809 - return @refs;
810 - } else {
811 - die("Invalid command in a '$cmd' batch: $_\n");
812 - }
813 - }
814 - return;
815 -}
816 -
817 -sub mw_import {
818 - # multiple import commands can follow each other.
819 - my @refs = (shift, get_more_refs('import'));
820 - my $processedRefs;
821 - foreach my $ref (@refs) {
822 - next if $processedRefs->{$ref}; # skip duplicates: "import refs/heads/master" being issued twice; TODO: why?
823 - $processedRefs->{$ref} = 1;
824 - mw_import_ref($ref);
825 - }
826 - print {*STDOUT} "done\n";
827 - return;
828 -}
829 -
830 -sub mw_import_ref {
831 - my $ref = shift;
832 - # The remote helper will call "import HEAD" and
833 - # "import refs/heads/master".
834 - # Since HEAD is a symbolic ref to master (by convention,
835 - # followed by the output of the command "list" that we gave),
836 - # we don't need to do anything in this case.
837 - if ($ref eq 'HEAD') {
838 - return;
839 - }
840 -
841 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
842 -
843 - print {*STDERR} "Searching revisions...\n";
844 - my $last_local = get_last_local_revision();
845 - my $fetch_from = $last_local + 1;
846 - if ($fetch_from == 1) {
847 - print {*STDERR} ", fetching from beginning.\n";
848 - } else {
849 - print {*STDERR} ", fetching from here.\n";
850 - }
851 -
852 - my $n = 0;
853 - if ($fetch_strategy eq 'by_rev') {
854 - print {*STDERR} "Fetching & writing export data by revs...\n";
855 - $n = mw_import_ref_by_revs($fetch_from);
856 - } elsif ($fetch_strategy eq 'by_page') {
857 - print {*STDERR} "Fetching & writing export data by pages...\n";
858 - $n = mw_import_ref_by_pages($fetch_from);
859 - } else {
860 - print {*STDERR} qq(fatal: invalid fetch strategy "${fetch_strategy}".\n);
861 - print {*STDERR} "Check your configuration variables remote.${remotename}.fetchStrategy and mediawiki.fetchStrategy\n";
862 - exit 1;
863 - }
864 -
865 - if ($fetch_from == 1 && $n == 0) {
866 - print {*STDERR} "You appear to have cloned an empty MediaWiki.\n";
867 - # Something has to be done remote-helper side. If nothing is done, an error is
868 - # thrown saying that HEAD is referring to unknown object 0000000000000000000
869 - # and the clone fails.
870 - }
871 - return;
872 -}
873 -
874 -sub mw_import_ref_by_pages {
875 -
876 - my $fetch_from = shift;
877 - my %pages_hash = get_mw_pages();
878 - my @pages = values(%pages_hash);
879 -
880 - my ($n, @revisions) = fetch_mw_revisions(\@pages, $fetch_from);
881 -
882 - @revisions = sort {$a->{revid} <=> $b->{revid}} @revisions;
883 - my @revision_ids = map { $_->{revid} } @revisions;
884 -
885 - return mw_import_revids($fetch_from, \@revision_ids, \%pages_hash);
886 -}
887 -
888 -sub mw_import_ref_by_revs {
889 -
890 - my $fetch_from = shift;
891 - my %pages_hash = get_mw_pages();
892 -
893 - my $last_remote = get_last_global_remote_rev();
894 - my @revision_ids = $fetch_from..$last_remote;
895 - return mw_import_revids($fetch_from, \@revision_ids, \%pages_hash);
896 -}
897 -
898 -# Import revisions given in second argument (array of integers).
899 -# Only pages appearing in the third argument (hash indexed by page titles)
900 -# will be imported.
901 -sub mw_import_revids {
902 - my $fetch_from = shift;
903 - my $revision_ids = shift;
904 - my $pages = shift;
905 -
906 - my $n = 0;
907 - my $n_actual = 0;
908 - my $last_timestamp = 0; # Placeholder in case $rev->timestamp is undefined
909 -
910 - foreach my $pagerevid (@{$revision_ids}) {
911 - # Count page even if we skip it, since we display
912 - # $n/$total and $total includes skipped pages.
913 - $n++;
914 -
915 - # fetch the content of the pages
916 - my $query = {
917 - action => 'query',
918 - prop => 'revisions',
919 - rvprop => 'content|timestamp|comment|user|ids',
920 - revids => $pagerevid,
921 - };
922 -
923 - my $result = $mediawiki->api($query);
924 -
925 - if (!$result) {
926 - die "Failed to retrieve modified page for revision $pagerevid\n";
927 - }
928 -
929 - if (defined($result->{query}->{badrevids}->{$pagerevid})) {
930 - # The revision id does not exist on the remote wiki.
931 - next;
932 - }
933 -
934 - if (!defined($result->{query}->{pages})) {
935 - die "Invalid revision ${pagerevid}.\n";
936 - }
937 -
938 - my @result_pages = values(%{$result->{query}->{pages}});
939 - my $result_page = $result_pages[0];
940 - my $rev = $result_pages[0]->{revisions}->[0];
941 -
942 - my $page_title = $result_page->{title};
943 -
944 - if (!exists($pages->{$page_title})) {
945 - print {*STDERR} "${n}/", scalar(@{$revision_ids}),
946 - ": Skipping revision #$rev->{revid} of ${page_title}\n";
947 - next;
948 - }
949 -
950 - $n_actual++;
951 -
952 - my %commit;
953 - $commit{author} = $rev->{user} || 'Anonymous';
954 - $commit{comment} = $rev->{comment} || EMPTY_MESSAGE;
955 - $commit{title} = smudge_filename($page_title);
956 - $commit{mw_revision} = $rev->{revid};
957 - $commit{content} = mediawiki_smudge($rev->{'*'});
958 -
959 - if (!defined($rev->{timestamp})) {
960 - $last_timestamp++;
961 - } else {
962 - $last_timestamp = $rev->{timestamp};
963 - }
964 - $commit{date} = DateTime::Format::ISO8601->parse_datetime($last_timestamp);
965 -
966 - # Differentiates classic pages and media files.
967 - my ($namespace, $filename) = $page_title =~ /^([^:]*):(.*)$/;
968 - my %mediafile;
969 - if ($namespace) {
970 - my $id = get_mw_namespace_id($namespace);
971 - if ($id && $id == get_mw_namespace_id('File')) {
972 - %mediafile = get_mw_mediafile_for_page_revision($filename, $rev->{timestamp});
973 - }
974 - }
975 - # If this is a revision of the media page for new version
976 - # of a file do one common commit for both file and media page.
977 - # Else do commit only for that page.
978 - print {*STDERR} "${n}/", scalar(@{$revision_ids}), ": Revision #$rev->{revid} of $commit{title}\n";
979 - import_file_revision(\%commit, ($fetch_from == 1), $n_actual, \%mediafile);
980 - }
981 -
982 - return $n_actual;
983 -}
984 -
985 -sub error_non_fast_forward {
986 - my $advice = run_git_quoted(["config", "--bool", "advice.pushNonFastForward"]);
987 - chomp($advice);
988 - if ($advice ne 'false') {
989 - # Native git-push would show this after the summary.
990 - # We can't ask it to display it cleanly, so print it
991 - # ourselves before.
992 - print {*STDERR} "To prevent you from losing history, non-fast-forward updates were rejected\n";
993 - print {*STDERR} "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n";
994 - print {*STDERR} "'Note about fast-forwards' section of 'git push --help' for details.\n";
995 - }
996 - print {*STDOUT} qq(error $_[0] "non-fast-forward"\n);
997 - return 0;
998 -}
999 -
1000 -sub mw_upload_file {
1001 - my $complete_file_name = shift;
1002 - my $new_sha1 = shift;
1003 - my $extension = shift;
1004 - my $file_deleted = shift;
1005 - my $summary = shift;
1006 - my $newrevid;
1007 - my $path = "File:${complete_file_name}";
1008 - my %hashFiles = get_allowed_file_extensions();
1009 - if (!exists($hashFiles{$extension})) {
1010 - print {*STDERR} "${complete_file_name} is not a permitted file on this wiki.\n";
1011 - print {*STDERR} "Check the configuration of file uploads in your mediawiki.\n";
1012 - return $newrevid;
1013 - }
1014 - # Deleting and uploading a file requires a privileged user
1015 - if ($file_deleted) {
1016 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1017 - my $query = {
1018 - action => 'delete',
1019 - title => $path,
1020 - reason => $summary
1021 - };
1022 - if (!$mediawiki->edit($query)) {
1023 - print {*STDERR} "Failed to delete file on remote wiki\n";
1024 - print {*STDERR} "Check your permissions on the remote site. Error code:\n";
1025 - print {*STDERR} $mediawiki->{error}->{code} . ':' . $mediawiki->{error}->{details};
1026 - exit 1;
1027 - }
1028 - } else {
1029 - # Don't let perl try to interpret file content as UTF-8 => use "raw"
1030 - my $content = run_git_quoted(["cat-file", "blob", $new_sha1], 'raw');
1031 - if ($content ne EMPTY) {
1032 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1033 - $mediawiki->{config}->{upload_url} =
1034 - "${url}/index.php/Special:Upload";
1035 - $mediawiki->edit({
1036 - action => 'upload',
1037 - filename => $complete_file_name,
1038 - comment => $summary,
1039 - file => [undef,
1040 - $complete_file_name,
1041 - Content => $content],
1042 - ignorewarnings => 1,
1043 - }, {
1044 - skip_encoding => 1
1045 - } ) || die $mediawiki->{error}->{code} . ':'
1046 - . $mediawiki->{error}->{details} . "\n";
1047 - my $last_file_page = $mediawiki->get_page({title => $path});
1048 - $newrevid = $last_file_page->{revid};
1049 - print {*STDERR} "Pushed file: ${new_sha1} - ${complete_file_name}.\n";
1050 - } else {
1051 - print {*STDERR} "Empty file ${complete_file_name} not pushed.\n";
1052 - }
1053 - }
1054 - return $newrevid;
1055 -}
1056 -
1057 -sub mw_push_file {
1058 - my $diff_info = shift;
1059 - # $diff_info contains a string in this format:
1060 - # 100644 100644 <sha1_of_blob_before_commit> <sha1_of_blob_now> <status>
1061 - my @diff_info_split = split(/[ \t]/, $diff_info);
1062 -
1063 - # Filename, including .mw extension
1064 - my $complete_file_name = shift;
1065 - # Commit message
1066 - my $summary = shift;
1067 - # MediaWiki revision number. Keep the previous one by default,
1068 - # in case there's no edit to perform.
1069 - my $oldrevid = shift;
1070 - my $newrevid;
1071 -
1072 - if ($summary eq EMPTY_MESSAGE) {
1073 - $summary = EMPTY;
1074 - }
1075 -
1076 - my $new_sha1 = $diff_info_split[3];
1077 - my $old_sha1 = $diff_info_split[2];
1078 - my $page_created = ($old_sha1 eq NULL_SHA1);
1079 - my $page_deleted = ($new_sha1 eq NULL_SHA1);
1080 - $complete_file_name = clean_filename($complete_file_name);
1081 -
1082 - my ($title, $extension) = $complete_file_name =~ /^(.*)\.([^\.]*)$/;
1083 - if (!defined($extension)) {
1084 - $extension = EMPTY;
1085 - }
1086 - if ($extension eq 'mw') {
1087 - my $ns = get_mw_namespace_id_for_page($complete_file_name);
1088 - if ($ns && $ns == get_mw_namespace_id('File') && (!$export_media)) {
1089 - print {*STDERR} "Ignoring media file related page: ${complete_file_name}\n";
1090 - return ($oldrevid, 'ok');
1091 - }
1092 - my $file_content;
1093 - if ($page_deleted) {
1094 - # Deleting a page usually requires
1095 - # special privileges. A common
1096 - # convention is to replace the page
1097 - # with this content instead:
1098 - $file_content = DELETED_CONTENT;
1099 - } else {
1100 - $file_content = run_git_quoted(["cat-file", "blob", $new_sha1]);
1101 - }
1102 -
1103 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1104 -
1105 - my $result = $mediawiki->edit( {
1106 - action => 'edit',
1107 - summary => $summary,
1108 - title => $title,
1109 - basetimestamp => $basetimestamps{$oldrevid},
1110 - text => mediawiki_clean($file_content, $page_created),
1111 - }, {
1112 - skip_encoding => 1 # Helps with names with accentuated characters
1113 - });
1114 - if (!$result) {
1115 - if ($mediawiki->{error}->{code} == 3) {
1116 - # edit conflicts, considered as non-fast-forward
1117 - print {*STDERR} 'Warning: Error ' .
1118 - $mediawiki->{error}->{code} .
1119 - ' from mediawiki: ' . $mediawiki->{error}->{details} .
1120 - ".\n";
1121 - return ($oldrevid, 'non-fast-forward');
1122 - } else {
1123 - # Other errors. Shouldn't happen => just die()
1124 - die 'Fatal: Error ' .
1125 - $mediawiki->{error}->{code} .
1126 - ' from mediawiki: ' . $mediawiki->{error}->{details} . "\n";
1127 - }
1128 - }
1129 - $newrevid = $result->{edit}->{newrevid};
1130 - print {*STDERR} "Pushed file: ${new_sha1} - ${title}\n";
1131 - } elsif ($export_media) {
1132 - $newrevid = mw_upload_file($complete_file_name, $new_sha1,
1133 - $extension, $page_deleted,
1134 - $summary);
1135 - } else {
1136 - print {*STDERR} "Ignoring media file ${title}\n";
1137 - }
1138 - $newrevid = ($newrevid or $oldrevid);
1139 - return ($newrevid, 'ok');
1140 -}
1141 -
1142 -sub mw_push {
1143 - # multiple push statements can follow each other
1144 - my @refsspecs = (shift, get_more_refs('push'));
1145 - my $pushed;
1146 - for my $refspec (@refsspecs) {
1147 - my ($force, $local, $remote) = $refspec =~ /^(\+)?([^:]*):([^:]*)$/
1148 - or die("Invalid refspec for push. Expected <src>:<dst> or +<src>:<dst>\n");
1149 - if ($force) {
1150 - print {*STDERR} "Warning: forced push not allowed on a MediaWiki.\n";
1151 - }
1152 - if ($local eq EMPTY) {
1153 - print {*STDERR} "Cannot delete remote branch on a MediaWiki\n";
1154 - print {*STDOUT} "error ${remote} cannot delete\n";
1155 - next;
1156 - }
1157 - if ($remote ne 'refs/heads/master') {
1158 - print {*STDERR} "Only push to the branch 'master' is supported on a MediaWiki\n";
1159 - print {*STDOUT} "error ${remote} only master allowed\n";
1160 - next;
1161 - }
1162 - if (mw_push_revision($local, $remote)) {
1163 - $pushed = 1;
1164 - }
1165 - }
1166 -
1167 - # Notify Git that the push is done
1168 - print {*STDOUT} "\n";
1169 -
1170 - if ($pushed && $dumb_push) {
1171 - print {*STDERR} "Just pushed some revisions to MediaWiki.\n";
1172 - print {*STDERR} "The pushed revisions now have to be re-imported, and your current branch\n";
1173 - print {*STDERR} "needs to be updated with these re-imported commits. You can do this with\n";
1174 - print {*STDERR} "\n";
1175 - print {*STDERR} " git pull --rebase\n";
1176 - print {*STDERR} "\n";
1177 - }
1178 - return;
1179 -}
1180 -
1181 -sub mw_push_revision {
1182 - my $local = shift;
1183 - my $remote = shift; # actually, this has to be "refs/heads/master" at this point.
1184 - my $last_local_revid = get_last_local_revision();
1185 - print {*STDERR} ".\n"; # Finish sentence started by get_last_local_revision()
1186 - my $last_remote_revid = get_last_remote_revision();
1187 - my $mw_revision = $last_remote_revid;
1188 -
1189 - # Get sha1 of commit pointed by local HEAD
1190 - my $HEAD_sha1 = run_git_quoted_nostderr(["rev-parse", $local]);
1191 - chomp($HEAD_sha1);
1192 - # Get sha1 of commit pointed by remotes/$remotename/master
1193 - my $remoteorigin_sha1 = run_git_quoted_nostderr(["rev-parse", "refs/remotes/${remotename}/master"]);
1194 - chomp($remoteorigin_sha1);
1195 -
1196 - if ($last_local_revid > 0 &&
1197 - $last_local_revid < $last_remote_revid) {
1198 - return error_non_fast_forward($remote);
1199 - }
1200 -
1201 - if ($HEAD_sha1 eq $remoteorigin_sha1) {
1202 - # nothing to push
1203 - return 0;
1204 - }
1205 -
1206 - # Get every commit in between HEAD and refs/remotes/origin/master,
1207 - # including HEAD and refs/remotes/origin/master
1208 - my @commit_pairs = ();
1209 - if ($last_local_revid > 0) {
1210 - my $parsed_sha1 = $remoteorigin_sha1;
1211 - # Find a path from last MediaWiki commit to pushed commit
1212 - print {*STDERR} "Computing path from local to remote ...\n";
1213 - my @local_ancestry = split(/\n/, run_git_quoted(["rev-list", "--boundary", "--parents", $local, "^${parsed_sha1}"]));
1214 - my %local_ancestry;
1215 - foreach my $line (@local_ancestry) {
1216 - if (my ($child, $parents) = $line =~ /^-?([a-f0-9]+) ([a-f0-9 ]+)/) {
1217 - foreach my $parent (split(/ /, $parents)) {
1218 - $local_ancestry{$parent} = $child;
1219 - }
1220 - } elsif (!$line =~ /^([a-f0-9]+)/) {
1221 - die "Unexpected output from git rev-list: ${line}\n";
1222 - }
1223 - }
1224 - while ($parsed_sha1 ne $HEAD_sha1) {
1225 - my $child = $local_ancestry{$parsed_sha1};
1226 - if (!$child) {
1227 - print {*STDERR} "Cannot find a path in history from remote commit to last commit\n";
1228 - return error_non_fast_forward($remote);
1229 - }
1230 - push(@commit_pairs, [$parsed_sha1, $child]);
1231 - $parsed_sha1 = $child;
1232 - }
1233 - } else {
1234 - # No remote mediawiki revision. Export the whole
1235 - # history (linearized with --first-parent)
1236 - print {*STDERR} "Warning: no common ancestor, pushing complete history\n";
1237 - my $history = run_git_quoted(["rev-list", "--first-parent", "--children", $local]);
1238 - my @history = split(/\n/, $history);
1239 - @history = @history[1..$#history];
1240 - foreach my $line (reverse @history) {
1241 - my @commit_info_split = split(/[ \n]/, $line);
1242 - push(@commit_pairs, \@commit_info_split);
1243 - }
1244 - }
1245 -
1246 - foreach my $commit_info_split (@commit_pairs) {
1247 - my $sha1_child = @{$commit_info_split}[0];
1248 - my $sha1_commit = @{$commit_info_split}[1];
1249 - my $diff_infos = run_git_quoted(["diff-tree", "-r", "--raw", "-z", $sha1_child, $sha1_commit]);
1250 - # TODO: we could detect rename, and encode them with a #redirect on the wiki.
1251 - # TODO: for now, it's just a delete+add
1252 - my @diff_info_list = split(/\0/, $diff_infos);
1253 - # Keep the subject line of the commit message as mediawiki comment for the revision
1254 - my $commit_msg = run_git_quoted(["log", "--no-walk", '--format="%s"', $sha1_commit]);
1255 - chomp($commit_msg);
1256 - # Push every blob
1257 - while (@diff_info_list) {
1258 - my $status;
1259 - # git diff-tree -z gives an output like
1260 - # <metadata>\0<filename1>\0
1261 - # <metadata>\0<filename2>\0
1262 - # and we've split on \0.
1263 - my $info = shift(@diff_info_list);
1264 - my $file = shift(@diff_info_list);
1265 - ($mw_revision, $status) = mw_push_file($info, $file, $commit_msg, $mw_revision);
1266 - if ($status eq 'non-fast-forward') {
1267 - # we may already have sent part of the
1268 - # commit to MediaWiki, but it's too
1269 - # late to cancel it. Stop the push in
1270 - # the middle, but still give an
1271 - # accurate error message.
1272 - return error_non_fast_forward($remote);
1273 - }
1274 - if ($status ne 'ok') {
1275 - die("Unknown error from mw_push_file()\n");
1276 - }
1277 - }
1278 - if (!$dumb_push) {
1279 - run_git_quoted(["notes", "--ref=${remotename}/mediawiki",
1280 - "add", "-f", "-m",
1281 - "mediawiki_revision: ${mw_revision}",
1282 - $sha1_commit]);
1283 - }
1284 - }
1285 -
1286 - print {*STDOUT} "ok ${remote}\n";
1287 - return 1;
1288 -}
1289 -
1290 -sub get_allowed_file_extensions {
1291 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1292 -
1293 - my $query = {
1294 - action => 'query',
1295 - meta => 'siteinfo',
1296 - siprop => 'fileextensions'
1297 - };
1298 - my $result = $mediawiki->api($query);
1299 - my @file_extensions = map { $_->{ext}} @{$result->{query}->{fileextensions}};
1300 - my %hashFile = map { $_ => 1 } @file_extensions;
1301 -
1302 - return %hashFile;
1303 -}
1304 -
1305 -# In memory cache for MediaWiki namespace ids.
1306 -my %namespace_id;
1307 -
1308 -# Namespaces whose id is cached in the configuration file
1309 -# (to avoid duplicates)
1310 -my %cached_mw_namespace_id;
1311 -
1312 -# Return MediaWiki id for a canonical namespace name.
1313 -# Ex.: "File", "Project".
1314 -sub get_mw_namespace_id {
1315 - $mediawiki = connect_maybe($mediawiki, $remotename, $url);
1316 - my $name = shift;
1317 -
1318 - if (!exists $namespace_id{$name}) {
1319 - # Look at configuration file, if the record for that namespace is
1320 - # already cached. Namespaces are stored in form:
1321 - # "Name_of_namespace:Id_namespace", ex.: "File:6".
1322 - my @temp = split(/\n/,
1323 - run_git_quoted(["config", "--get-all", "remote.${remotename}.namespaceCache"]));
1324 - chomp(@temp);
1325 - foreach my $ns (@temp) {
1326 - my ($n, $id) = split(/:/, $ns);
1327 - if ($id eq 'notANameSpace') {
1328 - $namespace_id{$n} = {is_namespace => 0};
1329 - } else {
1330 - $namespace_id{$n} = {is_namespace => 1, id => $id};
1331 - }
1332 - $cached_mw_namespace_id{$n} = 1;
1333 - }
1334 - }
1335 -
1336 - if (!exists $namespace_id{$name}) {
1337 - print {*STDERR} "Namespace ${name} not found in cache, querying the wiki ...\n";
1338 - # NS not found => get namespace id from MW and store it in
1339 - # configuration file.
1340 - my $query = {
1341 - action => 'query',
1342 - meta => 'siteinfo',
1343 - siprop => 'namespaces'
1344 - };
1345 - my $result = $mediawiki->api($query);
1346 -
1347 - while (my ($id, $ns) = each(%{$result->{query}->{namespaces}})) {
1348 - if (defined($ns->{id}) && defined($ns->{canonical})) {
1349 - $namespace_id{$ns->{canonical}} = {is_namespace => 1, id => $ns->{id}};
1350 - if ($ns->{'*'}) {
1351 - # alias (e.g. french Fichier: as alias for canonical File:)
1352 - $namespace_id{$ns->{'*'}} = {is_namespace => 1, id => $ns->{id}};
1353 - }
1354 - }
1355 - }
1356 - }
1357 -
1358 - my $ns = $namespace_id{$name};
1359 - my $id;
1360 -
1361 - if (!defined $ns) {
1362 - my @namespaces = map { s/ /_/g; $_; } sort keys %namespace_id;
1363 - print {*STDERR} "No such namespace ${name} on MediaWiki, known namespaces: @namespaces\n";
1364 - $ns = {is_namespace => 0};
1365 - $namespace_id{$name} = $ns;
1366 - }
1367 -
1368 - if ($ns->{is_namespace}) {
1369 - $id = $ns->{id};
1370 - }
1371 -
1372 - # Store "notANameSpace" as special value for inexisting namespaces
1373 - my $store_id = ($id || 'notANameSpace');
1374 -
1375 - # Store explicitly requested namespaces on disk
1376 - if (!exists $cached_mw_namespace_id{$name}) {
1377 - run_git_quoted(["config", "--add", "remote.${remotename}.namespaceCache", "${name}:${store_id}"]);
1378 - $cached_mw_namespace_id{$name} = 1;
1379 - }
1380 - return $id;
1381 -}
1382 -
1383 -sub get_mw_namespace_id_for_page {
1384 - my $namespace = shift;
1385 - if ($namespace =~ /^([^:]*):/) {
1386 - return get_mw_namespace_id($namespace);
1387 - } else {
1388 - return;
1389 - }
1390 -}
contrib/mw-to-git/git-remote-mediawiki.txt deleted
-7
@@ -1,7 +0,0 @@
1 -Git-Mediawiki is a project which aims the creation of a gate
2 -between git and mediawiki, allowing git users to push and pull
3 -objects from mediawiki just as one would do with a classic git
4 -repository thanks to remote-helpers.
5 -
6 -For more information, visit the wiki at
7 -https://github.com/Git-Mediawiki/Git-Mediawiki
contrib/mw-to-git/t/.gitignore deleted
-4
@@ -1,4 +0,0 @@
1 -WEB/
2 -mediawiki/
3 -trash directory.t*/
4 -test-results/
contrib/mw-to-git/t/Makefile deleted
-32
@@ -1,32 +0,0 @@
1 -#
2 -# Copyright (C) 2012
3 -# Charles Roussel <charles.roussel@ensimag.imag.fr>
4 -# Simon Cathebras <simon.cathebras@ensimag.imag.fr>
5 -# Julien Khayat <julien.khayat@ensimag.imag.fr>
6 -# Guillaume Sasdy <guillaume.sasdy@ensimag.imag.fr>
7 -# Simon Perrat <simon.perrat@ensimag.imag.fr>
8 -#
9 -## Test git-remote-mediawiki
10 -
11 -# The default target of this Makefile is...
12 -all:: test
13 -
14 --include ../../../config.mak.autogen
15 --include ../../../config.mak
16 -
17 -T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
18 -
19 -.PHONY: help test clean all
20 -
21 -help:
22 - @echo 'Run "$(MAKE) test" to launch test scripts'
23 - @echo 'Run "$(MAKE) clean" to remove trash folders'
24 -
25 -test:
26 - @for t in $(T); do \
27 - echo "$$t"; \
28 - "./$$t" || exit 1; \
29 - done
30 -
31 -clean:
32 - $(RM) -r 'trash directory'.*
contrib/mw-to-git/t/README deleted
-124
@@ -1,124 +0,0 @@
1 -Tests for Mediawiki-to-Git
2 -==========================
3 -
4 -Introduction
5 -------------
6 -This manual describes how to install the git-remote-mediawiki test
7 -environment on a machine with git installed on it.
8 -
9 -Prerequisite
10 -------------
11 -
12 -In order to run this test environment correctly, you will need to
13 -install the following packages (Debian/Ubuntu names, may need to be
14 -adapted for another distribution):
15 -
16 -* lighttpd
17 -* php
18 -* php-cgi
19 -* php-cli
20 -* php-curl
21 -* php-sqlite
22 -
23 -Principles and Technical Choices
24 ---------------------------------
25 -
26 -The test environment makes it easy to install and manipulate one or
27 -several MediaWiki instances. To allow developers to run the testsuite
28 -easily, the environment does not require root privilege (except to
29 -install the required packages if needed). It starts a webserver
30 -instance on the user's account (using lighttpd greatly helps for
31 -that), and does not need a separate database daemon (thanks to the use
32 -of sqlite).
33 -
34 -Run the test environment
35 -------------------------
36 -
37 -Install a new wiki
38 -~~~~~~~~~~~~~~~~~~
39 -
40 -Once you have all the prerequisite, you need to install a MediaWiki
41 -instance on your machine. If you already have one, it is still
42 -strongly recommended to install one with the script provided. Here's
43 -how to work it:
44 -
45 -a. change directory to contrib/mw-to-git/t/
46 -b. if needed, edit test.config to choose your installation parameters
47 -c. run `./install-wiki.sh install`
48 -d. check on your favourite web browser if your wiki is correctly
49 - installed.
50 -
51 -Remove an existing wiki
52 -~~~~~~~~~~~~~~~~~~~~~~~
53 -
54 -Edit the file test.config to fit the wiki you want to delete, and then
55 -execute the command `./install-wiki.sh delete` from the
56 -contrib/mw-to-git/t directory.
57 -
58 -Run the existing tests
59 -~~~~~~~~~~~~~~~~~~~~~~
60 -
61 -The provided tests are currently in the `contrib/mw-to-git/t` directory.
62 -The files are all the t936[0-9]-*.sh shell scripts.
63 -
64 -a. Run all tests:
65 -To do so, run "make test" from the contrib/mw-to-git/ directory.
66 -
67 -b. Run a specific test:
68 -To run a given test <test_name>, run ./<test_name> from the
69 -contrib/mw-to-git/t directory.
70 -
71 -How to create new tests
72 ------------------------
73 -
74 -Available functions
75 -~~~~~~~~~~~~~~~~~~~
76 -
77 -The test environment of git-remote-mediawiki provides some functions
78 -useful to test its behaviour. for more details about the functions'
79 -parameters, please refer to the `test-gitmw-lib.sh` and
80 -`test-gitmw.pl` files.
81 -
82 -** `test_check_wiki_precond`:
83 -Check if the tests must be skipped or not. Please use this function
84 -at the beginning of each new test file.
85 -
86 -** `wiki_getpage`:
87 -Fetch a given page from the wiki and puts its content in the
88 -directory in parameter.
89 -
90 -** `wiki_delete_page`:
91 -Delete a given page from the wiki.
92 -
93 -** `wiki_edit_page`:
94 -Create or modify a given page in the wiki. You can specify several
95 -parameters like a summary for the page edition, or add the page to a
96 -given category.
97 -See test-gitmw.pl for more details.
98 -
99 -** `wiki_getallpage`:
100 -Fetch all pages from the wiki into a given directory. The directory
101 -is created if it does not exists.
102 -
103 -** `test_diff_directories`:
104 -Compare the content of two directories. The content must be the same.
105 -Use this function to compare the content of a git directory and a wiki
106 -one created by wiki_getallpage.
107 -
108 -** `test_contains_N_files`:
109 -Check if the given directory contains a given number of file.
110 -
111 -** `wiki_page_exists`:
112 -Tests if a given page exists on the wiki.
113 -
114 -** `wiki_reset`:
115 -Reset the wiki, i.e. flush the database. Use this function at the
116 -beginning of each new test, except if the test re-uses the same wiki
117 -(and history) as the previous test.
118 -
119 -How to write a new test
120 -~~~~~~~~~~~~~~~~~~~~~~~
121 -
122 -Please, follow the standards given by git. See git/t/README.
123 -New file should be named as t936[0-9]-*.sh.
124 -Be sure to reset your wiki regularly with the function `wiki_reset`.
contrib/mw-to-git/t/install-wiki.sh deleted
-55
@@ -1,55 +0,0 @@
1 -#!/bin/sh
2 -
3 -# This script installs or deletes a MediaWiki on your computer.
4 -# It requires a web server with PHP and SQLite running. In addition, if you
5 -# do not have MediaWiki sources on your computer, the option 'install'
6 -# downloads them for you.
7 -# Please set the CONFIGURATION VARIABLES in ./test-gitmw-lib.sh
8 -
9 -WIKI_TEST_DIR=$(cd "$(dirname "$0")" && pwd)
10 -
11 -if test -z "$WIKI_TEST_DIR"
12 -then
13 - WIKI_TEST_DIR=.
14 -fi
15 -
16 -. "$WIKI_TEST_DIR"/test-gitmw-lib.sh
17 -usage () {
18 - echo "usage: "
19 - echo " ./install-wiki.sh <install | delete | --help>"
20 - echo " install | -i : Install a wiki on your computer."
21 - echo " delete | -d : Delete the wiki and all its pages and "
22 - echo " content."
23 - echo " start | -s : Start the previously configured lighttpd daemon"
24 - echo " stop : Stop lighttpd daemon."
25 -}
26 -
27 -
28 -# Argument: install, delete, --help | -h
29 -case "$1" in
30 - "install" | "-i")
31 - wiki_install
32 - exit 0
33 - ;;
34 - "delete" | "-d")
35 - wiki_delete
36 - exit 0
37 - ;;
38 - "start" | "-s")
39 - start_lighttpd
40 - exit
41 - ;;
42 - "stop")
43 - stop_lighttpd
44 - exit
45 - ;;
46 - "--help" | "-h")
47 - usage
48 - exit 0
49 - ;;
50 - *)
51 - echo "Invalid argument: $1"
52 - usage
53 - exit 1
54 - ;;
55 -esac
contrib/mw-to-git/t/push-pull-tests.sh deleted
-144
@@ -1,144 +0,0 @@
1 -test_push_pull () {
2 -
3 - test_expect_success 'Git pull works after adding a new wiki page' '
4 - wiki_reset &&
5 -
6 - git clone mediawiki::'"$WIKI_URL"' mw_dir_1 &&
7 - wiki_editpage Foo "page created after the git clone" false &&
8 -
9 - (
10 - cd mw_dir_1 &&
11 - git pull
12 - ) &&
13 -
14 - wiki_getallpage ref_page_1 &&
15 - test_diff_directories mw_dir_1 ref_page_1
16 - '
17 -
18 - test_expect_success 'Git pull works after editing a wiki page' '
19 - wiki_reset &&
20 -
21 - wiki_editpage Foo "page created before the git clone" false &&
22 - git clone mediawiki::'"$WIKI_URL"' mw_dir_2 &&
23 - wiki_editpage Foo "new line added on the wiki" true &&
24 -
25 - (
26 - cd mw_dir_2 &&
27 - git pull
28 - ) &&
29 -
30 - wiki_getallpage ref_page_2 &&
31 - test_diff_directories mw_dir_2 ref_page_2
32 - '
33 -
34 - test_expect_success 'git pull works on conflict handled by auto-merge' '
35 - wiki_reset &&
36 -
37 - wiki_editpage Foo "1 init
38 -3
39 -5
40 - " false &&
41 - git clone mediawiki::'"$WIKI_URL"' mw_dir_3 &&
42 -
43 - wiki_editpage Foo "1 init
44 -2 content added on wiki after clone
45 -3
46 -5
47 - " false &&
48 -
49 - (
50 - cd mw_dir_3 &&
51 - echo "1 init
52 -3
53 -4 content added on git after clone
54 -5
55 -" >Foo.mw &&
56 - git commit -am "conflicting change on foo" &&
57 - git pull &&
58 - git push
59 - )
60 - '
61 -
62 - test_expect_success 'Git push works after adding a file .mw' '
63 - wiki_reset &&
64 - git clone mediawiki::'"$WIKI_URL"' mw_dir_4 &&
65 - wiki_getallpage ref_page_4 &&
66 - (
67 - cd mw_dir_4 &&
68 - test_path_is_missing Foo.mw &&
69 - touch Foo.mw &&
70 - echo "hello world" >>Foo.mw &&
71 - git add Foo.mw &&
72 - git commit -m "Foo" &&
73 - git push
74 - ) &&
75 - wiki_getallpage ref_page_4 &&
76 - test_diff_directories mw_dir_4 ref_page_4
77 - '
78 -
79 - test_expect_success 'Git push works after editing a file .mw' '
80 - wiki_reset &&
81 - wiki_editpage "Foo" "page created before the git clone" false &&
82 - git clone mediawiki::'"$WIKI_URL"' mw_dir_5 &&
83 -
84 - (
85 - cd mw_dir_5 &&
86 - echo "new line added in the file Foo.mw" >>Foo.mw &&
87 - git commit -am "edit file Foo.mw" &&
88 - git push
89 - ) &&
90 -
91 - wiki_getallpage ref_page_5 &&
92 - test_diff_directories mw_dir_5 ref_page_5
93 - '
94 -
95 - test_expect_failure 'Git push works after deleting a file' '
96 - wiki_reset &&
97 - wiki_editpage Foo "wiki page added before git clone" false &&
98 - git clone mediawiki::'"$WIKI_URL"' mw_dir_6 &&
99 -
100 - (
101 - cd mw_dir_6 &&
102 - git rm Foo.mw &&
103 - git commit -am "page Foo.mw deleted" &&
104 - git push
105 - ) &&
106 -
107 - test_must_fail wiki_page_exist Foo
108 - '
109 -
110 - test_expect_success 'Merge conflict expected and solving it' '
111 - wiki_reset &&
112 -
113 - git clone mediawiki::'"$WIKI_URL"' mw_dir_7 &&
114 - wiki_editpage Foo "1 conflict
115 -3 wiki
116 -4" false &&
117 -
118 - (
119 - cd mw_dir_7 &&
120 - echo "1 conflict
121 -2 git
122 -4" >Foo.mw &&
123 - git add Foo.mw &&
124 - git commit -m "conflict created" &&
125 - test_must_fail git pull &&
126 - "$PERL_PATH" -pi -e "s/[<=>].*//g" Foo.mw &&
127 - git commit -am "merge conflict solved" &&
128 - git push
129 - )
130 - '
131 -
132 - test_expect_failure 'git pull works after deleting a wiki page' '
133 - wiki_reset &&
134 - wiki_editpage Foo "wiki page added before the git clone" false &&
135 - git clone mediawiki::'"$WIKI_URL"' mw_dir_8 &&
136 -
137 - wiki_delete_page Foo &&
138 - (
139 - cd mw_dir_8 &&
140 - git pull &&
141 - test_path_is_missing Foo.mw
142 - )
143 - '
144 -}
contrib/mw-to-git/t/t9360-mw-to-git-clone.sh deleted
-257
@@ -1,257 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (C) 2012
4 -# Charles Roussel <charles.roussel@ensimag.imag.fr>
5 -# Simon Cathebras <simon.cathebras@ensimag.imag.fr>
6 -# Julien Khayat <julien.khayat@ensimag.imag.fr>
7 -# Guillaume Sasdy <guillaume.sasdy@ensimag.imag.fr>
8 -# Simon Perrat <simon.perrat@ensimag.imag.fr>
9 -#
10 -# License: GPL v2 or later
11 -
12 -
13 -test_description='Test the Git Mediawiki remote helper: git clone'
14 -
15 -. ./test-gitmw-lib.sh
16 -. $TEST_DIRECTORY/test-lib.sh
17 -
18 -
19 -test_check_precond
20 -
21 -
22 -test_expect_success 'Git clone creates the expected git log with one file' '
23 - wiki_reset &&
24 - wiki_editpage foo "this is not important" false -c cat -s "this must be the same" &&
25 - git clone mediawiki::'"$WIKI_URL"' mw_dir_1 &&
26 - (
27 - cd mw_dir_1 &&
28 - git log --format=%s HEAD^..HEAD >log.tmp
29 - ) &&
30 - echo "this must be the same" >msg.tmp &&
31 - test_cmp msg.tmp mw_dir_1/log.tmp
32 -'
33 -
34 -
35 -test_expect_success 'Git clone creates the expected git log with multiple files' '
36 - wiki_reset &&
37 - wiki_editpage daddy "this is not important" false -s="this must be the same" &&
38 - wiki_editpage daddy "neither is this" true -s="this must also be the same" &&
39 - wiki_editpage daddy "neither is this" true -s="same same same" &&
40 - wiki_editpage dj "dont care" false -s="identical" &&
41 - wiki_editpage dj "dont care either" true -s="identical too" &&
42 - git clone mediawiki::'"$WIKI_URL"' mw_dir_2 &&
43 - (
44 - cd mw_dir_2 &&
45 - git log --format=%s Daddy.mw >logDaddy.tmp &&
46 - git log --format=%s Dj.mw >logDj.tmp
47 - ) &&
48 - echo "same same same" >msgDaddy.tmp &&
49 - echo "this must also be the same" >>msgDaddy.tmp &&
50 - echo "this must be the same" >>msgDaddy.tmp &&
51 - echo "identical too" >msgDj.tmp &&
52 - echo "identical" >>msgDj.tmp &&
53 - test_cmp msgDaddy.tmp mw_dir_2/logDaddy.tmp &&
54 - test_cmp msgDj.tmp mw_dir_2/logDj.tmp
55 -'
56 -
57 -
58 -test_expect_success 'Git clone creates only Main_Page.mw with an empty wiki' '
59 - wiki_reset &&
60 - git clone mediawiki::'"$WIKI_URL"' mw_dir_3 &&
61 - test_contains_N_files mw_dir_3 1 &&
62 - test_path_is_file mw_dir_3/Main_Page.mw
63 -'
64 -
65 -test_expect_success 'Git clone does not fetch a deleted page' '
66 - wiki_reset &&
67 - wiki_editpage foo "this page must be deleted before the clone" false &&
68 - wiki_delete_page foo &&
69 - git clone mediawiki::'"$WIKI_URL"' mw_dir_4 &&
70 - test_contains_N_files mw_dir_4 1 &&
71 - test_path_is_file mw_dir_4/Main_Page.mw &&
72 - test_path_is_missing mw_dir_4/Foo.mw
73 -'
74 -
75 -test_expect_success 'Git clone works with page added' '
76 - wiki_reset &&
77 - wiki_editpage foo " I will be cloned" false &&
78 - wiki_editpage bar "I will be cloned" false &&
79 - git clone mediawiki::'"$WIKI_URL"' mw_dir_5 &&
80 - wiki_getallpage ref_page_5 &&
81 - test_diff_directories mw_dir_5 ref_page_5 &&
82 - wiki_delete_page foo &&
83 - wiki_delete_page bar
84 -'
85 -
86 -test_expect_success 'Git clone works with an edited page ' '
87 - wiki_reset &&
88 - wiki_editpage foo "this page will be edited" \
89 - false -s "first edition of page foo" &&
90 - wiki_editpage foo "this page has been edited and must be on the clone " true &&
91 - git clone mediawiki::'"$WIKI_URL"' mw_dir_6 &&
92 - test_path_is_file mw_dir_6/Foo.mw &&
93 - test_path_is_file mw_dir_6/Main_Page.mw &&
94 - wiki_getallpage mw_dir_6/page_ref_6 &&
95 - test_diff_directories mw_dir_6 mw_dir_6/page_ref_6 &&
96 - (
97 - cd mw_dir_6 &&
98 - git log --format=%s HEAD^ Foo.mw > ../Foo.log
99 - ) &&
100 - echo "first edition of page foo" > FooExpect.log &&
101 - diff FooExpect.log Foo.log
102 -'
103 -
104 -
105 -test_expect_success 'Git clone works with several pages and some deleted ' '
106 - wiki_reset &&
107 - wiki_editpage foo "this page will not be deleted" false &&
108 - wiki_editpage bar "I must not be erased" false &&
109 - wiki_editpage namnam "I will not be there at the end" false &&
110 - wiki_editpage nyancat "nyan nyan nyan delete me" false &&
111 - wiki_delete_page namnam &&
112 - wiki_delete_page nyancat &&
113 - git clone mediawiki::'"$WIKI_URL"' mw_dir_7 &&
114 - test_path_is_file mw_dir_7/Foo.mw &&
115 - test_path_is_file mw_dir_7/Bar.mw &&
116 - test_path_is_missing mw_dir_7/Namnam.mw &&
117 - test_path_is_missing mw_dir_7/Nyancat.mw &&
118 - wiki_getallpage mw_dir_7/page_ref_7 &&
119 - test_diff_directories mw_dir_7 mw_dir_7/page_ref_7
120 -'
121 -
122 -
123 -test_expect_success 'Git clone works with one specific page cloned ' '
124 - wiki_reset &&
125 - wiki_editpage foo "I will not be cloned" false &&
126 - wiki_editpage bar "Do not clone me" false &&
127 - wiki_editpage namnam "I will be cloned :)" false -s="this log must stay" &&
128 - wiki_editpage nyancat "nyan nyan nyan you cant clone me" false &&
129 - git clone -c remote.origin.pages=namnam \
130 - mediawiki::'"$WIKI_URL"' mw_dir_8 &&
131 - test_contains_N_files mw_dir_8 1 &&
132 - test_path_is_file mw_dir_8/Namnam.mw &&
133 - test_path_is_missing mw_dir_8/Main_Page.mw &&
134 - (
135 - cd mw_dir_8 &&
136 - echo "this log must stay" >msg.tmp &&
137 - git log --format=%s >log.tmp &&
138 - test_cmp msg.tmp log.tmp
139 - ) &&
140 - wiki_check_content mw_dir_8/Namnam.mw Namnam
141 -'
142 -
143 -test_expect_success 'Git clone works with multiple specific page cloned ' '
144 - wiki_reset &&
145 - wiki_editpage foo "I will be there" false &&
146 - wiki_editpage bar "I will not disappear" false &&
147 - wiki_editpage namnam "I be erased" false &&
148 - wiki_editpage nyancat "nyan nyan nyan you will not erase me" false &&
149 - wiki_delete_page namnam &&
150 - git clone -c remote.origin.pages="foo bar nyancat namnam" \
151 - mediawiki::'"$WIKI_URL"' mw_dir_9 &&
152 - test_contains_N_files mw_dir_9 3 &&
153 - test_path_is_missing mw_dir_9/Namnam.mw &&
154 - test_path_is_file mw_dir_9/Foo.mw &&
155 - test_path_is_file mw_dir_9/Nyancat.mw &&
156 - test_path_is_file mw_dir_9/Bar.mw &&
157 - wiki_check_content mw_dir_9/Foo.mw Foo &&
158 - wiki_check_content mw_dir_9/Bar.mw Bar &&
159 - wiki_check_content mw_dir_9/Nyancat.mw Nyancat
160 -'
161 -
162 -test_expect_success 'Mediawiki-clone of several specific pages on wiki' '
163 - wiki_reset &&
164 - wiki_editpage foo "foo 1" false &&
165 - wiki_editpage bar "bar 1" false &&
166 - wiki_editpage dummy "dummy 1" false &&
167 - wiki_editpage cloned_1 "cloned_1 1" false &&
168 - wiki_editpage cloned_2 "cloned_2 2" false &&
169 - wiki_editpage cloned_3 "cloned_3 3" false &&
170 - mkdir -p ref_page_10 &&
171 - wiki_getpage cloned_1 ref_page_10 &&
172 - wiki_getpage cloned_2 ref_page_10 &&
173 - wiki_getpage cloned_3 ref_page_10 &&
174 - git clone -c remote.origin.pages="cloned_1 cloned_2 cloned_3" \
175 - mediawiki::'"$WIKI_URL"' mw_dir_10 &&
176 - test_diff_directories mw_dir_10 ref_page_10
177 -'
178 -
179 -test_expect_success 'Git clone works with the shallow option' '
180 - wiki_reset &&
181 - wiki_editpage foo "1st revision, should be cloned" false &&
182 - wiki_editpage bar "1st revision, should be cloned" false &&
183 - wiki_editpage nyan "1st revision, should not be cloned" false &&
184 - wiki_editpage nyan "2nd revision, should be cloned" false &&
185 - git -c remote.origin.shallow=true clone \
186 - mediawiki::'"$WIKI_URL"' mw_dir_11 &&
187 - test_contains_N_files mw_dir_11 4 &&
188 - test_path_is_file mw_dir_11/Nyan.mw &&
189 - test_path_is_file mw_dir_11/Foo.mw &&
190 - test_path_is_file mw_dir_11/Bar.mw &&
191 - test_path_is_file mw_dir_11/Main_Page.mw &&
192 - (
193 - cd mw_dir_11 &&
194 - test $(git log --oneline Nyan.mw | wc -l) -eq 1 &&
195 - test $(git log --oneline Foo.mw | wc -l) -eq 1 &&
196 - test $(git log --oneline Bar.mw | wc -l) -eq 1 &&
197 - test $(git log --oneline Main_Page.mw | wc -l ) -eq 1
198 - ) &&
199 - wiki_check_content mw_dir_11/Nyan.mw Nyan &&
200 - wiki_check_content mw_dir_11/Foo.mw Foo &&
201 - wiki_check_content mw_dir_11/Bar.mw Bar &&
202 - wiki_check_content mw_dir_11/Main_Page.mw Main_Page
203 -'
204 -
205 -test_expect_success 'Git clone works with the shallow option with a delete page' '
206 - wiki_reset &&
207 - wiki_editpage foo "1st revision, will be deleted" false &&
208 - wiki_editpage bar "1st revision, should be cloned" false &&
209 - wiki_editpage nyan "1st revision, should not be cloned" false &&
210 - wiki_editpage nyan "2nd revision, should be cloned" false &&
211 - wiki_delete_page foo &&
212 - git -c remote.origin.shallow=true clone \
213 - mediawiki::'"$WIKI_URL"' mw_dir_12 &&
214 - test_contains_N_files mw_dir_12 3 &&
215 - test_path_is_file mw_dir_12/Nyan.mw &&
216 - test_path_is_missing mw_dir_12/Foo.mw &&
217 - test_path_is_file mw_dir_12/Bar.mw &&
218 - test_path_is_file mw_dir_12/Main_Page.mw &&
219 - (
220 - cd mw_dir_12 &&
221 - test $(git log --oneline Nyan.mw | wc -l) -eq 1 &&
222 - test $(git log --oneline Bar.mw | wc -l) -eq 1 &&
223 - test $(git log --oneline Main_Page.mw | wc -l ) -eq 1
224 - ) &&
225 - wiki_check_content mw_dir_12/Nyan.mw Nyan &&
226 - wiki_check_content mw_dir_12/Bar.mw Bar &&
227 - wiki_check_content mw_dir_12/Main_Page.mw Main_Page
228 -'
229 -
230 -test_expect_success 'Test of fetching a category' '
231 - wiki_reset &&
232 - wiki_editpage Foo "I will be cloned" false -c=Category &&
233 - wiki_editpage Bar "Meet me on the repository" false -c=Category &&
234 - wiki_editpage Dummy "I will not come" false &&
235 - wiki_editpage BarWrong "I will stay online only" false -c=NotCategory &&
236 - git clone -c remote.origin.categories="Category" \
237 - mediawiki::'"$WIKI_URL"' mw_dir_13 &&
238 - wiki_getallpage ref_page_13 Category &&
239 - test_diff_directories mw_dir_13 ref_page_13
240 -'
241 -
242 -test_expect_success 'Test of resistance to modification of category on wiki for clone' '
243 - wiki_reset &&
244 - wiki_editpage Tobedeleted "this page will be deleted" false -c=Catone &&
245 - wiki_editpage Tobeedited "this page will be modified" false -c=Catone &&
246 - wiki_editpage Normalone "this page wont be modified and will be on git" false -c=Catone &&
247 - wiki_editpage Notconsidered "this page will not appear on local" false &&
248 - wiki_editpage Othercategory "this page will not appear on local" false -c=Cattwo &&
249 - wiki_editpage Tobeedited "this page have been modified" true -c=Catone &&
250 - wiki_delete_page Tobedeleted &&
251 - git clone -c remote.origin.categories="Catone" \
252 - mediawiki::'"$WIKI_URL"' mw_dir_14 &&
253 - wiki_getallpage ref_page_14 Catone &&
254 - test_diff_directories mw_dir_14 ref_page_14
255 -'
256 -
257 -test_done
contrib/mw-to-git/t/t9361-mw-to-git-push-pull.sh deleted
-24
@@ -1,24 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (C) 2012
4 -# Charles Roussel <charles.roussel@ensimag.imag.fr>
5 -# Simon Cathebras <simon.cathebras@ensimag.imag.fr>
6 -# Julien Khayat <julien.khayat@ensimag.imag.fr>
7 -# Guillaume Sasdy <guillaume.sasdy@ensimag.imag.fr>
8 -# Simon Perrat <simon.perrat@ensimag.imag.fr>
9 -#
10 -# License: GPL v2 or later
11 -
12 -# tests for git-remote-mediawiki
13 -
14 -test_description='Test the Git Mediawiki remote helper: git push and git pull simple test cases'
15 -
16 -. ./test-gitmw-lib.sh
17 -. ./push-pull-tests.sh
18 -. $TEST_DIRECTORY/test-lib.sh
19 -
20 -test_check_precond
21 -
22 -test_push_pull
23 -
24 -test_done
contrib/mw-to-git/t/t9362-mw-to-git-utf8.sh deleted
-347
@@ -1,347 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (C) 2012
4 -# Charles Roussel <charles.roussel@ensimag.imag.fr>
5 -# Simon Cathebras <simon.cathebras@ensimag.imag.fr>
6 -# Julien Khayat <julien.khayat@ensimag.imag.fr>
7 -# Guillaume Sasdy <guillaume.sasdy@ensimag.imag.fr>
8 -# Simon Perrat <simon.perrat@ensimag.imag.fr>
9 -#
10 -# License: GPL v2 or later
11 -
12 -# tests for git-remote-mediawiki
13 -
14 -test_description='Test git-mediawiki with special characters in filenames'
15 -
16 -. ./test-gitmw-lib.sh
17 -. $TEST_DIRECTORY/test-lib.sh
18 -
19 -
20 -test_check_precond
21 -
22 -
23 -test_expect_success 'Git clone works for a wiki with accents in the page names' '
24 - wiki_reset &&
25 - wiki_editpage féé "This page must be délétéd before clone" false &&
26 - wiki_editpage kèè "This page must be deleted before clone" false &&
27 - wiki_editpage hàà "This page must be deleted before clone" false &&
28 - wiki_editpage kîî "This page must be deleted before clone" false &&
29 - wiki_editpage foo "This page must be deleted before clone" false &&
30 - git clone mediawiki::'"$WIKI_URL"' mw_dir_1 &&
31 - wiki_getallpage ref_page_1 &&
32 - test_diff_directories mw_dir_1 ref_page_1
33 -'
34 -
35 -
36 -test_expect_success 'Git pull works with a wiki with accents in the pages names' '
37 - wiki_reset &&
38 - wiki_editpage kîî "this page must be cloned" false &&
39 - wiki_editpage foo "this page must be cloned" false &&
40 - git clone mediawiki::'"$WIKI_URL"' mw_dir_2 &&
41 - wiki_editpage éàîôû "This page must be pulled" false &&
42 - (
43 - cd mw_dir_2 &&
44 - git pull
45 - ) &&
46 - wiki_getallpage ref_page_2 &&
47 - test_diff_directories mw_dir_2 ref_page_2
48 -'
49 -
50 -
51 -test_expect_success 'Cloning a chosen page works with accents' '
52 - wiki_reset &&
53 - wiki_editpage kîî "this page must be cloned" false &&
54 - git clone -c remote.origin.pages=kîî \
55 - mediawiki::'"$WIKI_URL"' mw_dir_3 &&
56 - wiki_check_content mw_dir_3/Kîî.mw Kîî &&
57 - test_path_is_file mw_dir_3/Kîî.mw &&
58 - rm -rf mw_dir_3
59 -'
60 -
61 -
62 -test_expect_success 'The shallow option works with accents' '
63 - wiki_reset &&
64 - wiki_editpage néoà "1st revision, should not be cloned" false &&
65 - wiki_editpage néoà "2nd revision, should be cloned" false &&
66 - git -c remote.origin.shallow=true clone \
67 - mediawiki::'"$WIKI_URL"' mw_dir_4 &&
68 - test_contains_N_files mw_dir_4 2 &&
69 - test_path_is_file mw_dir_4/Néoà.mw &&
70 - test_path_is_file mw_dir_4/Main_Page.mw &&
71 - (
72 - cd mw_dir_4 &&
73 - test $(git log --oneline Néoà.mw | wc -l) -eq 1 &&
74 - test $(git log --oneline Main_Page.mw | wc -l ) -eq 1
75 - ) &&
76 - wiki_check_content mw_dir_4/Néoà.mw Néoà &&
77 - wiki_check_content mw_dir_4/Main_Page.mw Main_Page
78 -'
79 -
80 -
81 -test_expect_success 'Cloning works when page name first letter has an accent' '
82 - wiki_reset &&
83 - wiki_editpage îî "this page must be cloned" false &&
84 - git clone -c remote.origin.pages=îî \
85 - mediawiki::'"$WIKI_URL"' mw_dir_5 &&
86 - test_path_is_file mw_dir_5/Îî.mw &&
87 - wiki_check_content mw_dir_5/Îî.mw Îî
88 -'
89 -
90 -
91 -test_expect_success 'Git push works with a wiki with accents' '
92 - wiki_reset &&
93 - wiki_editpage féé "lots of accents : éèàÖ" false &&
94 - wiki_editpage foo "this page must be cloned" false &&
95 - git clone mediawiki::'"$WIKI_URL"' mw_dir_6 &&
96 - (
97 - cd mw_dir_6 &&
98 - echo "A wild Pîkächû appears on the wiki" >Pîkächû.mw &&
99 - git add Pîkächû.mw &&
100 - git commit -m "A new page appears" &&
101 - git push
102 - ) &&
103 - wiki_getallpage ref_page_6 &&
104 - test_diff_directories mw_dir_6 ref_page_6
105 -'
106 -
107 -test_expect_success 'Git clone works with accentsand spaces' '
108 - wiki_reset &&
109 - wiki_editpage "é à î" "this page must be délété before the clone" false &&
110 - git clone mediawiki::'"$WIKI_URL"' mw_dir_7 &&
111 - wiki_getallpage ref_page_7 &&
112 - test_diff_directories mw_dir_7 ref_page_7
113 -'
114 -
115 -test_expect_success 'character $ in page name (mw -> git)' '
116 - wiki_reset &&
117 - wiki_editpage file_\$_foo "expect to be called file_$_foo" false &&
118 - git clone mediawiki::'"$WIKI_URL"' mw_dir_8 &&
119 - test_path_is_file mw_dir_8/File_\$_foo.mw &&
120 - wiki_getallpage ref_page_8 &&
121 - test_diff_directories mw_dir_8 ref_page_8
122 -'
123 -
124 -
125 -
126 -test_expect_success 'character $ in file name (git -> mw) ' '
127 - wiki_reset &&
128 - git clone mediawiki::'"$WIKI_URL"' mw_dir_9 &&
129 - (
130 - cd mw_dir_9 &&
131 - echo "this file is called File_\$_foo.mw" >File_\$_foo.mw &&
132 - git add . &&
133 - git commit -am "file File_\$_foo.mw" &&
134 - git pull &&
135 - git push
136 - ) &&
137 - wiki_getallpage ref_page_9 &&
138 - test_diff_directories mw_dir_9 ref_page_9
139 -'
140 -
141 -
142 -test_expect_failure 'capital at the beginning of file names' '
143 - wiki_reset &&
144 - git clone mediawiki::'"$WIKI_URL"' mw_dir_10 &&
145 - (
146 - cd mw_dir_10 &&
147 - echo "my new file foo" >foo.mw &&
148 - echo "my new file Foo... Finger crossed" >Foo.mw &&
149 - git add . &&
150 - git commit -am "file foo.mw" &&
151 - git pull &&
152 - git push
153 - ) &&
154 - wiki_getallpage ref_page_10 &&
155 - test_diff_directories mw_dir_10 ref_page_10
156 -'
157 -
158 -
159 -test_expect_failure 'special character at the beginning of file name from mw to git' '
160 - wiki_reset &&
161 - git clone mediawiki::'"$WIKI_URL"' mw_dir_11 &&
162 - wiki_editpage {char_1 "expect to be renamed {char_1" false &&
163 - wiki_editpage [char_2 "expect to be renamed [char_2" false &&
164 - (
165 - cd mw_dir_11 &&
166 - git pull
167 - ) &&
168 - test_path_is_file mw_dir_11/{char_1 &&
169 - test_path_is_file mw_dir_11/[char_2
170 -'
171 -
172 -test_expect_success 'Pull page with title containing ":" other than namespace separator' '
173 - wiki_editpage Foo:Bar content false &&
174 - (
175 - cd mw_dir_11 &&
176 - git pull
177 - ) &&
178 - test_path_is_file mw_dir_11/Foo:Bar.mw
179 -'
180 -
181 -test_expect_success 'Push page with title containing ":" other than namespace separator' '
182 - (
183 - cd mw_dir_11 &&
184 - echo content >NotANameSpace:Page.mw &&
185 - git add NotANameSpace:Page.mw &&
186 - git commit -m "add page with colon" &&
187 - git push
188 - ) &&
189 - wiki_page_exist NotANameSpace:Page
190 -'
191 -
192 -test_expect_success 'test of correct formatting for file name from mw to git' '
193 - wiki_reset &&
194 - git clone mediawiki::'"$WIKI_URL"' mw_dir_12 &&
195 - wiki_editpage char_%_7b_1 "expect to be renamed char{_1" false &&
196 - wiki_editpage char_%_5b_2 "expect to be renamed char{_2" false &&
197 - (
198 - cd mw_dir_12 &&
199 - git pull
200 - ) &&
201 - test_path_is_file mw_dir_12/Char\{_1.mw &&
202 - test_path_is_file mw_dir_12/Char\[_2.mw &&
203 - wiki_getallpage ref_page_12 &&
204 - mv ref_page_12/Char_%_7b_1.mw ref_page_12/Char\{_1.mw &&
205 - mv ref_page_12/Char_%_5b_2.mw ref_page_12/Char\[_2.mw &&
206 - test_diff_directories mw_dir_12 ref_page_12
207 -'
208 -
209 -
210 -test_expect_failure 'test of correct formatting for file name beginning with special character' '
211 - wiki_reset &&
212 - git clone mediawiki::'"$WIKI_URL"' mw_dir_13 &&
213 - (
214 - cd mw_dir_13 &&
215 - echo "my new file {char_1" >\{char_1.mw &&
216 - echo "my new file [char_2" >\[char_2.mw &&
217 - git add . &&
218 - git commit -am "committing some exotic file name..." &&
219 - git push &&
220 - git pull
221 - ) &&
222 - wiki_getallpage ref_page_13 &&
223 - test_path_is_file ref_page_13/{char_1.mw &&
224 - test_path_is_file ref_page_13/[char_2.mw &&
225 - test_diff_directories mw_dir_13 ref_page_13
226 -'
227 -
228 -
229 -test_expect_success 'test of correct formatting for file name from git to mw' '
230 - wiki_reset &&
231 - git clone mediawiki::'"$WIKI_URL"' mw_dir_14 &&
232 - (
233 - cd mw_dir_14 &&
234 - echo "my new file char{_1" >Char\{_1.mw &&
235 - echo "my new file char[_2" >Char\[_2.mw &&
236 - git add . &&
237 - git commit -m "committing some exotic file name..." &&
238 - git push
239 - ) &&
240 - wiki_getallpage ref_page_14 &&
241 - mv mw_dir_14/Char\{_1.mw mw_dir_14/Char_%_7b_1.mw &&
242 - mv mw_dir_14/Char\[_2.mw mw_dir_14/Char_%_5b_2.mw &&
243 - test_diff_directories mw_dir_14 ref_page_14
244 -'
245 -
246 -
247 -test_expect_success 'git clone with /' '
248 - wiki_reset &&
249 - wiki_editpage \/fo\/o "this is not important" false -c=Deleted &&
250 - git clone mediawiki::'"$WIKI_URL"' mw_dir_15 &&
251 - test_path_is_file mw_dir_15/%2Ffo%2Fo.mw &&
252 - wiki_check_content mw_dir_15/%2Ffo%2Fo.mw \/fo\/o
253 -'
254 -
255 -
256 -test_expect_success 'git push with /' '
257 - wiki_reset &&
258 - git clone mediawiki::'"$WIKI_URL"' mw_dir_16 &&
259 - echo "I will be on the wiki" >mw_dir_16/%2Ffo%2Fo.mw &&
260 - (
261 - cd mw_dir_16 &&
262 - git add %2Ffo%2Fo.mw &&
263 - git commit -m " %2Ffo%2Fo added" &&
264 - git push
265 - ) &&
266 - wiki_page_exist \/fo\/o &&
267 - wiki_check_content mw_dir_16/%2Ffo%2Fo.mw \/fo\/o
268 -
269 -'
270 -
271 -
272 -test_expect_success 'git clone with \' '
273 - wiki_reset &&
274 - wiki_editpage \\ko\\o "this is not important" false -c=Deleted &&
275 - git clone mediawiki::'"$WIKI_URL"' mw_dir_17 &&
276 - test_path_is_file mw_dir_17/\\ko\\o.mw &&
277 - wiki_check_content mw_dir_17/\\ko\\o.mw \\ko\\o
278 -'
279 -
280 -
281 -test_expect_success 'git push with \' '
282 - wiki_reset &&
283 - git clone mediawiki::'"$WIKI_URL"' mw_dir_18 &&
284 - echo "I will be on the wiki" >mw_dir_18/\\ko\\o.mw &&
285 - (
286 - cd mw_dir_18 &&
287 - git add \\ko\\o.mw &&
288 - git commit -m " \\ko\\o added" &&
289 - git push
290 - ) &&
291 - wiki_page_exist \\ko\\o &&
292 - wiki_check_content mw_dir_18/\\ko\\o.mw \\ko\\o
293 -
294 -'
295 -
296 -test_expect_success 'git clone with \ in format control' '
297 - wiki_reset &&
298 - wiki_editpage \\no\\o "this is not important" false &&
299 - git clone mediawiki::'"$WIKI_URL"' mw_dir_19 &&
300 - test_path_is_file mw_dir_19/\\no\\o.mw &&
301 - wiki_check_content mw_dir_19/\\no\\o.mw \\no\\o
302 -'
303 -
304 -
305 -test_expect_success 'git push with \ in format control' '
306 - wiki_reset &&
307 - git clone mediawiki::'"$WIKI_URL"' mw_dir_20 &&
308 - echo "I will be on the wiki" >mw_dir_20/\\fo\\o.mw &&
309 - (
310 - cd mw_dir_20 &&
311 - git add \\fo\\o.mw &&
312 - git commit -m " \\fo\\o added" &&
313 - git push
314 - ) &&
315 - wiki_page_exist \\fo\\o &&
316 - wiki_check_content mw_dir_20/\\fo\\o.mw \\fo\\o
317 -
318 -'
319 -
320 -
321 -test_expect_success 'fast-import meta-characters in page name (mw -> git)' '
322 - wiki_reset &&
323 - wiki_editpage \"file\"_\\_foo "expect to be called \"file\"_\\_foo" false &&
324 - git clone mediawiki::'"$WIKI_URL"' mw_dir_21 &&
325 - test_path_is_file mw_dir_21/\"file\"_\\_foo.mw &&
326 - wiki_getallpage ref_page_21 &&
327 - test_diff_directories mw_dir_21 ref_page_21
328 -'
329 -
330 -
331 -test_expect_success 'fast-import meta-characters in page name (git -> mw) ' '
332 - wiki_reset &&
333 - git clone mediawiki::'"$WIKI_URL"' mw_dir_22 &&
334 - (
335 - cd mw_dir_22 &&
336 - echo "this file is called \"file\"_\\_foo.mw" >\"file\"_\\_foo &&
337 - git add . &&
338 - git commit -am "file \"file\"_\\_foo" &&
339 - git pull &&
340 - git push
341 - ) &&
342 - wiki_getallpage ref_page_22 &&
343 - test_diff_directories mw_dir_22 ref_page_22
344 -'
345 -
346 -
347 -test_done
contrib/mw-to-git/t/t9363-mw-to-git-export-import.sh deleted
-218
@@ -1,218 +0,0 @@
1 -#!/bin/sh
2 -#
3 -# Copyright (C) 2012
4 -# Charles Roussel <charles.roussel@ensimag.imag.fr>
5 -# Simon Cathebras <simon.cathebras@ensimag.imag.fr>
6 -# Julien Khayat <julien.khayat@ensimag.imag.fr>
7 -# Guillaume Sasdy <guillaume.sasdy@ensimag.imag.fr>
8 -# Simon Perrat <simon.perrat@ensimag.imag.fr>
9 -#
10 -# License: GPL v2 or later
11 -
12 -# tests for git-remote-mediawiki
13 -
14 -test_description='Test the Git Mediawiki remote helper: git push and git pull simple test cases'
15 -
16 -. ./test-gitmw-lib.sh
17 -. $TEST_DIRECTORY/test-lib.sh
18 -
19 -
20 -test_check_precond
21 -
22 -
23 -test_git_reimport () {
24 - git -c remote.origin.dumbPush=true push &&
25 - git -c remote.origin.mediaImport=true pull --rebase
26 -}
27 -
28 -# Don't bother with permissions, be administrator by default
29 -test_expect_success 'setup config' '
30 - git config --global remote.origin.mwLogin "$WIKI_ADMIN" &&
31 - git config --global remote.origin.mwPassword "$WIKI_PASSW" &&
32 - test_might_fail git config --global --unset remote.origin.mediaImport
33 -'
34 -
35 -test_expect_failure 'git push can upload media (File:) files' '
36 - wiki_reset &&
37 - git clone mediawiki::'"$WIKI_URL"' mw_dir &&
38 - (
39 - cd mw_dir &&
40 - echo "hello world" >Foo.txt &&
41 - git add Foo.txt &&
42 - git commit -m "add a text file" &&
43 - git push &&
44 - "$PERL_PATH" -e "print STDOUT \"binary content: \".chr(255);" >Foo.txt &&
45 - git add Foo.txt &&
46 - git commit -m "add a text file with binary content" &&
47 - git push
48 - )
49 -'
50 -
51 -test_expect_failure 'git clone works on previously created wiki with media files' '
52 - test_when_finished "rm -rf mw_dir mw_dir_clone" &&
53 - git clone -c remote.origin.mediaimport=true \
54 - mediawiki::'"$WIKI_URL"' mw_dir_clone &&
55 - test_cmp mw_dir_clone/Foo.txt mw_dir/Foo.txt &&
56 - (cd mw_dir_clone && git checkout HEAD^) &&
57 - (cd mw_dir && git checkout HEAD^) &&
58 - test_path_is_file mw_dir_clone/Foo.txt &&
59 - test_cmp mw_dir_clone/Foo.txt mw_dir/Foo.txt
60 -'
61 -
62 -test_expect_success 'git push can upload media (File:) files containing valid UTF-8' '
63 - wiki_reset &&
64 - git clone mediawiki::'"$WIKI_URL"' mw_dir &&
65 - (
66 - cd mw_dir &&
67 - "$PERL_PATH" -e "print STDOUT \"UTF-8 content: éèàéê€.\";" >Bar.txt &&
68 - git add Bar.txt &&
69 - git commit -m "add a text file with UTF-8 content" &&
70 - git push
71 - )
72 -'
73 -
74 -test_expect_success 'git clone works on previously created wiki with media files containing valid UTF-8' '
75 - test_when_finished "rm -rf mw_dir mw_dir_clone" &&
76 - git clone -c remote.origin.mediaimport=true \
77 - mediawiki::'"$WIKI_URL"' mw_dir_clone &&
78 - test_cmp mw_dir_clone/Bar.txt mw_dir/Bar.txt
79 -'
80 -
81 -test_expect_success 'git push & pull work with locally renamed media files' '
82 - wiki_reset &&
83 - git clone mediawiki::'"$WIKI_URL"' mw_dir &&
84 - test_when_finished "rm -fr mw_dir" &&
85 - (
86 - cd mw_dir &&
87 - echo "A File" >Foo.txt &&
88 - git add Foo.txt &&
89 - git commit -m "add a file" &&
90 - git mv Foo.txt Bar.txt &&
91 - git commit -m "Rename a file" &&
92 - test_git_reimport &&
93 - echo "A File" >expect &&
94 - test_cmp expect Bar.txt &&
95 - test_path_is_missing Foo.txt
96 - )
97 -'
98 -
99 -test_expect_success 'git push can propagate local page deletion' '
100 - wiki_reset &&
101 - git clone mediawiki::'"$WIKI_URL"' mw_dir &&
102 - test_when_finished "rm -fr mw_dir" &&
103 - (
104 - cd mw_dir &&
105 - test_path_is_missing Foo.mw &&
106 - echo "hello world" >Foo.mw &&
107 - git add Foo.mw &&
108 - git commit -m "Add the page Foo" &&
109 - git push &&
110 - rm -f Foo.mw &&
111 - git commit -am "Delete the page Foo" &&
112 - test_git_reimport &&
113 - test_path_is_missing Foo.mw
114 - )
115 -'
116 -
117 -test_expect_success 'git push can propagate local media file deletion' '
118 - wiki_reset &&
119 - git clone mediawiki::'"$WIKI_URL"' mw_dir &&
120 - test_when_finished "rm -fr mw_dir" &&
121 - (
122 - cd mw_dir &&
123 - echo "hello world" >Foo.txt &&
124 - git add Foo.txt &&
125 - git commit -m "Add the text file Foo" &&
126 - git rm Foo.txt &&
127 - git commit -m "Delete the file Foo" &&
128 - test_git_reimport &&
129 - test_path_is_missing Foo.txt
130 - )
131 -'
132 -
133 -# test failure: the file is correctly uploaded, and then deleted but
134 -# as no page link to it, the import (which looks at page revisions)
135 -# doesn't notice the file deletion on the wiki. We fetch the list of
136 -# files from the wiki, but as the file is deleted, it doesn't appear.
137 -test_expect_failure 'git pull correctly imports media file deletion when no page link to it' '
138 - wiki_reset &&
139 - git clone mediawiki::'"$WIKI_URL"' mw_dir &&
140 - test_when_finished "rm -fr mw_dir" &&
141 - (
142 - cd mw_dir &&
143 - echo "hello world" >Foo.txt &&
144 - git add Foo.txt &&
145 - git commit -m "Add the text file Foo" &&
146 - git push &&
147 - git rm Foo.txt &&
148 - git commit -m "Delete the file Foo" &&
149 - test_git_reimport &&
150 - test_path_is_missing Foo.txt
151 - )
152 -'
153 -
154 -test_expect_success 'git push properly warns about insufficient permissions' '
155 - wiki_reset &&
156 - git clone mediawiki::'"$WIKI_URL"' mw_dir &&
157 - test_when_finished "rm -fr mw_dir" &&
158 - (
159 - cd mw_dir &&
160 - echo "A File" >foo.forbidden &&
161 - git add foo.forbidden &&
162 - git commit -m "add a file" &&
163 - git push 2>actual &&
164 - test_grep "foo.forbidden is not a permitted file" actual
165 - )
166 -'
167 -
168 -test_expect_success 'setup a repository with media files' '
169 - wiki_reset &&
170 - wiki_editpage testpage "I am linking a file [[File:File.txt]]" false &&
171 - echo "File content" >File.txt &&
172 - wiki_upload_file File.txt &&
173 - echo "Another file content" >AnotherFile.txt &&
174 - wiki_upload_file AnotherFile.txt
175 -'
176 -
177 -test_expect_success 'git clone works with one specific page cloned and mediaimport=true' '
178 - git clone -c remote.origin.pages=testpage \
179 - -c remote.origin.mediaimport=true \
180 - mediawiki::'"$WIKI_URL"' mw_dir_15 &&
181 - test_when_finished "rm -rf mw_dir_15" &&
182 - test_contains_N_files mw_dir_15 3 &&
183 - test_path_is_file mw_dir_15/Testpage.mw &&
184 - test_path_is_file mw_dir_15/File:File.txt.mw &&
185 - test_path_is_file mw_dir_15/File.txt &&
186 - test_path_is_missing mw_dir_15/Main_Page.mw &&
187 - test_path_is_missing mw_dir_15/File:AnotherFile.txt.mw &&
188 - test_path_is_missing mw_dir_15/AnothetFile.txt &&
189 - wiki_check_content mw_dir_15/Testpage.mw Testpage &&
190 - test_cmp mw_dir_15/File.txt File.txt
191 -'
192 -
193 -test_expect_success 'git clone works with one specific page cloned and mediaimport=false' '
194 - test_when_finished "rm -rf mw_dir_16" &&
195 - git clone -c remote.origin.pages=testpage \
196 - mediawiki::'"$WIKI_URL"' mw_dir_16 &&
197 - test_contains_N_files mw_dir_16 1 &&
198 - test_path_is_file mw_dir_16/Testpage.mw &&
199 - test_path_is_missing mw_dir_16/File:File.txt.mw &&
200 - test_path_is_missing mw_dir_16/File.txt &&
201 - test_path_is_missing mw_dir_16/Main_Page.mw &&
202 - wiki_check_content mw_dir_16/Testpage.mw Testpage
203 -'
204 -
205 -# should behave like mediaimport=false
206 -test_expect_success 'git clone works with one specific page cloned and mediaimport unset' '
207 - test_when_finished "rm -fr mw_dir_17" &&
208 - git clone -c remote.origin.pages=testpage \
209 - mediawiki::'"$WIKI_URL"' mw_dir_17 &&
210 - test_contains_N_files mw_dir_17 1 &&
211 - test_path_is_file mw_dir_17/Testpage.mw &&
212 - test_path_is_missing mw_dir_17/File:File.txt.mw &&
213 - test_path_is_missing mw_dir_17/File.txt &&
214 - test_path_is_missing mw_dir_17/Main_Page.mw &&
215 - wiki_check_content mw_dir_17/Testpage.mw Testpage
216 -'
217 -
218 -test_done
contrib/mw-to-git/t/t9364-pull-by-rev.sh deleted
-17
@@ -1,17 +0,0 @@
1 -#!/bin/sh
2 -
3 -test_description='Test the Git Mediawiki remote helper: git pull by revision'
4 -
5 -. ./test-gitmw-lib.sh
6 -. ./push-pull-tests.sh
7 -. $TEST_DIRECTORY/test-lib.sh
8 -
9 -test_check_precond
10 -
11 -test_expect_success 'configuration' '
12 - git config --global mediawiki.fetchStrategy by_rev
13 -'
14 -
15 -test_push_pull
16 -
17 -test_done
contrib/mw-to-git/t/t9365-continuing-queries.sh deleted
-23
@@ -1,23 +0,0 @@
1 -#!/bin/sh
2 -
3 -test_description='Test the Git Mediawiki remote helper: queries w/ more than 500 results'
4 -
5 -. ./test-gitmw-lib.sh
6 -. $TEST_DIRECTORY/test-lib.sh
7 -
8 -test_check_precond
9 -
10 -test_expect_success 'creating page w/ >500 revisions' '
11 - wiki_reset &&
12 - for i in $(test_seq 501)
13 - do
14 - echo "creating revision $i" &&
15 - wiki_editpage foo "revision $i<br/>" true || return 1
16 - done
17 -'
18 -
19 -test_expect_success 'cloning page w/ >500 revisions' '
20 - git clone mediawiki::'"$WIKI_URL"' mw_dir
21 -'
22 -
23 -test_done
contrib/mw-to-git/t/test-gitmw-lib.sh deleted
-432
@@ -1,432 +0,0 @@
1 -# Copyright (C) 2012
2 -# Charles Roussel <charles.roussel@ensimag.imag.fr>
3 -# Simon Cathebras <simon.cathebras@ensimag.imag.fr>
4 -# Julien Khayat <julien.khayat@ensimag.imag.fr>
5 -# Guillaume Sasdy <guillaume.sasdy@ensimag.imag.fr>
6 -# Simon Perrat <simon.perrat@ensimag.imag.fr>
7 -# License: GPL v2 or later
8 -
9 -#
10 -# CONFIGURATION VARIABLES
11 -# You might want to change these ones
12 -#
13 -
14 -. ./test.config
15 -
16 -WIKI_BASE_URL=http://$SERVER_ADDR:$PORT
17 -WIKI_URL=$WIKI_BASE_URL/$WIKI_DIR_NAME
18 -CURR_DIR=$(pwd)
19 -TEST_OUTPUT_DIRECTORY=$(pwd)
20 -TEST_DIRECTORY="$CURR_DIR"/../../../t
21 -
22 -export TEST_OUTPUT_DIRECTORY TEST_DIRECTORY CURR_DIR
23 -
24 -if test "$LIGHTTPD" = "false" ; then
25 - PORT=80
26 -else
27 - WIKI_DIR_INST="$CURR_DIR/$WEB_WWW"
28 -fi
29 -
30 -wiki_upload_file () {
31 - "$CURR_DIR"/test-gitmw.pl upload_file "$@"
32 -}
33 -
34 -wiki_getpage () {
35 - "$CURR_DIR"/test-gitmw.pl get_page "$@"
36 -}
37 -
38 -wiki_delete_page () {
39 - "$CURR_DIR"/test-gitmw.pl delete_page "$@"
40 -}
41 -
42 -wiki_editpage () {
43 - "$CURR_DIR"/test-gitmw.pl edit_page "$@"
44 -}
45 -
46 -die () {
47 - die_with_status 1 "$@"
48 -}
49 -
50 -die_with_status () {
51 - status=$1
52 - shift
53 - echo >&2 "$*"
54 - exit "$status"
55 -}
56 -
57 -
58 -# Check the preconditions to run git-remote-mediawiki's tests
59 -test_check_precond () {
60 - if ! test_have_prereq PERL
61 - then
62 - skip_all='skipping gateway git-mw tests, perl not available'
63 - test_done
64 - fi
65 -
66 - GIT_EXEC_PATH=$(cd "$(dirname "$0")" && cd "../.." && pwd)
67 - PATH="$GIT_EXEC_PATH"'/bin-wrapper:'"$PATH"
68 -
69 - if ! test -d "$WIKI_DIR_INST/$WIKI_DIR_NAME"
70 - then
71 - skip_all='skipping gateway git-mw tests, no mediawiki found'
72 - test_done
73 - fi
74 -}
75 -
76 -# test_diff_directories <dir_git> <dir_wiki>
77 -#
78 -# Compare the contents of directories <dir_git> and <dir_wiki> with diff
79 -# and errors if they do not match. The program will
80 -# not look into .git in the process.
81 -# Warning: the first argument MUST be the directory containing the git data
82 -test_diff_directories () {
83 - rm -rf "$1_tmp"
84 - mkdir -p "$1_tmp"
85 - cp "$1"/*.mw "$1_tmp"
86 - diff -r -b "$1_tmp" "$2"
87 -}
88 -
89 -# $1=<dir>
90 -# $2=<N>
91 -#
92 -# Check that <dir> contains exactly <N> files
93 -test_contains_N_files () {
94 - if test $(ls -- "$1" | wc -l) -ne "$2"; then
95 - echo "directory $1 should contain $2 files"
96 - echo "it contains these files:"
97 - ls "$1"
98 - false
99 - fi
100 -}
101 -
102 -
103 -# wiki_check_content <file_name> <page_name>
104 -#
105 -# Compares the contents of the file <file_name> and the wiki page
106 -# <page_name> and exits with error 1 if they do not match.
107 -wiki_check_content () {
108 - mkdir -p wiki_tmp
109 - wiki_getpage "$2" wiki_tmp
110 - # replacement of forbidden character in file name
111 - page_name=$(printf "%s\n" "$2" | sed -e "s/\//%2F/g")
112 -
113 - diff -b "$1" wiki_tmp/"$page_name".mw
114 - if test $? -ne 0
115 - then
116 - rm -rf wiki_tmp
117 - error "ERROR: file $2 not found on wiki"
118 - fi
119 - rm -rf wiki_tmp
120 -}
121 -
122 -# wiki_page_exist <page_name>
123 -#
124 -# Check the existence of the page <page_name> on the wiki and exits
125 -# with error if it is absent from it.
126 -wiki_page_exist () {
127 - mkdir -p wiki_tmp
128 - wiki_getpage "$1" wiki_tmp
129 - page_name=$(printf "%s\n" "$1" | sed "s/\//%2F/g")
130 - if test -f wiki_tmp/"$page_name".mw ; then
131 - rm -rf wiki_tmp
132 - else
133 - rm -rf wiki_tmp
134 - error "test failed: file $1 not found on wiki"
135 - fi
136 -}
137 -
138 -# wiki_getallpagename
139 -#
140 -# Fetch the name of each page on the wiki.
141 -wiki_getallpagename () {
142 - "$CURR_DIR"/test-gitmw.pl getallpagename
143 -}
144 -
145 -# wiki_getallpagecategory <category>
146 -#
147 -# Fetch the name of each page belonging to <category> on the wiki.
148 -wiki_getallpagecategory () {
149 - "$CURR_DIR"/test-gitmw.pl getallpagename "$@"
150 -}
151 -
152 -# wiki_getallpage <dest_dir> [<category>]
153 -#
154 -# Fetch all the pages from the wiki and place them in the directory
155 -# <dest_dir>.
156 -# If <category> is define, then wiki_getallpage fetch the pages included
157 -# in <category>.
158 -wiki_getallpage () {
159 - if test -z "$2";
160 - then
161 - wiki_getallpagename
162 - else
163 - wiki_getallpagecategory "$2"
164 - fi
165 - mkdir -p "$1"
166 - while read -r line; do
167 - wiki_getpage "$line" $1;
168 - done < all.txt
169 -}
170 -
171 -# ================= Install part =================
172 -
173 -error () {
174 - echo "$@" >&2
175 - exit 1
176 -}
177 -
178 -# config_lighttpd
179 -#
180 -# Create the configuration files and the folders necessary to start lighttpd.
181 -# Overwrite any existing file.
182 -config_lighttpd () {
183 - mkdir -p $WEB
184 - mkdir -p $WEB_TMP
185 - mkdir -p $WEB_WWW
186 - cat > $WEB/lighttpd.conf <<EOF
187 - server.document-root = "$CURR_DIR/$WEB_WWW"
188 - server.port = $PORT
189 - server.pid-file = "$CURR_DIR/$WEB_TMP/pid"
190 -
191 - server.modules = (
192 - "mod_rewrite",
193 - "mod_redirect",
194 - "mod_access",
195 - "mod_accesslog",
196 - "mod_fastcgi"
197 - )
198 -
199 - index-file.names = ("index.php" , "index.html")
200 -
201 - mimetype.assign = (
202 - ".pdf" => "application/pdf",
203 - ".sig" => "application/pgp-signature",
204 - ".spl" => "application/futuresplash",
205 - ".class" => "application/octet-stream",
206 - ".ps" => "application/postscript",
207 - ".torrent" => "application/x-bittorrent",
208 - ".dvi" => "application/x-dvi",
209 - ".gz" => "application/x-gzip",
210 - ".pac" => "application/x-ns-proxy-autoconfig",
211 - ".swf" => "application/x-shockwave-flash",
212 - ".tar.gz" => "application/x-tgz",
213 - ".tgz" => "application/x-tgz",
214 - ".tar" => "application/x-tar",
215 - ".zip" => "application/zip",
216 - ".mp3" => "audio/mpeg",
217 - ".m3u" => "audio/x-mpegurl",
218 - ".wma" => "audio/x-ms-wma",
219 - ".wax" => "audio/x-ms-wax",
220 - ".ogg" => "application/ogg",
221 - ".wav" => "audio/x-wav",
222 - ".gif" => "image/gif",
223 - ".jpg" => "image/jpeg",
224 - ".jpeg" => "image/jpeg",
225 - ".png" => "image/png",
226 - ".xbm" => "image/x-xbitmap",
227 - ".xpm" => "image/x-xpixmap",
228 - ".xwd" => "image/x-xwindowdump",
229 - ".css" => "text/css",
230 - ".html" => "text/html",
231 - ".htm" => "text/html",
232 - ".js" => "text/javascript",
233 - ".asc" => "text/plain",
234 - ".c" => "text/plain",
235 - ".cpp" => "text/plain",
236 - ".log" => "text/plain",
237 - ".conf" => "text/plain",
238 - ".text" => "text/plain",
239 - ".txt" => "text/plain",
240 - ".dtd" => "text/xml",
241 - ".xml" => "text/xml",
242 - ".mpeg" => "video/mpeg",
243 - ".mpg" => "video/mpeg",
244 - ".mov" => "video/quicktime",
245 - ".qt" => "video/quicktime",
246 - ".avi" => "video/x-msvideo",
247 - ".asf" => "video/x-ms-asf",
248 - ".asx" => "video/x-ms-asf",
249 - ".wmv" => "video/x-ms-wmv",
250 - ".bz2" => "application/x-bzip",
251 - ".tbz" => "application/x-bzip-compressed-tar",
252 - ".tar.bz2" => "application/x-bzip-compressed-tar",
253 - "" => "text/plain"
254 - )
255 -
256 - fastcgi.server = ( ".php" =>
257 - ("localhost" =>
258 - ( "socket" => "$CURR_DIR/$WEB_TMP/php.socket",
259 - "bin-path" => "$PHP_DIR/php-cgi -c $CURR_DIR/$WEB/php.ini"
260 -
261 - )
262 - )
263 - )
264 -EOF
265 -
266 - cat > $WEB/php.ini <<EOF
267 - session.save_path ='$CURR_DIR/$WEB_TMP'
268 -EOF
269 -}
270 -
271 -# start_lighttpd
272 -#
273 -# Start or restart daemon lighttpd. If restart, rewrite configuration files.
274 -start_lighttpd () {
275 - if test -f "$WEB_TMP/pid"; then
276 - echo "Instance already running. Restarting..."
277 - stop_lighttpd
278 - fi
279 - config_lighttpd
280 - "$LIGHTTPD_DIR"/lighttpd -f "$WEB"/lighttpd.conf
281 -
282 - if test $? -ne 0 ; then
283 - echo "Could not execute http daemon lighttpd"
284 - exit 1
285 - fi
286 -}
287 -
288 -# stop_lighttpd
289 -#
290 -# Kill daemon lighttpd and removes files and folders associated.
291 -stop_lighttpd () {
292 - test -f "$WEB_TMP/pid" && kill $(cat "$WEB_TMP/pid")
293 -}
294 -
295 -wiki_delete_db () {
296 - rm -rf \
297 - "$FILES_FOLDER_DB"/* || error "Couldn't delete $FILES_FOLDER_DB/"
298 -}
299 -
300 -wiki_delete_db_backup () {
301 - rm -rf \
302 - "$FILES_FOLDER_POST_INSTALL_DB"/* || error "Couldn't delete $FILES_FOLDER_POST_INSTALL_DB/"
303 -}
304 -
305 -# Install MediaWiki using its install.php script. If the database file
306 -# already exists, it will be deleted.
307 -install_mediawiki () {
308 -
309 - localsettings="$WIKI_DIR_INST/$WIKI_DIR_NAME/LocalSettings.php"
310 - if test -f "$localsettings"
311 - then
312 - error "We already installed the wiki, since $localsettings exists" \
313 - "perhaps you wanted to run 'delete' first?"
314 - fi
315 -
316 - wiki_delete_db
317 - wiki_delete_db_backup
318 - mkdir \
319 - "$FILES_FOLDER_DB/" \
320 - "$FILES_FOLDER_POST_INSTALL_DB/"
321 -
322 - install_script="$WIKI_DIR_INST/$WIKI_DIR_NAME/maintenance/install.php"
323 - echo "Installing MediaWiki using $install_script. This may take some time ..."
324 -
325 - php "$WIKI_DIR_INST/$WIKI_DIR_NAME/maintenance/install.php" \
326 - --server $WIKI_BASE_URL \
327 - --scriptpath /wiki \
328 - --lang en \
329 - --dbtype sqlite \
330 - --dbpath $PWD/$FILES_FOLDER_DB/ \
331 - --pass "$WIKI_PASSW" \
332 - Git-MediaWiki-Test \
333 - "$WIKI_ADMIN" ||
334 - error "Couldn't run $install_script, see errors above. Try to run ./install-wiki.sh delete first."
335 - cat <<-'EOF' >>$localsettings
336 -# Custom settings added by test-gitmw-lib.sh
337 -#
338 -# Uploading text files is needed for
339 -# t9363-mw-to-git-export-import.sh
340 -$wgEnableUploads = true;
341 -$wgFileExtensions[] = 'txt';
342 -EOF
343 -
344 - # Copy the initially generated database file into our backup
345 - # folder
346 - cp -R "$FILES_FOLDER_DB/"* "$FILES_FOLDER_POST_INSTALL_DB/" ||
347 - error "Unable to copy $FILES_FOLDER_DB/* to $FILES_FOLDER_POST_INSTALL_DB/*"
348 -}
349 -
350 -# Install a wiki in your web server directory.
351 -wiki_install () {
352 - if test $LIGHTTPD = "true" ; then
353 - start_lighttpd
354 - fi
355 -
356 - # In this part, we change directory to $TMP in order to download,
357 - # unpack and copy the files of MediaWiki
358 - (
359 - mkdir -p "$WIKI_DIR_INST/$WIKI_DIR_NAME"
360 - if ! test -d "$WIKI_DIR_INST/$WIKI_DIR_NAME"
361 - then
362 - error "Folder $WIKI_DIR_INST/$WIKI_DIR_NAME doesn't exist.
363 - Please create it and launch the script again."
364 - fi
365 -
366 - # Fetch MediaWiki's archive if not already present in the
367 - # download directory
368 - mkdir -p "$FILES_FOLDER_DOWNLOAD"
369 - MW_FILENAME="mediawiki-$MW_VERSION_MAJOR.$MW_VERSION_MINOR.tar.gz"
370 - cd "$FILES_FOLDER_DOWNLOAD"
371 - if ! test -f $MW_FILENAME
372 - then
373 - echo "Downloading $MW_VERSION_MAJOR.$MW_VERSION_MINOR sources ..."
374 - wget "http://download.wikimedia.org/mediawiki/$MW_VERSION_MAJOR/$MW_FILENAME" ||
375 - error "Unable to download "\
376 - "http://download.wikimedia.org/mediawiki/$MW_VERSION_MAJOR/"\
377 - "$MW_FILENAME. "\
378 - "Please fix your connection and launch the script again."
379 - echo "$MW_FILENAME downloaded in $(pwd)/;" \
380 - "you can delete it later if you want."
381 - else
382 - echo "Reusing existing $MW_FILENAME downloaded in $(pwd)/"
383 - fi
384 - archive_abs_path=$(pwd)/$MW_FILENAME
385 - cd "$WIKI_DIR_INST/$WIKI_DIR_NAME/" ||
386 - error "can't cd to $WIKI_DIR_INST/$WIKI_DIR_NAME/"
387 - tar xzf "$archive_abs_path" --strip-components=1 ||
388 - error "Unable to extract WikiMedia's files from $archive_abs_path to "\
389 - "$WIKI_DIR_INST/$WIKI_DIR_NAME"
390 - ) || exit 1
391 - echo Extracted in "$WIKI_DIR_INST/$WIKI_DIR_NAME"
392 -
393 - install_mediawiki
394 -
395 - echo "Your wiki has been installed. You can check it at
396 - $WIKI_URL"
397 -}
398 -
399 -# Reset the database of the wiki and the password of the admin
400 -#
401 -# Warning: This function must be called only in a subdirectory of t/ directory
402 -wiki_reset () {
403 - # Copy initial database of the wiki
404 - if ! test -d "../$FILES_FOLDER_DB"
405 - then
406 - error "No wiki database at ../$FILES_FOLDER_DB, not installed yet?"
407 - fi
408 - if ! test -d "../$FILES_FOLDER_POST_INSTALL_DB"
409 - then
410 - error "No wiki backup database at ../$FILES_FOLDER_POST_INSTALL_DB, failed installation?"
411 - fi
412 - wiki_delete_db
413 - cp -R "../$FILES_FOLDER_POST_INSTALL_DB/"* "../$FILES_FOLDER_DB/" ||
414 - error "Can't copy ../$FILES_FOLDER_POST_INSTALL_DB/* to ../$FILES_FOLDER_DB/*"
415 - echo "File $FILES_FOLDER_DB/* has been reset"
416 -}
417 -
418 -# Delete the wiki created in the web server's directory and all its content
419 -# saved in the database.
420 -wiki_delete () {
421 - if test $LIGHTTPD = "true"; then
422 - stop_lighttpd
423 - rm -fr "$WEB"
424 - else
425 - # Delete the wiki's directory.
426 - rm -rf "$WIKI_DIR_INST/$WIKI_DIR_NAME" ||
427 - error "Wiki's directory $WIKI_DIR_INST/" \
428 - "$WIKI_DIR_NAME could not be deleted"
429 - fi
430 - wiki_delete_db
431 - wiki_delete_db_backup
432 -}
contrib/mw-to-git/t/test-gitmw.pl deleted
-223
@@ -1,223 +0,0 @@
1 -#!/usr/bin/perl -w -s
2 -# Copyright (C) 2012
3 -# Charles Roussel <charles.roussel@ensimag.imag.fr>
4 -# Simon Cathebras <simon.cathebras@ensimag.imag.fr>
5 -# Julien Khayat <julien.khayat@ensimag.imag.fr>
6 -# Guillaume Sasdy <guillaume.sasdy@ensimag.imag.fr>
7 -# Simon Perrat <simon.perrat@ensimag.imag.fr>
8 -# License: GPL v2 or later
9 -
10 -# Usage:
11 -# ./test-gitmw.pl <command> [argument]*
12 -# Execute in terminal using the name of the function to call as first
13 -# parameter, and the function's arguments as following parameters
14 -#
15 -# Example:
16 -# ./test-gitmw.pl "get_page" foo .
17 -# will call <wiki_getpage> with arguments <foo> and <.>
18 -#
19 -# Available functions are:
20 -# "get_page"
21 -# "delete_page"
22 -# "edit_page"
23 -# "getallpagename"
24 -
25 -use MediaWiki::API;
26 -use Getopt::Long;
27 -use DateTime::Format::ISO8601;
28 -use constant SLASH_REPLACEMENT => "%2F";
29 -
30 -#Parsing of the config file
31 -
32 -my $configfile = "$ENV{'CURR_DIR'}/test.config";
33 -my %config;
34 -open my $CONFIG, "<", $configfile or die "can't open $configfile: $!";
35 -while (<$CONFIG>)
36 -{
37 - chomp;
38 - s/#.*//;
39 - s/^\s+//;
40 - s/\s+$//;
41 - next unless length;
42 - my ($key, $value) = split (/\s*=\s*/,$_, 2);
43 - $config{$key} = $value;
44 - last if ($key eq 'LIGHTTPD' and $value eq 'false');
45 - last if ($key eq 'PORT');
46 -}
47 -close $CONFIG or die "can't close $configfile: $!";
48 -
49 -my $wiki_address = "http://$config{'SERVER_ADDR'}".":"."$config{'PORT'}";
50 -my $wiki_url = "$wiki_address/$config{'WIKI_DIR_NAME'}/api.php";
51 -my $wiki_admin = "$config{'WIKI_ADMIN'}";
52 -my $wiki_admin_pass = "$config{'WIKI_PASSW'}";
53 -my $mw = MediaWiki::API->new;
54 -$mw->{config}->{api_url} = $wiki_url;
55 -
56 -
57 -# wiki_login <name> <password>
58 -#
59 -# Logs the user with <name> and <password> in the global variable
60 -# of the mediawiki $mw
61 -sub wiki_login {
62 - $mw->login( { lgname => "$_[0]",lgpassword => "$_[1]" } )
63 - || die "getpage: login failed";
64 -}
65 -
66 -# wiki_getpage <wiki_page> <dest_path>
67 -#
68 -# fetch a page <wiki_page> from the wiki referenced in the global variable
69 -# $mw and copies its content in directory dest_path
70 -sub wiki_getpage {
71 - my $pagename = $_[0];
72 - my $destdir = $_[1];
73 -
74 - my $page = $mw->get_page( { title => $pagename } );
75 - if (!defined($page)) {
76 - die "getpage: wiki does not exist";
77 - }
78 -
79 - my $content = $page->{'*'};
80 - if (!defined($content)) {
81 - die "getpage: page does not exist";
82 - }
83 -
84 - $pagename=$page->{'title'};
85 - # Replace spaces by underscore in the page name
86 - $pagename =~ s/ /_/g;
87 - $pagename =~ s/\//%2F/g;
88 - open(my $file, ">:encoding(UTF-8)", "$destdir/$pagename.mw");
89 - print $file "$content";
90 - close ($file);
91 -
92 -}
93 -
94 -# wiki_delete_page <page_name>
95 -#
96 -# delete the page with name <page_name> from the wiki referenced
97 -# in the global variable $mw
98 -sub wiki_delete_page {
99 - my $pagename = $_[0];
100 -
101 - my $exist=$mw->get_page({title => $pagename});
102 -
103 - if (defined($exist->{'*'})){
104 - $mw->edit({ action => 'delete',
105 - title => $pagename})
106 - || die $mw->{error}->{code} . ": " . $mw->{error}->{details};
107 - } else {
108 - die "no page with such name found: $pagename\n";
109 - }
110 -}
111 -
112 -# wiki_editpage <wiki_page> <wiki_content> <wiki_append> [-c=<category>] [-s=<summary>]
113 -#
114 -# Edit a page named <wiki_page> with content <wiki_content> on the wiki
115 -# referenced with the global variable $mw
116 -# If <wiki_append> == true : append <wiki_content> at the end of the actual
117 -# content of the page <wiki_page>
118 -# If <wik_page> doesn't exist, that page is created with the <wiki_content>
119 -sub wiki_editpage {
120 - my $wiki_page = $_[0];
121 - my $wiki_content = $_[1];
122 - my $wiki_append = $_[2];
123 - my $summary = "";
124 - my ($summ, $cat) = ();
125 - GetOptions('s=s' => \$summ, 'c=s' => \$cat);
126 -
127 - my $append = 0;
128 - if (defined($wiki_append) && $wiki_append eq 'true') {
129 - $append=1;
130 - }
131 -
132 - my $previous_text ="";
133 -
134 - if ($append) {
135 - my $ref = $mw->get_page( { title => $wiki_page } );
136 - $previous_text = $ref->{'*'};
137 - }
138 -
139 - my $text = $wiki_content;
140 - if (defined($previous_text)) {
141 - $text="$previous_text$text";
142 - }
143 -
144 - # Eventually, add this page to a category.
145 - if (defined($cat)) {
146 - my $category_name="[[Category:$cat]]";
147 - $text="$text\n $category_name";
148 - }
149 - if(defined($summ)){
150 - $summary=$summ;
151 - }
152 -
153 - $mw->edit( { action => 'edit', title => $wiki_page, summary => $summary, text => "$text"} );
154 -}
155 -
156 -# wiki_getallpagename [<category>]
157 -#
158 -# Fetch all pages of the wiki referenced by the global variable $mw
159 -# and print the names of each one in the file all.txt with a new line
160 -# ("\n") between these.
161 -# If the argument <category> is defined, then this function get only the pages
162 -# belonging to <category>.
163 -sub wiki_getallpagename {
164 - # fetch the pages of the wiki
165 - if (defined($_[0])) {
166 - my $mw_pages = $mw->list ( { action => 'query',
167 - list => 'categorymembers',
168 - cmtitle => "Category:$_[0]",
169 - cmnamespace => 0,
170 - cmlimit => 500 },
171 - )
172 - || die $mw->{error}->{code}.": ".$mw->{error}->{details};
173 - open(my $file, ">:encoding(UTF-8)", "all.txt");
174 - foreach my $page (@{$mw_pages}) {
175 - print $file "$page->{title}\n";
176 - }
177 - close ($file);
178 -
179 - } else {
180 - my $mw_pages = $mw->list({
181 - action => 'query',
182 - list => 'allpages',
183 - aplimit => 500,
184 - })
185 - || die $mw->{error}->{code}.": ".$mw->{error}->{details};
186 - open(my $file, ">:encoding(UTF-8)", "all.txt");
187 - foreach my $page (@{$mw_pages}) {
188 - print $file "$page->{title}\n";
189 - }
190 - close ($file);
191 - }
192 -}
193 -
194 -sub wiki_upload_file {
195 - my $file_name = $_[0];
196 - my $resultat = $mw->edit ( {
197 - action => 'upload',
198 - filename => $file_name,
199 - comment => 'upload a file',
200 - file => [ $file_name ],
201 - ignorewarnings=>1,
202 - }, {
203 - skip_encoding => 1
204 - } ) || die $mw->{error}->{code} . ' : ' . $mw->{error}->{details};
205 -}
206 -
207 -
208 -
209 -# Main part of this script: parse the command line arguments
210 -# and select which function to execute
211 -my $fct_to_call = shift;
212 -
213 -wiki_login($wiki_admin, $wiki_admin_pass);
214 -
215 -my %functions_to_call = (
216 - upload_file => \&wiki_upload_file,
217 - get_page => \&wiki_getpage,
218 - delete_page => \&wiki_delete_page,
219 - edit_page => \&wiki_editpage,
220 - getallpagename => \&wiki_getallpagename,
221 -);
222 -die "$0 ERROR: wrong argument" unless exists $functions_to_call{$fct_to_call};
223 -$functions_to_call{$fct_to_call}->(map { utf8::decode($_); $_ } @ARGV);
contrib/mw-to-git/t/test.config deleted
-40
@@ -1,40 +0,0 @@
1 -# Name of the web server's directory dedicated to the wiki is WIKI_DIR_NAME
2 -WIKI_DIR_NAME=wiki
3 -
4 -# Login and password of the wiki's admin
5 -WIKI_ADMIN=WikiAdmin
6 -WIKI_PASSW=AdminPass1
7 -
8 -# Address of the web server
9 -SERVER_ADDR=localhost
10 -
11 -# If LIGHTTPD is not set to true, the script will use the default
12 -# web server running in WIKI_DIR_INST.
13 -WIKI_DIR_INST=/var/www
14 -
15 -# If LIGHTTPD is set to true, the script will use Lighttpd to run
16 -# the wiki.
17 -LIGHTTPD=true
18 -
19 -# The variables below are useful only if LIGHTTPD is set to true.
20 -PORT=1234
21 -PHP_DIR=/usr/bin
22 -LIGHTTPD_DIR=/usr/sbin
23 -WEB=WEB
24 -WEB_TMP=$WEB/tmp
25 -WEB_WWW=$WEB/www
26 -
27 -# Where our configuration for the wiki is located
28 -FILES_FOLDER=mediawiki
29 -FILES_FOLDER_DOWNLOAD=$FILES_FOLDER/download
30 -FILES_FOLDER_DB=$FILES_FOLDER/db
31 -FILES_FOLDER_POST_INSTALL_DB=$FILES_FOLDER/post-install-db
32 -
33 -# The variables below are used by the script to install a wiki.
34 -# You should not modify these unless you are modifying the script itself.
35 -# tested versions: 1.19.X -> 1.21.1 -> 1.34.2
36 -#
37 -# See https://www.mediawiki.org/wiki/Download for what the latest
38 -# version is.
39 -MW_VERSION_MAJOR=1.34
40 -MW_VERSION_MINOR=2