From: Jeremie Nikaes <jeremie.nikaes@ensimag.imag.fr>
To: git@vger.kernel.org
Cc: "Jeremie Nikaes" <jeremie.nikaes@ensimag.imag.fr>,
"Arnaud Lacurie" <arnaud.lacurie@ensimag.imag.fr>,
"Claire Fousse" <claire.fousse@ensimag.imag.fr>,
"David Amouyal" <david.amouyal@ensimag.imag.fr>,
"Matthieu Moy" <matthieu.moy@grenoble-inp.fr>,
"Sylvain Boulmé" <sylvain.boulme@imag.fr>
Subject: [RFC/PATCH 2/2] Git-remote-mediawiki: Add push support
Date: Thu, 9 Jun 2011 15:16:00 +0200 [thread overview]
Message-ID: <1307625360-10973-2-git-send-email-jeremie.nikaes@ensimag.imag.fr> (raw)
In-Reply-To: <1307625360-10973-1-git-send-email-jeremie.nikaes@ensimag.imag.fr>
Push is now supported by the remote-helper
Thanks to notes metadata, it is possible to compare remote and local
last mediawiki revision to warn non fast-forward and everything
up-to-date.
When allowed, push looks for each commit between remotes/origin/master
and HEAD, catches every blob related to these commit and push them in
chronological order. To do so, it uses git rev-list --children HEAD and
travels the tree from remotes/origin/master to HEAD through children. In
other words :
* Shortest path from remotes/origin/master to HEAD
* For each commit encountered, push blobs related to this commit
An automatic git pull --rebase is executed after a successful push to
get metadata back from mediawiki. This is also done to maintain
closeness with the form of a mediawiki history. It can be a problem
since it also flatens the entire history. (This solution is still
to be discussed).
To send files to mediawiki, the mediawiki API is used. A filter is
applied to the data send because mediawiki pages cannot have blank
characters at the end. The filter is thus more or less a right trim.
Signed-off-by: Jérémie Nikaes <jeremie.nikaes@ensimag.imag.fr>
Signed-off-by: Arnaud Lacurie <arnaud.lacurie@ensimag.imag.fr>
Signed-off-by: Claire Fousse <claire.fousse@ensimag.imag.fr>
Signed-off-by: David Amouyal <david.amouyal@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>
Signed-off-by: Sylvain Boulmé <sylvain.boulme@imag.fr>
---
contrib/mw-to-git/git-remote-mediawiki | 93 +++++++++++++++++++++++++++++++-
1 files changed, 92 insertions(+), 1 deletions(-)
diff --git a/contrib/mw-to-git/git-remote-mediawiki b/contrib/mw-to-git/git-remote-mediawiki
index 176ff09..dc1aacf 100755
--- a/contrib/mw-to-git/git-remote-mediawiki
+++ b/contrib/mw-to-git/git-remote-mediawiki
@@ -148,6 +148,14 @@ sub get_last_remote_revision {
return $max_rev_num;
}
+sub mediawiki_filter($) {
+ # Mediawiki does not allow blank space at the end of a page and ends with a single \n.
+ # This function right trims a string and adds a \n at the end to follow this rule
+ my $string = shift;
+ $string =~ s/\s+$//;
+ return $string."\n";
+}
+
sub literal_data {
my ($content) = @_;
print STDOUT "data ", bytes::length($content), "\n", $content;
@@ -175,6 +183,7 @@ sub mw_list {
}
sub mw_option {
+ print STDERR "remote-helper capability 'option' not yet implemented \n";
print STDOUT "unsupported\n";
}
@@ -318,5 +327,87 @@ sub mw_import {
}
sub mw_push {
- print STDERR "Push not yet implemented\n";
+
+ sub push_file {
+ #$_[0] contains a string in this format :
+ #100644 100644 <sha1_of_blob_before_commit> <sha1_of_blob_now> <status>\0<filename.mw>\0
+ #$_[1] contains the title of the commit message (the only phrase kept in the revision message)
+ my @blob_info_split = split(/ |\t|\0/, $_[0]);
+
+ my $sha1 = $blob_info_split[3];
+ my $complete_file_name = $blob_info_split[5];
+ # complete_file_name = uri_unescape($complete_file_name); # If we use the uri escape before
+ # we should unescape here, before anything
+
+ if (substr($complete_file_name,-3) eq ".mw"){
+ my $title = substr($complete_file_name,0,-3);
+ $title =~ s/$slash_replacement/\//g;
+
+ my $file_content = run_git("cat-file -p $sha1");
+
+ my $mw = MediaWiki::API->new();
+ $mw->{config}->{api_url} = "$url/api.php";
+
+ # log in to the wiki : here should be added a way to push changes with an identity
+ #$mw->login( { lgname => 'login', lgpassword => 'passwd' })
+ #|| die $mw->{error}->{code} . ': ' . $mw->{error}->{details};
+
+ $mw->edit( {
+ action => 'edit',
+ summary => $_[1],
+ title => $title,
+ text => mediawiki_filter($file_content),
+ }, {
+ skip_encoding => 1 # Helps with names with accentuated characters
+ }) || die 'Fatal: Error ' . $mw->{error}->{code} . ' from mediwiki: ' . $mw->{error}->{details};
+
+ print STDERR "Pushed file : $sha1 - $title\n";
+ } else {
+ print STDERR "$complete_file_name not a mediawiki file. '(Not pushable on this version)\n"
+ }
+ }
+
+ my $last_local_revid = get_last_local_revision();
+ my $last_remote_revid = get_last_remote_revision();
+
+ # Get sha1 of commit pointed by local HEAD
+ my $HEAD_sha1 = run_git("rev-parse $_[0] 2>/dev/null"); chomp($HEAD_sha1);
+ # Get sha1 of commit pointed by remotes/origin/master
+ my $remoteorigin_sha1 = run_git("rev-parse refs/remotes/origin/master 2>/dev/null"); chomp($remoteorigin_sha1);
+
+ if ($last_local_revid < $last_remote_revid){
+ my $message = "\"To prevent you from losing history, non-fast-forward updates were rejected \\n";
+ $message .= "Merge the remote changes (e.g. 'git pull') before pushing again. See the";
+ $message .= " 'Note about fast-forwards' section of 'git push --help' for details.\"";
+ print STDOUT "error $_[0] $message\n";
+ print STDOUT "\n";
+ } elsif ($HEAD_sha1 ne $remoteorigin_sha1) {
+ # Get every commit in between HEAD and refs/remotes/origin/master,
+ # including HEAD and refs/remotes/origin/master
+ my $parsed_sha1 = $remoteorigin_sha1;
+ while ($parsed_sha1 ne $HEAD_sha1) {
+ my @commit_info = grep(/^$parsed_sha1/, `git rev-list --children $_[0]`);
+ my @commit_info_split = split(/ |\n/, $commit_info[0]);
+ # $commit_info_split[0] is the sha1 of the commit itself
+ # $commit_info_split[1] is the sha1 of its direct child
+ my $blob_infos = run_git("diff --raw --abbrev=40 -z $commit_info_split[0] $commit_info_split[1]");
+ my @blob_info_list = split(/\n/, $blob_infos);
+ # Keep the first line of the commit message as mediawiki comment for the revision
+ my $commit_msg = (split(/\n/, run_git("show --pretty=format:\"%s\" $commit_info_split[1]")))[0];
+ chomp($commit_msg);
+ foreach my $blob_info (@blob_info_list) {
+ # Push every blob
+ push_file($blob_info, $commit_msg);
+ }
+ $parsed_sha1 = $commit_info_split[1];
+ }
+
+ print STDOUT "ok $_[1]\n";
+ print STDOUT "\n";
+
+ # Pulling from mediawiki after pushing in order to keep things synchronized
+ exec("git pull --rebase >/dev/null");
+ } else {
+ print STDOUT "\n";
+ }
}
--
1.7.4.1
next prev parent reply other threads:[~2011-06-09 13:17 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-09 13:15 [PATCHv3 1/2] Add a remote helper to interact with mediawiki, pull & clone handled Jeremie Nikaes
2011-06-09 13:16 ` Jeremie Nikaes [this message]
2011-06-09 17:15 ` [RFC/PATCH 2/2] Git-remote-mediawiki: Add push support Junio C Hamano
2011-06-09 14:03 ` [PATCHv3 1/2] Add a remote helper to interact with mediawiki, pull & clone handled Sverre Rabbelier
2011-06-09 14:30 ` Jérémie NIKAES
2011-06-09 14:32 ` Sverre Rabbelier
2011-06-09 22:44 ` Jeff King
2011-06-10 0:21 ` Jeff King
2011-06-10 6:31 ` Arnaud Lacurie
2011-06-10 7:22 ` Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1307625360-10973-2-git-send-email-jeremie.nikaes@ensimag.imag.fr \
--to=jeremie.nikaes@ensimag.imag.fr \
--cc=arnaud.lacurie@ensimag.imag.fr \
--cc=claire.fousse@ensimag.imag.fr \
--cc=david.amouyal@ensimag.imag.fr \
--cc=git@vger.kernel.org \
--cc=matthieu.moy@grenoble-inp.fr \
--cc=sylvain.boulme@imag.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).