* Re: need to create new repository initially seeded with several branches
From: Brandon Casey @ 2011-08-31 17:01 UTC (permalink / raw)
To: Jeff King; +Cc: ryan@iridiumsuite.com, git
In-Reply-To: <20110831165405.GB4356@sigill.intra.peff.net>
On 08/31/2011 11:54 AM, Jeff King wrote:
> On Wed, Aug 31, 2011 at 11:14:48AM -0500, Brandon Casey wrote:
>
>> git checkout -b devel && # make a new branch named "devel"
>> # which has the same state as the
>> # currently checked out branch: "master"
>> # i.e. devel and master point to the
>> # same tip commit.
>> rm -rf * && # remove the files in the working dir
>> cp -a $devel_dir/* . && # cp devel source code to working dir
>> git add -A . && # add new/removed files to the index
>> # to be committed on next 'git commit'
>> git commit
>> # use editor to give descriptive commit message
>>
>> Repeat for your topic branch based off of devel.
>
> I am probably just going to confuse the original poster more, but here
> is how I would do it. It's slightly more efficient, as it doesn't
> involve removing and copying files for the intermediate states:
>
> # make a repo and switch to it
> git init repo && cd repo
>
> # and now add everything from the "master" version, and
> # make a commit out of it
> GIT_WORK_TREE=/path/to/master git add -A
> git commit
>
> # now make the devel branch and do the same
> git checkout -b devel
> GIT_WORK_TREE=/path/to/devel git add -A
> git commit
>
> # and then check out the result in the working tree of
> # your newly created repo
> git checkout -f
Better.
-Brandon
^ permalink raw reply
* [PATCH v6] Add a remote helper to interact with mediawiki (fetch & push)
From: Matthieu Moy @ 2011-08-31 16:55 UTC (permalink / raw)
To: git, gitster
Cc: Jeremie Nikaes, Arnaud Lacurie, Claire Fousse, David Amouyal,
Matthieu Moy, Sylvain Boulmé, Matthieu Moy
In-Reply-To: <1314381329-8989-1-git-send-email-Matthieu.Moy@imag.fr>
From: Jeremie Nikaes <jeremie.nikaes@ensimag.imag.fr>
Implement a gate between git and mediawiki, allowing git users to push
and pull objects from mediawiki just as one would do with a classic git
repository thanks to remote-helpers.
The following packages need to be installed (available on common
repositories):
libmediawiki-api-perl
libdatetime-format-iso8601-perl
Use remote helpers in order to be as transparent as possible to the git
user.
Download Mediawiki revisions through the Mediawiki API and then
fast-import into git.
Mediawiki revision number and git commits are linked thanks to notes
bound to commits.
The import part is done on a refs/mediawiki/<remote> branch before
coming to refs/remote/origin/master (Huge thanks to Jonathan Nieder
for his help)
We use UTF-8 everywhere: use encoding 'utf8'; does most of the job, but
we also read the output of Git commands in UTF-8 with the small helper
run_git, and write to the console (STDERR) in UTF-8. This allows a
seamless use of non-ascii characters in page titles, but hasn't been
tested on non-UTF-8 systems. In particular, UTF-8 encoding for filenames
could raise problems if different file systems handle UTF-8 filenames
differently. A uri_escape of mediawiki filenames could be imaginable, and
is still to be discussed further.
Partial cloning is supported using one of:
git clone -c remote.origin.pages='A_Page Another_Page' mediawiki::http://wikiurl
git clone -c remote.origin.categories='Some_Category' mediawiki::http://wikiurl
git clone -c remote.origin.shallow='True' mediawiki::http://wikiurl
Thanks to notes metadata, it is possible to compare remote and local last
mediawiki revision to warn non-fast forward pushes and "everything
up-to-date" case.
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
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>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
So, after understanding better how import works, here's an updated
patch that gets rid of the hacky workaround to terminate and send the
"done" command at the right time.
Actually, push had the same problem but it just went unnoticed (the
remote has just one branch, so it's silly to try to push multiple
branches at the same time ...). This version handles push more
cleanly, giving accurate error message in cases like
git push origin :master
git push origin foo bar master
or perhaps more commonly
git push --all
in a repository with branches other than master.
There are still a few TODO, but I think all of them can wait.
contrib/mw-to-git/git-remote-mediawiki | 758 ++++++++++++++++++++++++++++
contrib/mw-to-git/git-remote-mediawiki.txt | 7 +
2 files changed, 765 insertions(+), 0 deletions(-)
create mode 100755 contrib/mw-to-git/git-remote-mediawiki
create mode 100644 contrib/mw-to-git/git-remote-mediawiki.txt
diff --git a/contrib/mw-to-git/git-remote-mediawiki b/contrib/mw-to-git/git-remote-mediawiki
new file mode 100755
index 0000000..51f01cd
--- /dev/null
+++ b/contrib/mw-to-git/git-remote-mediawiki
@@ -0,0 +1,758 @@
+#! /usr/bin/perl
+
+# Copyright (C) 2011
+# Jérémie 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>
+# License: GPL v2 or later
+
+# Gateway between Git and MediaWiki.
+# https://github.com/Bibzball/Git-Mediawiki/wiki
+#
+# Known limitations:
+#
+# - Only wiki pages are managed, no support for [[File:...]]
+# attachments.
+#
+# - Poor performance in the best case: it takes forever to check
+# whether we're up-to-date (on fetch or push) or to fetch a few
+# revisions from a large wiki, because we use exclusively a
+# page-based synchronization. We could switch to a wiki-wide
+# synchronization when the synchronization involves few revisions
+# but the wiki is large.
+#
+# - Git renames could be turned into MediaWiki renames (see TODO
+# below)
+#
+# - login/password support requires the user to write the password
+# cleartext in a file (see TODO below).
+#
+# - No way to import "one page, and all pages included in it"
+#
+# - Multiple remote MediaWikis have not been very well tested.
+
+use strict;
+use MediaWiki::API;
+use DateTime::Format::ISO8601;
+use encoding 'utf8';
+
+# use encoding 'utf8' doesn't change STDERROR
+# but we're going to output UTF-8 filenames to STDERR
+binmode STDERR, ":utf8";
+
+use URI::Escape;
+use warnings;
+
+# Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
+use constant SLASH_REPLACEMENT => "%2F";
+
+# It's not always possible to delete pages (may require some
+# priviledges). Deleted pages are replaced with this content.
+use constant DELETED_CONTENT => "[[Category:Deleted]]\n";
+
+# It's not possible to create empty pages. New empty files in Git are
+# sent with this content instead.
+use constant EMPTY_CONTENT => "<!-- empty page -->\n";
+
+# used to reflect file creation or deletion in diff.
+use constant NULL_SHA1 => "0000000000000000000000000000000000000000";
+
+my $remotename = $ARGV[0];
+my $url = $ARGV[1];
+
+# Accept both space-separated and multiple keys in config file.
+# Spaces should be written as _ anyway because we'll use chomp.
+my @tracked_pages = split(/[ \n]/, run_git("config --get-all remote.". $remotename .".pages"));
+chomp(@tracked_pages);
+
+# Just like @tracked_pages, but for MediaWiki categories.
+my @tracked_categories = split(/[ \n]/, run_git("config --get-all remote.". $remotename .".categories"));
+chomp(@tracked_categories);
+
+my $wiki_login = run_git("config --get remote.". $remotename .".mwLogin");
+# TODO: ideally, this should be able to read from keyboard, but we're
+# inside a remote helper, so our stdin is connect to git, not to a
+# terminal.
+my $wiki_passwd = run_git("config --get remote.". $remotename .".mwPassword");
+chomp ($wiki_login);
+chomp ($wiki_passwd);
+
+# Import only last revisions (both for clone and fetch)
+my $shallow_import = run_git("config --get --bool remote.". $remotename .".shallow");
+chomp($shallow_import);
+$shallow_import = ($shallow_import eq "true");
+
+my $wiki_name = $url;
+$wiki_name =~ s/[^\/]*:\/\///;
+
+# Commands parser
+my $entry;
+my @cmd;
+while (<STDIN>) {
+ chomp;
+ @cmd = split(/ /);
+ if (defined($cmd[0])) {
+ # Line not blank
+ if ($cmd[0] eq "capabilities") {
+ die("Too many arguments for capabilities") unless (!defined($cmd[1]));
+ mw_capabilities();
+ } elsif ($cmd[0] eq "list") {
+ die("Too many arguments for list") unless (!defined($cmd[2]));
+ mw_list($cmd[1]);
+ } elsif ($cmd[0] eq "import") {
+ die("Invalid arguments for import") unless ($cmd[1] ne "" && !defined($cmd[2]));
+ mw_import($cmd[1]);
+ } elsif ($cmd[0] eq "option") {
+ die("Too many arguments for option") unless ($cmd[1] ne "" && $cmd[2] ne "" && !defined($cmd[3]));
+ mw_option($cmd[1],$cmd[2]);
+ } elsif ($cmd[0] eq "push") {
+ mw_push($cmd[1]);
+ } else {
+ print STDERR "Unknown command. Aborting...\n";
+ last;
+ }
+ } else {
+ # blank line: we should terminate
+ last;
+ }
+
+ BEGIN { $| = 1 } # flush STDOUT, to make sure the previous
+ # command is fully processed.
+}
+
+########################## Functions ##############################
+
+# MediaWiki API instance, created lazily.
+my $mediawiki;
+
+sub mw_connect_maybe {
+ if ($mediawiki) {
+ return;
+ }
+ $mediawiki = MediaWiki::API->new;
+ $mediawiki->{config}->{api_url} = "$url/api.php";
+ if ($wiki_login) {
+ if (!$mediawiki->login({
+ lgname => $wiki_login,
+ lgpassword => $wiki_passwd,
+ })) {
+ print STDERR "Failed to log in mediawiki user \"$wiki_login\" on $url\n";
+ print STDERR "(error " .
+ $mediawiki->{error}->{code} . ': ' .
+ $mediawiki->{error}->{details} . ")\n";
+ exit 1;
+ } else {
+ print STDERR "Logged in with user \"$wiki_login\".\n";
+ }
+ }
+}
+
+sub get_mw_first_pages {
+ my $some_pages = shift;
+ my @some_pages = @{$some_pages};
+
+ my $pages = shift;
+
+ # pattern 'page1|page2|...' required by the API
+ my $titles = join('|', @some_pages);
+
+ my $mw_pages = $mediawiki->api({
+ action => 'query',
+ titles => $titles,
+ });
+ if (!defined($mw_pages)) {
+ print STDERR "fatal: could not query the list of wiki pages.\n";
+ print STDERR "fatal: '$url' does not appear to be a mediawiki\n";
+ print STDERR "fatal: make sure '$url/api.php' is a valid page.\n";
+ exit 1;
+ }
+ while (my ($id, $page) = each (%{$mw_pages->{query}->{pages}})) {
+ if ($id < 0) {
+ print STDERR "Warning: page $page->{title} not found on wiki\n";
+ } else {
+ $pages->{$page->{title}} = $page;
+ }
+ }
+}
+
+sub get_mw_pages {
+ mw_connect_maybe();
+
+ my %pages; # hash on page titles to avoid duplicates
+ my $user_defined;
+ if (@tracked_pages) {
+ $user_defined = 1;
+ # The user provided a list of pages titles, but we
+ # still need to query the API to get the page IDs.
+
+ my @some_pages = @tracked_pages;
+ while (@some_pages) {
+ my $last = 50;
+ if ($#some_pages < $last) {
+ $last = $#some_pages;
+ }
+ my @slice = @some_pages[0..$last];
+ get_mw_first_pages(\@slice, \%pages);
+ @some_pages = @some_pages[51..$#some_pages];
+ }
+ }
+ if (@tracked_categories) {
+ $user_defined = 1;
+ foreach my $category (@tracked_categories) {
+ if (index($category, ':') < 0) {
+ # Mediawiki requires the Category
+ # prefix, but let's not force the user
+ # to specify it.
+ $category = "Category:" . $category;
+ }
+ my $mw_pages = $mediawiki->list ( {
+ action => 'query',
+ list => 'categorymembers',
+ cmtitle => $category,
+ cmlimit => 'max' } )
+ || die $mediawiki->{error}->{code} . ': ' . $mediawiki->{error}->{details};
+ foreach my $page (@{$mw_pages}) {
+ $pages{$page->{title}} = $page;
+ }
+ }
+ }
+ if (!$user_defined) {
+ # No user-provided list, get the list of pages from
+ # the API.
+ my $mw_pages = $mediawiki->list({
+ action => 'query',
+ list => 'allpages',
+ aplimit => 500,
+ });
+ if (!defined($mw_pages)) {
+ print STDERR "fatal: could not get the list of wiki pages.\n";
+ print STDERR "fatal: '$url' does not appear to be a mediawiki\n";
+ print STDERR "fatal: make sure '$url/api.php' is a valid page.\n";
+ exit 1;
+ }
+ foreach my $page (@{$mw_pages}) {
+ $pages{$page->{title}} = $page;
+ }
+ }
+ return values(%pages);
+}
+
+sub run_git {
+ open(my $git, "-|:encoding(UTF-8)", "git " . $_[0]);
+ my $res = do { local $/; <$git> };
+ close($git);
+
+ return $res;
+}
+
+
+sub get_last_local_revision {
+ # Get note regarding last mediawiki revision
+ my $note = run_git("notes --ref=$remotename/mediawiki show refs/mediawiki/$remotename/master 2>/dev/null");
+ my @note_info = split(/ /, $note);
+
+ my $lastrevision_number;
+ if (!(defined($note_info[0]) && $note_info[0] eq "mediawiki_revision:")) {
+ print STDERR "No previous mediawiki revision found";
+ $lastrevision_number = 0;
+ } else {
+ # Notes are formatted : mediawiki_revision: #number
+ $lastrevision_number = $note_info[1];
+ chomp($lastrevision_number);
+ print STDERR "Last local mediawiki revision found is $lastrevision_number";
+ }
+ return $lastrevision_number;
+}
+
+sub get_last_remote_revision {
+ mw_connect_maybe();
+
+ my @pages = get_mw_pages();
+
+ my $max_rev_num = 0;
+
+ foreach my $page (@pages) {
+ my $id = $page->{pageid};
+
+ my $query = {
+ action => 'query',
+ prop => 'revisions',
+ rvprop => 'ids',
+ pageids => $id,
+ };
+
+ my $result = $mediawiki->api($query);
+
+ my $lastrev = pop(@{$result->{query}->{pages}->{$id}->{revisions}});
+
+ $max_rev_num = ($lastrev->{revid} > $max_rev_num ? $lastrev->{revid} : $max_rev_num);
+ }
+
+ print STDERR "Last remote revision found is $max_rev_num.\n";
+ return $max_rev_num;
+}
+
+# Clean content before sending it to MediaWiki
+sub mediawiki_clean {
+ my $string = shift;
+ my $page_created = shift;
+ # 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
+ $string =~ s/\s+$//;
+ if ($string eq "" && $page_created) {
+ # Creating empty pages is forbidden.
+ $string = EMPTY_CONTENT;
+ }
+ return $string."\n";
+}
+
+# Filter applied on MediaWiki data before adding them to Git
+sub mediawiki_smudge {
+ my $string = shift;
+ if ($string eq EMPTY_CONTENT) {
+ $string = "";
+ }
+ # This \n is important. This is due to mediawiki's way to handle end of files.
+ return $string."\n";
+}
+
+sub mediawiki_clean_filename {
+ my $filename = shift;
+ $filename =~ s/@{[SLASH_REPLACEMENT]}/\//g;
+ # [, ], |, {, and } are forbidden by MediaWiki, even URL-encoded.
+ # Do a variant of URL-encoding, i.e. looks like URL-encoding,
+ # but with _ added to prevent MediaWiki from thinking this is
+ # an actual special character.
+ $filename =~ s/[\[\]\{\}\|]/sprintf("_%%_%x", ord($&))/ge;
+ # If we use the uri escape before
+ # we should unescape here, before anything
+
+ return $filename;
+}
+
+sub mediawiki_smudge_filename {
+ my $filename = shift;
+ $filename =~ s/\//@{[SLASH_REPLACEMENT]}/g;
+ $filename =~ s/ /_/g;
+ # Decode forbidden characters encoded in mediawiki_clean_filename
+ $filename =~ s/_%_([0-9a-fA-F][0-9a-fA-F])/sprintf("%c", hex($1))/ge;
+ return $filename;
+}
+
+sub literal_data {
+ my ($content) = @_;
+ print STDOUT "data ", bytes::length($content), "\n", $content;
+}
+
+sub mw_capabilities {
+ # Revisions are imported to the private namespace
+ # refs/mediawiki/$remotename/ by the helper and fetched into
+ # refs/remotes/$remotename later by fetch.
+ print STDOUT "refspec refs/heads/*:refs/mediawiki/$remotename/*\n";
+ print STDOUT "import\n";
+ print STDOUT "list\n";
+ print STDOUT "push\n";
+ print STDOUT "\n";
+}
+
+sub mw_list {
+ # MediaWiki do not have branches, we consider one branch arbitrarily
+ # called master, and HEAD pointing to it.
+ print STDOUT "? refs/heads/master\n";
+ print STDOUT "\@refs/heads/master HEAD\n";
+ print STDOUT "\n";
+}
+
+sub mw_option {
+ print STDERR "remote-helper command 'option $_[0]' not yet implemented\n";
+ print STDOUT "unsupported\n";
+}
+
+sub fetch_mw_revisions_for_page {
+ my $page = shift;
+ my $id = shift;
+ my $fetch_from = shift;
+ my @page_revs = ();
+ my $query = {
+ action => 'query',
+ prop => 'revisions',
+ rvprop => 'ids',
+ rvdir => 'newer',
+ rvstartid => $fetch_from,
+ rvlimit => 500,
+ pageids => $id,
+ };
+
+ my $revnum = 0;
+ # Get 500 revisions at a time due to the mediawiki api limit
+ while (1) {
+ my $result = $mediawiki->api($query);
+
+ # Parse each of those 500 revisions
+ foreach my $revision (@{$result->{query}->{pages}->{$id}->{revisions}}) {
+ my $page_rev_ids;
+ $page_rev_ids->{pageid} = $page->{pageid};
+ $page_rev_ids->{revid} = $revision->{revid};
+ push (@page_revs, $page_rev_ids);
+ $revnum++;
+ }
+ last unless $result->{'query-continue'};
+ $query->{rvstartid} = $result->{'query-continue'}->{revisions}->{rvstartid};
+ }
+ if ($shallow_import && @page_revs) {
+ print STDERR " Found 1 revision (shallow import).\n";
+ @page_revs = sort {$b->{revid} <=> $a->{revid}} (@page_revs);
+ return $page_revs[0];
+ }
+ print STDERR " Found ", $revnum, " revision(s).\n";
+ return @page_revs;
+}
+
+sub fetch_mw_revisions {
+ my $pages = shift; my @pages = @{$pages};
+ my $fetch_from = shift;
+
+ my @revisions = ();
+ my $n = 1;
+ foreach my $page (@pages) {
+ my $id = $page->{pageid};
+
+ print STDERR "page $n/", scalar(@pages), ": ". $page->{title} ."\n";
+ $n++;
+ my @page_revs = fetch_mw_revisions_for_page($page, $id, $fetch_from);
+ @revisions = (@page_revs, @revisions);
+ }
+
+ return ($n, @revisions);
+}
+
+sub import_file_revision {
+ my $commit = shift;
+ my %commit = %{$commit};
+ my $full_import = shift;
+ my $n = shift;
+
+ my $title = $commit{title};
+ my $comment = $commit{comment};
+ my $content = $commit{content};
+ my $author = $commit{author};
+ my $date = $commit{date};
+
+ print STDOUT "commit refs/mediawiki/$remotename/master\n";
+ print STDOUT "mark :$n\n";
+ print STDOUT "committer $author <$author\@$wiki_name> ", $date->epoch, " +0000\n";
+ literal_data($comment);
+
+ # If it's not a clone, we need to know where to start from
+ if (!$full_import && $n == 1) {
+ print STDOUT "from refs/mediawiki/$remotename/master^0\n";
+ }
+ if ($content ne DELETED_CONTENT) {
+ print STDOUT "M 644 inline $title.mw\n";
+ literal_data($content);
+ print STDOUT "\n\n";
+ } else {
+ print STDOUT "D $title.mw\n";
+ }
+
+ # mediawiki revision number in the git note
+ if ($full_import && $n == 1) {
+ print STDOUT "reset refs/notes/$remotename/mediawiki\n";
+ }
+ print STDOUT "commit refs/notes/$remotename/mediawiki\n";
+ print STDOUT "committer $author <$author\@$wiki_name> ", $date->epoch, " +0000\n";
+ literal_data("note added by git-mediawiki");
+ if (!$full_import && $n == 1) {
+ print STDOUT "from refs/notes/$remotename/mediawiki^0\n";
+ }
+ print STDOUT "N inline :$n\n";
+ literal_data("mediawiki_revision: " . $commit{mw_revision});
+ print STDOUT "\n\n";
+}
+
+# parse a sequence of
+# <cmd> <arg1>
+# <cmd> <arg2>
+# \n
+# (like batch sequence of import and sequence of push statements)
+sub get_more_refs {
+ my $cmd = shift;
+ my @refs;
+ while (1) {
+ my $line = <STDIN>;
+ if ($line =~ m/^$cmd (.*)$/) {
+ push(@refs, $1);
+ } elsif ($line eq "\n") {
+ return @refs;
+ } else {
+ die("Invalid command in a '$cmd' batch: ". $_);
+ }
+ }
+}
+
+sub mw_import {
+ # multiple import commands can follow each other.
+ my @refs = (shift, get_more_refs("import"));
+ foreach my $ref (@refs) {
+ mw_import_ref($ref);
+ }
+ print STDOUT "done\n";
+}
+
+sub mw_import_ref {
+ my $ref = shift;
+ # The remote helper will call "import HEAD" and
+ # "import refs/heads/master".
+ # Since HEAD is a symbolic ref to master (by convention,
+ # followed by the output of the command "list" that we gave),
+ # we don't need to do anything in this case.
+ if ($ref eq "HEAD") {
+ return;
+ }
+
+ mw_connect_maybe();
+
+ my @pages = get_mw_pages();
+
+ print STDERR "Searching revisions...\n";
+ my $last_local = get_last_local_revision();
+ my $fetch_from = $last_local + 1;
+ if ($fetch_from == 1) {
+ print STDERR ", fetching from beginning.\n";
+ } else {
+ print STDERR ", fetching from here.\n";
+ }
+ my ($n, @revisions) = fetch_mw_revisions(\@pages, $fetch_from);
+
+ # Creation of the fast-import stream
+ print STDERR "Fetching & writing export data...\n";
+
+ $n = 0;
+ my $last_timestamp = 0; # Placeholer in case $rev->timestamp is undefined
+
+ foreach my $pagerevid (sort {$a->{revid} <=> $b->{revid}} @revisions) {
+ # fetch the content of the pages
+ my $query = {
+ action => 'query',
+ prop => 'revisions',
+ rvprop => 'content|timestamp|comment|user|ids',
+ revids => $pagerevid->{revid},
+ };
+
+ my $result = $mediawiki->api($query);
+
+ my $rev = pop(@{$result->{query}->{pages}->{$pagerevid->{pageid}}->{revisions}});
+
+ $n++;
+
+ my %commit;
+ $commit{author} = $rev->{user} || 'Anonymous';
+ $commit{comment} = $rev->{comment} || '*Empty MediaWiki Message*';
+ $commit{title} = mediawiki_smudge_filename(
+ $result->{query}->{pages}->{$pagerevid->{pageid}}->{title}
+ );
+ $commit{mw_revision} = $pagerevid->{revid};
+ $commit{content} = mediawiki_smudge($rev->{'*'});
+
+ if (!defined($rev->{timestamp})) {
+ $last_timestamp++;
+ } else {
+ $last_timestamp = $rev->{timestamp};
+ }
+ $commit{date} = DateTime::Format::ISO8601->parse_datetime($last_timestamp);
+
+ print STDERR "$n/", scalar(@revisions), ": Revision #$pagerevid->{revid} of $commit{title}\n";
+
+ import_file_revision(\%commit, ($fetch_from == 1), $n);
+ }
+
+ if ($fetch_from == 1 && $n == 0) {
+ print STDERR "You appear to have cloned an empty MediaWiki.\n";
+ # Something has to be done remote-helper side. If nothing is done, an error is
+ # thrown saying that HEAD is refering to unknown object 0000000000000000000
+ # and the clone fails.
+ }
+}
+
+sub error_non_fast_forward {
+ # Native git-push would show this after the summary.
+ # We can't ask it to display it cleanly, so print it
+ # ourselves before.
+ print STDERR "To prevent you from losing history, non-fast-forward updates were rejected\n";
+ print STDERR "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n";
+ print STDERR "'Note about fast-forwards' section of 'git push --help' for details.\n";
+
+ print STDOUT "error $_[0] \"non-fast-forward\"\n";
+ return 0;
+}
+
+sub mw_push_file {
+ my $diff_info = shift;
+ # $diff_info contains a string in this format:
+ # 100644 100644 <sha1_of_blob_before_commit> <sha1_of_blob_now> <status>
+ my @diff_info_split = split(/[ \t]/, $diff_info);
+
+ # Filename, including .mw extension
+ my $complete_file_name = shift;
+ # Commit message
+ my $summary = shift;
+
+ my $new_sha1 = $diff_info_split[3];
+ my $old_sha1 = $diff_info_split[2];
+ my $page_created = ($old_sha1 eq NULL_SHA1);
+ my $page_deleted = ($new_sha1 eq NULL_SHA1);
+ $complete_file_name = mediawiki_clean_filename($complete_file_name);
+
+ if (substr($complete_file_name,-3) eq ".mw"){
+ my $title = substr($complete_file_name,0,-3);
+
+ my $file_content;
+ if ($page_deleted) {
+ # Deleting a page usually requires
+ # special priviledges. A common
+ # convention is to replace the page
+ # with this content instead:
+ $file_content = DELETED_CONTENT;
+ } else {
+ $file_content = run_git("cat-file blob $new_sha1");
+ }
+
+ mw_connect_maybe();
+
+ my $result = $mediawiki->edit( {
+ action => 'edit',
+ summary => $summary,
+ title => $title,
+ text => mediawiki_clean($file_content, $page_created),
+ }, {
+ skip_encoding => 1 # Helps with names with accentuated characters
+ }) || die 'Fatal: Error ' .
+ $mediawiki->{error}->{code} .
+ ' from mediwiki: ' . $mediawiki->{error}->{details};
+ print STDERR "Pushed file : $new_sha1 - $title\n";
+ } else {
+ print STDERR "$complete_file_name not a mediawiki file (Not pushable on this version of git-remote-mediawiki).\n"
+ }
+}
+
+sub mw_push {
+ # multiple push statements can follow each other
+ my @refsspecs = (shift, get_more_refs("push"));
+ my %status;
+ my $pushed;
+ for my $refspec (@refsspecs) {
+ unless ($refspec =~ m/^(\+?)([^:]*):([^:]*)$/) {
+ die("Invalid refspec for push. Expected <src>:<dst> or +<src>:<dst>");
+ }
+ my ($force, $local, $remote) = ($1 eq "+", $2, $3);
+ if ($force) {
+ print STDERR "Warning: forced push not allowed on a MediaWiki.\n";
+ }
+ if ($local eq "") {
+ print STDERR "Cannot delete remote branch on a MediaWiki\n";
+ print STDOUT "error $remote cannot delete\n";
+ next;
+ }
+ if ($remote ne "refs/heads/master") {
+ print STDERR "Only push to the branch 'master' is supported on a MediaWiki\n";
+ print STDOUT "error $remote only master allowed\n";
+ next;
+ }
+ if (mw_push_revision($local, $remote)) {
+ $pushed = 1;
+ }
+ }
+
+ # Notify Git that the push is done
+ print STDOUT "\n";
+
+ if ($pushed) {
+ print STDERR "Just pushed some revisions to MediaWiki.\n";
+ print STDERR "The pushed revisions now have to be re-imported, and your current branch\n";
+ print STDERR "needs to be updated with these re-imported commits. You can do this with\n";
+ print STDERR "\n";
+ print STDERR " git pull --rebase\n";
+ print STDERR "\n";
+ }
+}
+
+sub mw_push_revision {
+ my $local = shift;
+ my $remote = shift; # actually, this has to be "refs/heads/master" at this point.
+ my $last_local_revid = get_last_local_revision();
+ print STDERR ".\n"; # Finish sentence started by 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 $local 2>/dev/null"); chomp($HEAD_sha1);
+ # Get sha1 of commit pointed by remotes/$remotename/master
+ my $remoteorigin_sha1 = run_git("rev-parse refs/remotes/$remotename/master 2>/dev/null");
+ chomp($remoteorigin_sha1);
+
+ if ($last_local_revid > 0 &&
+ $last_local_revid < $last_remote_revid){
+ return error_non_fast_forward($remote);
+ }
+
+ if ($HEAD_sha1 eq $remoteorigin_sha1) {
+ # nothing to push
+ return 0;
+ }
+
+ # Get every commit in between HEAD and refs/remotes/origin/master,
+ # including HEAD and refs/remotes/origin/master
+ my @commit_pairs = ();
+ if ($last_local_revid > 0) {
+ my $parsed_sha1 = $remoteorigin_sha1;
+ # Find a path from last MediaWiki commit to pushed commit
+ while ($parsed_sha1 ne $HEAD_sha1) {
+ my @commit_info = grep(/^$parsed_sha1/, split(/\n/, run_git("rev-list --children $local")));
+ if (!@commit_info) {
+ return error_non_fast_forward($remote);
+ }
+ my @commit_info_split = split(/ |\n/, $commit_info[0]);
+ # $commit_info_split[1] is the sha1 of the commit to export
+ # $commit_info_split[0] is the sha1 of its direct child
+ push (@commit_pairs, \@commit_info_split);
+ $parsed_sha1 = $commit_info_split[1];
+ }
+ } else {
+ # No remote mediawiki revision. Export the whole
+ # history (linearized with --first-parent)
+ print STDERR "Warning: no common ancestor, pushing complete history\n";
+ my $history = run_git("rev-list --first-parent --children $local");
+ my @history = split('\n', $history);
+ @history = @history[1..$#history];
+ foreach my $line (reverse @history) {
+ my @commit_info_split = split(/ |\n/, $line);
+ push (@commit_pairs, \@commit_info_split);
+ }
+ }
+
+ foreach my $commit_info_split (@commit_pairs) {
+ my $sha1_child = @{$commit_info_split}[0];
+ my $sha1_commit = @{$commit_info_split}[1];
+ my $diff_infos = run_git("diff-tree -r --raw -z $sha1_child $sha1_commit");
+ # TODO: we could detect rename, and encode them with a #redirect on the wiki.
+ # TODO: for now, it's just a delete+add
+ my @diff_info_list = split(/\0/, $diff_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\" $sha1_commit")))[0];
+ chomp($commit_msg);
+ # Push every blob
+ while (@diff_info_list) {
+ # git diff-tree -z gives an output like
+ # <metadata>\0<filename1>\0
+ # <metadata>\0<filename2>\0
+ # and we've split on \0.
+ my $info = shift(@diff_info_list);
+ my $file = shift(@diff_info_list);
+ mw_push_file($info, $file, $commit_msg);
+ }
+ }
+
+ print STDOUT "ok $remote\n";
+ return 1;
+}
diff --git a/contrib/mw-to-git/git-remote-mediawiki.txt b/contrib/mw-to-git/git-remote-mediawiki.txt
new file mode 100644
index 0000000..4d211f5
--- /dev/null
+++ b/contrib/mw-to-git/git-remote-mediawiki.txt
@@ -0,0 +1,7 @@
+Git-Mediawiki is a project which aims the creation of a gate
+between git and mediawiki, allowing git users to push and pull
+objects from mediawiki just as one would do with a classic git
+repository thanks to remote-helpers.
+
+For more information, visit the wiki at
+https://github.com/Bibzball/Git-Mediawiki/wiki
--
1.7.7.rc0.78.ge4b5a.dirty
^ permalink raw reply related
* Re: git-svn and mergeinfo
From: Bryan Jacobs @ 2011-08-31 16:55 UTC (permalink / raw)
To: Sverre Rabbelier; +Cc: Eric Wong, git
In-Reply-To: <CAGdFq_h+KjWQUwwLdaqA-0j0p1zQznZkNNEVgfS46_o-Zfr3oQ@mail.gmail.com>
On Wed, 31 Aug 2011 15:59:26 +0200
Sverre Rabbelier <srabbelier@gmail.com> wrote:
>
> Why not submit this as a proper patch [0] to the list, I reckon Eric
> (cc-ed, the maintainer of git-svn) wouldn't mind including it.
I have submitted a patch, following your conventions as best I could. I
forgot the CC line, sorry Eric!
There was an inaccurate line in the documentation concerning the
svn:mergeinfo property ("git-svn does not currently make use of this")
which I clobbered with my documentation change. I did not document the
whole of how "git svn fetch" deals with the property, but this should
probably be done at some point.
Side notes: It may also be productive to automatically set mergeinfo
when all parents of a merge commit have git-svn-info annotations, but I
have not done this (as I said earlier, I use scripts external to git
for this task). Finally, I am uncertain why the git-svn-info lines are
stored in commit bodies instead of as notes; a notes-based approach
would not involve commit hashes changing when they are pushed to an
upstream SVN server.
Thanks all,
Bryan Jacobs
^ permalink raw reply
* Re: Re: need to create new repository initially seeded with several branches
From: Brandon Casey @ 2011-08-31 16:54 UTC (permalink / raw)
To: Git Mailing List
In-Reply-To: <yOArP4qOaF5Yee5Bgcafl_795D9Xnz_IaUH21_GToggoTEy0uLzpGd3OA-rFJt2MlFFYbhvSBNDlv5C_GjSvXfcw7SRn4Ut12giha2cV4yM@cipher.nrlssc.navy.mil>
@Seth Robertson
Your email address seems to be broken. My message to you bounced:
----- The following addresses had permanent fatal errors -----
<in-git-vger@baka.org>
(reason: 550 5.1.1 <in-git-vger@baka.org>... User unknown)
----- Transcript of session follows -----
... while talking to tsutomu.baka.org.:
>>> >>> DATA
<<< 550 5.1.1 <in-git-vger@baka.org>... User unknown
550 5.1.1 <in-git-vger@baka.org>... User unknown
<<< 503 5.0.0 Need RCPT (recipient)
----- Original message follows -----
<snip>
^ permalink raw reply
* Re: need to create new repository initially seeded with several branches
From: Jeff King @ 2011-08-31 16:54 UTC (permalink / raw)
To: Brandon Casey; +Cc: ryan@iridiumsuite.com, git
In-Reply-To: <sDZ5pnWzh3ZbFYS6GK-NcPdn09kF53MJ2eRkBnzInzdL8-cvCiF5beUw2k9Pz6BTq-Y3i_XwpYfgTOvXNlP1vPjLSHJ6FIzxL0jN1W0d0M8@cipher.nrlssc.navy.mil>
On Wed, Aug 31, 2011 at 11:14:48AM -0500, Brandon Casey wrote:
> git checkout -b devel && # make a new branch named "devel"
> # which has the same state as the
> # currently checked out branch: "master"
> # i.e. devel and master point to the
> # same tip commit.
> rm -rf * && # remove the files in the working dir
> cp -a $devel_dir/* . && # cp devel source code to working dir
> git add -A . && # add new/removed files to the index
> # to be committed on next 'git commit'
> git commit
> # use editor to give descriptive commit message
>
> Repeat for your topic branch based off of devel.
I am probably just going to confuse the original poster more, but here
is how I would do it. It's slightly more efficient, as it doesn't
involve removing and copying files for the intermediate states:
# make a repo and switch to it
git init repo && cd repo
# and now add everything from the "master" version, and
# make a commit out of it
GIT_WORK_TREE=/path/to/master git add -A
git commit
# now make the devel branch and do the same
git checkout -b devel
GIT_WORK_TREE=/path/to/devel git add -A
git commit
# and then check out the result in the working tree of
# your newly created repo
git checkout -f
-Peff
^ permalink raw reply
* [PATCH] Teach dcommit --mergeinfo to handle multiple lines
From: Bryan Jacobs @ 2011-08-31 16:48 UTC (permalink / raw)
To: git
"svn dcommit --mergeinfo" replaces the svn:mergeinfo property in an
upstream SVN repository with the given text. The svn:mergeinfo
property may contain commits originating on multiple branches,
separated by newlines.
Cause space characters in the mergeinfo to be replaced by newlines,
allowing a user to create history representing multiple branches being
merged into one.
Update the corresponding documentation and add a test for the new
functionality.
Signed-off-by: Bryan Jacobs <bjacobs@woti.com>
---
Documentation/git-svn.txt | 5 +++--
git-svn.perl | 3 +++
t/t9158-git-svn-mergeinfo.sh | 13 +++++++++++++
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index ed5eca1..3ed28df 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -211,8 +211,9 @@ discouraged.
Add the given merge information during the dcommit
(e.g. `--mergeinfo="/branches/foo:1-10"`). All svn server versions can
store this information (as a property), and svn clients starting from
- version 1.5 can make use of it. 'git svn' currently does not use it
- and does not set it automatically.
+ version 1.5 can make use of it. To specify merge information from multiple
+ branches, use a single space character between the branches
+ (`--mergeinfo="/branches/foo:1-10 /branches/bar:3,5-6,8"`)
'branch'::
Create a branch in the SVN repository.
diff --git a/git-svn.perl b/git-svn.perl
index 89f83fd..3ee26a2 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -548,6 +548,9 @@ sub cmd_dcommit {
}
my $expect_url = $url;
Git::SVN::remove_username($expect_url);
+ if (defined($_merge_info)) {
+ $_merge_info =~ tr{ }{\n};
+ }
while (1) {
my $d = shift @$linear_refs or last;
unless (defined $last_rev) {
diff --git a/t/t9158-git-svn-mergeinfo.sh b/t/t9158-git-svn-mergeinfo.sh
index 3ab4390..8c9539e 100755
--- a/t/t9158-git-svn-mergeinfo.sh
+++ b/t/t9158-git-svn-mergeinfo.sh
@@ -38,4 +38,17 @@ test_expect_success 'verify svn:mergeinfo' '
test "$mergeinfo" = "/branches/foo:1-10"
'
+test_expect_success 'change svn:mergeinfo multiline' '
+ touch baz &&
+ git add baz &&
+ git commit -m "baz" &&
+ git svn dcommit --mergeinfo="/branches/bar:1-10 /branches/other:3-5,8,10-11"
+'
+
+test_expect_success 'verify svn:mergeinfo multiline' '
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/trunk)
+ test "$mergeinfo" = "/branches/bar:1-10
+/branches/other:3-5,8,10-11"
+'
+
test_done
--
1.7.6
^ permalink raw reply related
* [PATCH] git-remote-helpers.txt: explain how import works with multiple refs
From: Matthieu Moy @ 2011-08-31 16:47 UTC (permalink / raw)
To: git, gitster; +Cc: Matthieu Moy
In-Reply-To: <CAGdFq_gooPGQMa5D19-wag=X+mDntHF1MwXiYF0zovB=L-Sybw@mail.gmail.com>
This is important for two reasons:
* when two "import" lines follow each other, only one "done" command
should be issued in the fast-import stream, not one per "import".
* The blank line terminating an import command should not be confused
with the one terminating the sequence of commands.
While we're there, illustrate the corresponding explanation for push
batches with an example.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
Sverre Rabbelier <srabbelier@gmail.com> writes:
> No, a list of 'import' statements has to be followed by a \n, similar
> to the push command. You can have multiple 'blocks' of import/push
> commands, but each block has to be followed by a newline. Again, you
> should read:
>
> import A
> import B
> \n
> import C
> import D
> \n
Thanks for the explanation. This was documented for 'push', but your
illustration made it easier for me to understand, so I've added the
example for push.
The documentation of "batch import" also fixes the "it's not
documented that remote-helpers should use 'done'" as a side-effect.
While investigating all this, I found in git-remote-testgit.py that
the remote-helpers had an "export" functionality, which seems totally
undocumented. Any volunteer to document it?
Documentation/git-remote-helpers.txt | 22 +++++++++++++++++++++-
1 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 760b164..526fc6a 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -241,7 +241,22 @@ Supported if the helper has the "fetch" capability.
'push' +<src>:<dst>::
Pushes the given local <src> commit or branch to the
remote branch described by <dst>. A batch sequence of
- one or more push commands is terminated with a blank line.
+ one or more 'push' commands is terminated with a blank line
+ (if there is only one reference to push, a single 'push' command
+ is followed by a blank line). For example, the following would
+ be two batches of 'push', the first asking the remote-helper
+ to push the local ref 'master' to the remote ref 'master' and
+ the local 'HEAD' to the remote 'branch', and the second
+ asking to push ref 'foo' to ref 'bar' (forced update requested
+ by the '+').
++
+------------
+push refs/heads/master:refs/heads/master
+push HEAD:refs/heads/branch
+\n
+push +refs/heads/foo:refs/heads/bar
+\n
+------------
+
Zero or more protocol options may be entered after the last 'push'
command, before the batch's terminating blank line.
@@ -266,6 +281,11 @@ Supported if the helper has the "push" capability.
Especially useful for interoperability with a foreign versioning
system.
+
+Just like 'push', a batch sequence of one or more 'import' is
+terminated with a blank line. For each batch of 'import', the remote
+helper should produce a fast-import stream terminated by a 'done'
+command.
++
Supported if the helper has the "import" capability.
'connect' <service>::
--
1.7.7.rc0.78.ge4b5a.dirty
^ permalink raw reply related
* [little BUG] pushing to existing branch with remote-helper shows [new branch]
From: Matthieu Moy @ 2011-08-31 16:46 UTC (permalink / raw)
To: git
Hi,
Nothing serious, but I think this is a little bug in transport-helper. I
noticed it working on git-remote-mediawiki, and could reproduce it with
testgit:
/tmp/clone$ git push
To testgit::/tmp/repo
* [new branch] master -> master
/tmp/clone$ date >> foo.txt; git commit -am bar
[master 4438ced] bar
1 files changed, 1 insertions(+), 0 deletions(-)
/tmp/clone$ git push
To testgit::/tmp/repo
* [new branch] master -> master
(/tmp/clone is a clone of testgit::/tmp/repo)
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: Re: need to create new repository initially seeded with several branches
From: Brandon Casey @ 2011-08-31 16:45 UTC (permalink / raw)
To: in-git-vger; +Cc: ryan@iridiumsuite.com, Git Mailing List
In-Reply-To: <201108311624.p7VGOWWq018472@no.baka.org>
On 08/31/2011 11:24 AM, in-git-vger@baka.org wrote:
>
> In message <sDZ5pnWzh3ZbFYS6GK-NcPdn09kF53MJ2eRkBnzInzdL8-cvCiF5beUw2k9Pz6BTq-Y3i_XwpYfgTOvXNlP1vPjLSHJ6FIzxL0jN1W0d0M8@cipher.nrlssc.navy.mil>, Brandon Casey writes:
>
> rm -rf * && # remove the files in the working dir
>
> I just note (for your information only) that this doesn't get rid of
> any . files which might exist. That is the advantage of the
> git-read-tree;git-clean or the `find | xargs rm` alternatives I
> mentioned in my post. 99% of the time it doesn't matter of course,
> since it would only fail on . files which were deleted in the data
> stream you were replacing.
I was just crafting a reply to your message to say the same thing.
Note also that the dot files would not have been copied into the
working directory in the first place, using a command like this:
cp -a /some/path/* .
So, Ryan, if your project contains dot files that you would want
to track, take care that they are actually copied and deleted
with the other files while you are creating your repository.
-Brandon
^ permalink raw reply
* [PATCH 2/2] t6300: test new content:* for-each-ref placeholders
From: Jeff King @ 2011-08-31 16:44 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Michael J Gruber
In-Reply-To: <20110831164233.GA4356@sigill.intra.peff.net>
For commits and unsigned tags, these are the same as %(body)
and %(subject). This patch also introduces a signed tag and
checks for-each-ref's output.
These tests would fit better near the top of the script;
however, creating the extra tag throws off the output of
later tests. Those tests can't just be adjusted to the new
output, either, as the presence of the signed tag depends on
the GPG prerequisite.
Signed-off-by: Jeff King <peff@peff.net>
---
t/lib-gpg.sh | 8 ++++++++
t/t6300-for-each-ref.sh | 44 ++++++++++++++++++++++++++++++++++++++++----
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
index 28463fb..05824fa 100755
--- a/t/lib-gpg.sh
+++ b/t/lib-gpg.sh
@@ -24,3 +24,11 @@ else
;;
esac
fi
+
+sanitize_pgp() {
+ perl -ne '
+ /^-----END PGP/ and $in_pgp = 0;
+ print unless $in_pgp;
+ /^-----BEGIN PGP/ and $in_pgp = 1;
+ '
+}
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 7dc8a51..24f39de 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -6,6 +6,7 @@
test_description='for-each-ref test'
. ./test-lib.sh
+. ../lib-gpg.sh
# Mon Jul 3 15:18:43 2006 +0000
datestamp=1151939923
@@ -35,13 +36,15 @@ test_expect_success 'Create upstream config' '
test_atom() {
case "$1" in
- head) ref=refs/heads/master ;;
- tag) ref=refs/tags/testtag ;;
+ head) ref=refs/heads/master; prereq= ;;
+ tag) ref=refs/tags/testtag; prereq= ;;
+ signed) ref=refs/tags/signed-tag; prereq=GPG ;;
esac
printf '%s\n' "$3" >expected
- test_expect_${4:-success} "basic atom: $1 $2" "
+ test_expect_${4:-success} $prereq "basic atom: $1 $2" "
git for-each-ref --format='%($2)' $ref >actual &&
- test_cmp expected actual
+ sanitize_pgp <actual >actual.clean &&
+ test_cmp expected actual.clean
"
}
@@ -71,7 +74,10 @@ test_atom head taggerdate ''
test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200'
test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200'
test_atom head subject 'Initial'
+test_atom head contents:subject 'Initial'
test_atom head body ''
+test_atom head contents:body ''
+test_atom head contents:signature ''
test_atom head contents 'Initial
'
@@ -101,7 +107,10 @@ test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200'
test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200'
test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200'
test_atom tag subject 'Tagging at 1151939927'
+test_atom tag contents:subject 'Tagging at 1151939927'
test_atom tag body ''
+test_atom tag contents:body ''
+test_atom tag contents:signature ''
test_atom tag contents 'Tagging at 1151939927
'
@@ -359,4 +368,31 @@ test_expect_success 'an unusual tag with an incomplete line' '
'
+test_expect_success GPG 'create signed tag' '
+ cat <<-\EOF |
+ subject line
+
+ body contents
+ EOF
+ git tag -s -F - signed-tag
+'
+
+test_atom signed contents 'subject line
+
+body contents
+-----BEGIN PGP SIGNATURE-----
+-----END PGP SIGNATURE-----
+'
+test_atom signed body 'body contents
+-----BEGIN PGP SIGNATURE-----
+-----END PGP SIGNATURE-----
+'
+test_atom signed contents:body 'body contents
+'
+test_atom signed contents:subject 'subject line'
+test_atom signed subject 'subject line'
+test_atom signed contents:signature '-----BEGIN PGP SIGNATURE-----
+-----END PGP SIGNATURE-----
+'
+
test_done
--
1.7.6.10.g62f04
^ permalink raw reply related
* [PATCH 1/2] t7004: factor out gpg setup
From: Jeff King @ 2011-08-31 16:44 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Michael J Gruber
In-Reply-To: <20110831164233.GA4356@sigill.intra.peff.net>
Other test scripts may want to look at or verify signed
tags, and the setup is non-trivial. Let's factor this out
into lib-gpg.sh for other tests to use.
Signed-off-by: Jeff King <peff@peff.net>
---
t/lib-gpg.sh | 26 ++++++++++++++++++++++++++
t/{t7004 => lib-gpg}/pubring.gpg | Bin 1164 -> 1164 bytes
t/{t7004 => lib-gpg}/random_seed | Bin 600 -> 600 bytes
t/{t7004 => lib-gpg}/secring.gpg | Bin 1237 -> 1237 bytes
t/{t7004 => lib-gpg}/trustdb.gpg | Bin 1280 -> 1280 bytes
t/t7004-tag.sh | 29 +----------------------------
6 files changed, 27 insertions(+), 28 deletions(-)
create mode 100755 t/lib-gpg.sh
rename t/{t7004 => lib-gpg}/pubring.gpg (100%)
rename t/{t7004 => lib-gpg}/random_seed (100%)
rename t/{t7004 => lib-gpg}/secring.gpg (100%)
rename t/{t7004 => lib-gpg}/trustdb.gpg (100%)
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
new file mode 100755
index 0000000..28463fb
--- /dev/null
+++ b/t/lib-gpg.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+gpg_version=`gpg --version 2>&1`
+if test $? = 127; then
+ say "You do not seem to have gpg installed"
+else
+ # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
+ # the gpg version 1.0.6 didn't parse trust packets correctly, so for
+ # that version, creation of signed tags using the generated key fails.
+ case "$gpg_version" in
+ 'gpg (GnuPG) 1.0.6'*)
+ say "Your version of gpg (1.0.6) is too buggy for testing"
+ ;;
+ *)
+ # key generation info: gpg --homedir t/lib-gpg --gen-key
+ # Type DSA and Elgamal, size 2048 bits, no expiration date.
+ # Name and email: C O Mitter <committer@example.com>
+ # No password given, to enable non-interactive operation.
+ cp -R "$TEST_DIRECTORY"/lib-gpg ./gpghome
+ chmod 0700 gpghome
+ GNUPGHOME="$(pwd)/gpghome"
+ export GNUPGHOME
+ test_set_prereq GPG
+ ;;
+ esac
+fi
diff --git a/t/t7004/pubring.gpg b/t/lib-gpg/pubring.gpg
similarity index 100%
rename from t/t7004/pubring.gpg
rename to t/lib-gpg/pubring.gpg
diff --git a/t/t7004/random_seed b/t/lib-gpg/random_seed
similarity index 100%
rename from t/t7004/random_seed
rename to t/lib-gpg/random_seed
diff --git a/t/t7004/secring.gpg b/t/lib-gpg/secring.gpg
similarity index 100%
rename from t/t7004/secring.gpg
rename to t/lib-gpg/secring.gpg
diff --git a/t/t7004/trustdb.gpg b/t/lib-gpg/trustdb.gpg
similarity index 100%
rename from t/t7004/trustdb.gpg
rename to t/lib-gpg/trustdb.gpg
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 097ce2b..5922f43 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -8,6 +8,7 @@ test_description='git tag
Tests for operations with tags.'
. ./test-lib.sh
+. ../lib-gpg.sh
# creating and listing lightweight tags:
@@ -585,24 +586,6 @@ test_expect_success \
test_cmp expect actual
'
-# subsequent tests require gpg; check if it is available
-gpg --version >/dev/null 2>/dev/null
-if [ $? -eq 127 ]; then
- say "# gpg not found - skipping tag signing and verification tests"
-else
- # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
- # the gpg version 1.0.6 didn't parse trust packets correctly, so for
- # that version, creation of signed tags using the generated key fails.
- case "$(gpg --version)" in
- 'gpg (GnuPG) 1.0.6'*)
- say "Skipping signed tag tests, because a bug in 1.0.6 version"
- ;;
- *)
- test_set_prereq GPG
- ;;
- esac
-fi
-
# trying to verify annotated non-signed tags:
test_expect_success GPG \
@@ -625,16 +608,6 @@ test_expect_success GPG \
# creating and verifying signed tags:
-# key generation info: gpg --homedir t/t7004 --gen-key
-# Type DSA and Elgamal, size 2048 bits, no expiration date.
-# Name and email: C O Mitter <committer@example.com>
-# No password given, to enable non-interactive operation.
-
-cp -R "$TEST_DIRECTORY"/t7004 ./gpghome
-chmod 0700 gpghome
-GNUPGHOME="$(pwd)/gpghome"
-export GNUPGHOME
-
get_tag_header signed-tag $commit commit $time >expect
echo 'A signed tag message' >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
--
1.7.6.10.g62f04
^ permalink raw reply related
* Re: [PATCH] for-each-ref: add split message parts to %(contents:*).
From: Jeff King @ 2011-08-31 16:42 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Michael J Gruber
In-Reply-To: <1314781909-19252-1-git-send-email-mgorny@gentoo.org>
On Wed, Aug 31, 2011 at 11:11:49AM +0200, Michał Górny wrote:
> @@ -478,18 +481,20 @@ static void find_subpos(const char *buf, unsigned long sz, const char **sub, con
> buf = strchr(buf, '\n');
> if (!buf) {
> *body = "";
> + *signature = *body;
> return; /* no body */
> }
> while (*buf == '\n')
> buf++; /* skip blank between subject and body */
> *body = buf;
> + *signature = buf + parse_signature(buf, strlen(buf));
Hmm. I had doubts at first that "buf" is guaranteed to be
NUL-terminated, since we are passing around the "sz" parameter (though
note that we also use strchr already). But I think it is OK, as the
buffer comes from read_sha1_file, which defensively NUL-terminates all
objects we get.
Other than that, the patch looks fine. It could use some tests, so I'll
follow up with some:
[1/2]: t7004: factor out gpg setup
[2/2]: t6300: test new content:* for-each-ref placeholders
-Peff
^ permalink raw reply
* Re: need to create new repository initially seeded with several branches
From: in-git-vger @ 2011-08-31 15:40 UTC (permalink / raw)
To: ryan@iridiumsuite.com; +Cc: git
In-Reply-To: <1314804325568-6746957.post@n2.nabble.com>
In message <1314804325568-6746957.post@n2.nabble.com>, "ryan@iridiumsuite.com" writes:
I would like to turn this into a git repository. One branch being master,
the second develop and finally a third branch that is extended off the
develop branch.
I will assume in my instructions that develop is "extended" off of master.
----------------------------------------------------------------------
cd /path/to/new/master
# Make this a git repo
git init
# Add all files to git
git add .
# Commit all files to git
git commit -m "initial master version"
# Make new develop branch
git checkout -b develop
# Cause git to delete all files in the internal index
git read-tree --reset -i 4b825dc642cb6eb9a060e54bf8d69288fbee4904
# Cause git to delete all files in the working directory
git clean -dfx
# Copy all files from the develop directory
cp -r /path/to/new/develop .
# Add all files to git (and delete them too)
git add -A .
# Commit
git commit -m "Initial develop branch"
# Make new extended branch
git checkout -b extended
# Cause git to delete all files in the internal index
git read-tree --reset -i 4b825dc642cb6eb9a060e54bf8d69288fbee4904
# Cause git to delete all files in the working directory
git clean -dfx
# Copy all files from the extended directory
cp -r /path/to/new/extended .
# Add all files to git (and delete them too)
git add -A .
# Commit
git commit -m "Initial develop branch"
----------------------------------------------------------------------
The only "magic" is the read-tree/git-clean stuff. The 4b82⦠value is
the SHA of an empty tree. It could be replaced by a:
find . -maxdepth 1 ! -name '.git' -a ! -name '..' -a ! -name '.' -print0 | xargs -0 rm -rf
But that is 9 extra characters.
Untested, but it should work.
-Seth Robertson
^ permalink raw reply
* Re: need to create new repository initially seeded with several branches
From: in-git-vger @ 2011-08-31 16:21 UTC (permalink / raw)
To: Ryan Wexler; +Cc: git
In-Reply-To: <CAKjsY4nsPNO_kvxeime8qcNrRFykgG2TOYxJ0HKbj2zR5Rwv+Q@mail.gmail.com>
In message <CAKjsY4nsPNO_kvxeime8qcNrRFykgG2TOYxJ0HKbj2zR5Rwv+Q@mail.gmail.com>, Ryan Wexler writes:
> # Cause git to delete all files in the internal index
> git read-tree --reset -i 4b825dc642cb6eb9a060e54bf8d69288fbee4904
> # Cause git to delete all files in the working directory
> git clean -dfx
> The only "magic" is the read-tree/git-clean stuff. The 4b82
> value is the SHA of an empty tree. It could be replaced by
> a:
>
> find . -maxdepth 1 ! -name '.git' -a ! -name '..' -a ! -name '.' -print0 | xargs -0 rm -rf
I have to say that I am lost by the "magic" you describe. I don't
understand what you mean by the 4b82... value should be replaced by
the find | xargs remove all command. That command looks like it just
deletes all the "." file names? But when you say replace I thought
you would mean I need to generate a new value to replace that magic
number?? Confused...
I was just trying to explain what the git-read-tree and git-clean
commands are doing. The long string starting with 4b825d is a special
SHA that git knows represents an empty tree. I was saying that you
*could* (not should) replace the two commands (git-read-tree and
git-clean) with the "find | xargs rm" command I quoted. The two sets
of commands are equivalent.
Also, if you look at the find command, I am finding everything
*except* the .git . and .. directories
-Seth Robertson
^ permalink raw reply
* Re: need to create new repository initially seeded with several branches
From: Brandon Casey @ 2011-08-31 16:14 UTC (permalink / raw)
To: ryan@iridiumsuite.com; +Cc: git
In-Reply-To: <1314804325568-6746957.post@n2.nabble.com>
On 08/31/2011 10:25 AM, ryan@iridiumsuite.com wrote:
> Noobie here...Don't ask why, but I have essentially 3 branches in separate
> code bases on my file system that aren't in a repository right now.
>
> I would like to turn this into a git repository. One branch being master,
> the second develop and finally a third branch that is extended off the
> develop branch.
>
> Is there a way to do this? Could someone give me a step by step? I am
> having a hard enough time just getting use to git and I am lost trying to
> figure this out.
So, you want your repository and dag to look like this:
*------*------*
| | |
master devel topic
but it may help you visualize it to write it like this:
master *
\
devel *
\
topic *
Just be aware that the above two are the same. If you don't understand
that now, then let this plant the seed in your brain of the concept that
branches are merely "pointers" to a state of your repository. Don't
worry, you don't have to understand that now in order to get started
and accomplish what you are trying to do...
First, create your git repository based on the code in the directory
holding what you would like to become the master branch.
Either
cd $path_to_master_code
or
mkdir $my_new_project_directory &&
cd $my_new_project_directory &&
cp -a $path_to_master_code/* .
then
git init &&
git add . &&
git commit -m 'Initial import into git'
Voila, you have your master branch. Now just create your devel
branch and copy your devel code into it and commit.
git checkout -b devel && # make a new branch named "devel"
# which has the same state as the
# currently checked out branch: "master"
# i.e. devel and master point to the
# same tip commit.
rm -rf * && # remove the files in the working dir
cp -a $devel_dir/* . && # cp devel source code to working dir
git add -A . && # add new/removed files to the index
# to be committed on next 'git commit'
git commit
# use editor to give descriptive commit message
Repeat for your topic branch based off of devel.
Please make sure you read the man pages for the above commands and
understand what is going on before you do it, and double-check my
commands.
-Brandon
^ permalink raw reply
* Re: need to create new repository initially seeded with several branches
From: Ryan Wexler @ 2011-08-31 16:10 UTC (permalink / raw)
To: in-git-vger; +Cc: git
In-Reply-To: <201108311540.p7VFen5S015756@no.baka.org>
On Wed, Aug 31, 2011 at 8:40 AM, <in-git-vger@baka.org> wrote:
>
> In message <1314804325568-6746957.post@n2.nabble.com>, "ryan@iridiumsuite.com" writes:
>
> I would like to turn this into a git repository. One branch being master,
> the second develop and finally a third branch that is extended off the
> develop branch.
>
> I will assume in my instructions that develop is "extended" off of master.
>
> ----------------------------------------------------------------------
> cd /path/to/new/master
> # Make this a git repo
> git init
> # Add all files to git
> git add .
> # Commit all files to git
> git commit -m "initial master version"
> # Make new develop branch
> git checkout -b develop
> # Cause git to delete all files in the internal index
> git read-tree --reset -i 4b825dc642cb6eb9a060e54bf8d69288fbee4904
> # Cause git to delete all files in the working directory
> git clean -dfx
> # Copy all files from the develop directory
> cp -r /path/to/new/develop .
> # Add all files to git (and delete them too)
> git add -A .
> # Commit
> git commit -m "Initial develop branch"
> # Make new extended branch
> git checkout -b extended
> # Cause git to delete all files in the internal index
> git read-tree --reset -i 4b825dc642cb6eb9a060e54bf8d69288fbee4904
> # Cause git to delete all files in the working directory
> git clean -dfx
> # Copy all files from the extended directory
> cp -r /path/to/new/extended .
> # Add all files to git (and delete them too)
> git add -A .
> # Commit
> git commit -m "Initial develop branch"
> ----------------------------------------------------------------------
>
> The only "magic" is the read-tree/git-clean stuff. The 4b82… value is
> the SHA of an empty tree. It could be replaced by a:
>
> find . -maxdepth 1 ! -name '.git' -a ! -name '..' -a ! -name '.' -print0 | xargs -0 rm -rf
>
> But that is 9 extra characters.
>
> Untested, but it should work.
>
> -Seth Robertson
>
Seth-
Thanks for the extensive reply. I am excited that this is even possible.
I have to say that I am lost by the "magic" you describe. I don't
understand what you mean by the 4b82... value should be replaced by
the find | xargs remove all command. That command looks like it just
deletes all the "." file names? But when you say replace I thought
you would mean I need to generate a new value to replace that magic
number?? Confused...
^ permalink raw reply
* need to create new repository initially seeded with several branches
From: ryan @ 2011-08-31 15:25 UTC (permalink / raw)
To: git
Noobie here...Don't ask why, but I have essentially 3 branches in separate
code bases on my file system that aren't in a repository right now.
I would like to turn this into a git repository. One branch being master,
the second develop and finally a third branch that is extended off the
develop branch.
Is there a way to do this? Could someone give me a step by step? I am
having a hard enough time just getting use to git and I am lost trying to
figure this out.
thanks so much
--
View this message in context: http://git.661346.n2.nabble.com/need-to-create-new-repository-initially-seeded-with-several-branches-tp6746957p6746957.html
Sent from the git mailing list archive at Nabble.com.
^ permalink raw reply
* Re: Clean termination of remote-helpers (was Re: [PATCH 2/2] Add a remote helper to interact with mediawiki (fetch & push))
From: Sverre Rabbelier @ 2011-08-31 15:00 UTC (permalink / raw)
To: Matthieu Moy
Cc: git, gitster, Jeremie Nikaes, Arnaud Lacurie, Claire Fousse,
David Amouyal
In-Reply-To: <vpqty8x3a5b.fsf@bauges.imag.fr>
Heya,
On Wed, Aug 31, 2011 at 16:53, Matthieu Moy
<Matthieu.Moy@grenoble-inp.fr> wrote:
> So it seems the only bug I've found is insufficient documentation. A
> patch follows.
Yay! Thanks :)
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: Clean termination of remote-helpers (was Re: [PATCH 2/2] Add a remote helper to interact with mediawiki (fetch & push))
From: Matthieu Moy @ 2011-08-31 14:53 UTC (permalink / raw)
To: Sverre Rabbelier
Cc: git, gitster, Jeremie Nikaes, Arnaud Lacurie, Claire Fousse,
David Amouyal
In-Reply-To: <CAGdFq_gSpFm8D1qHs5smUgsqyZXRjw73QFCCkBjTi0n4pwzmHA@mail.gmail.com>
Sverre Rabbelier <srabbelier@gmail.com> writes:
> Heya,
>
> On Wed, Aug 31, 2011 at 14:33, Matthieu Moy
> <Matthieu.Moy@grenoble-inp.fr> wrote:
>> I was expecting this part to be more controversial, so I'm just
>> repeating it to draw more attention ;-).
>
> Eek! :)
>
>> # Inform Git that we're done, otherwise Git won't close it's stdin,
>> # and the next loop will be infinite.
>> close(STDOUT);
>> # Flush stdin before we terminate. If we don't, git fetch
>> # (transport-helper.c's sendline function) will try to write to our
>> # stdin, which may be closed, and git fetch will be killed. That's
>> # probably a bug in transport-helper.c, but in the meantime ...
>> while (<STDIN>) {};
>
> Is this caused by you not reading the terminating '\n' that git sends
> when all commands are done?
Indeed. The stream sent by git looks like
import HEAD
import refs/heads/master
\n <-- this one closes the sequence of import
\n <-- this one closes the sequence of commands.
and I was interpreting it as
import HEAD
import refs/heads/master
\n <-- this one closes the sequence of commands
\n <-- what's this??
So it seems the only bug I've found is insufficient documentation. A
patch follows.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: [PATCH 1/2] am: preliminary support for hg patches
From: Sverre Rabbelier @ 2011-08-31 14:22 UTC (permalink / raw)
To: Giuseppe Bilotta; +Cc: Junio C Hamano, git
In-Reply-To: <7vwrdu3ka0.fsf@alter.siamese.dyndns.org>
Heya,
On Tue, Aug 30, 2011 at 19:02, Junio C Hamano <gitster@pobox.com> wrote:
> These were exactly what I wanted to know. Thanks for experimenting.
And thanks for working on this, Giuseppe!
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: git bug reporting
From: Sverre Rabbelier @ 2011-08-31 14:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Bryan Jacobs, Scott Chacon, git
In-Reply-To: <7vpqjo54my.fsf@alter.siamese.dyndns.org>
Heya,
On Mon, Aug 29, 2011 at 22:44, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>> In the meantime, I've updated:
>> ...
>
> Thanks. I've also made sure that the very first paragraph of "A note fromt
> he maintainer" talks about it (yes it already does).
While we're at it, should we also make sure that these places mention
Documentation/SubmittingPatches?
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: git-svn and mergeinfo
From: Sverre Rabbelier @ 2011-08-31 13:59 UTC (permalink / raw)
To: Bryan Jacobs, Eric Wong; +Cc: git
In-Reply-To: <20110829132052.0ad7a088@robyn.woti.com>
Heya,
On Mon, Aug 29, 2011 at 19:20, Bryan Jacobs <bjacobs@woti.com> wrote:
> Apologies if this is not the right forum for bug reports. I was unable
> to find a Bugzilla/Redmine/Flyspray instance for issue maintenance, nor
> some "proper procedure" on the git web page.
This is indeed the correct way of reporting bugs :).
> However, to make this work with git 1.7.6, I needed to make *one* change
> to the git internals: --merge-info does not allow setting mergeinfo for
> more than one branch. Because it's a complete overwrite operation
> instead of an update, this is a serious issue preventing its use for
> nontrivial branches.
>
> Might I suggest adding a block like the following around line 552 of
> git-svn?
>
> if (defined($_merge_info))
> {
> $_merge_info =~ tr{ }{\n};
> }
>
> This will replace any spaces in --merge-info with newlines, allowing
> specification of an svn:mergeinfo that contains merges from more than a
> singe branch. So the user can provide "--merge-info
> '/branch1:r2323-3849,r8888 /branch2:r9999'" and the like.
Why not submit this as a proper patch [0] to the list, I reckon Eric
(cc-ed, the maintainer of git-svn) wouldn't mind including it.
> Thank you for your consideration. I am not subscribed to this list, so
> if there are any replies, please copy my address.
That's the policy on this list anyway :).
[0] http://git.kernel.org/?p=git/git.git;a=blob;f=Documentation/SubmittingPatches;hb=HEAD
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: Clean termination of remote-helpers (was Re: [PATCH 2/2] Add a remote helper to interact with mediawiki (fetch & push))
From: Sverre Rabbelier @ 2011-08-31 13:25 UTC (permalink / raw)
To: Matthieu Moy
Cc: git, gitster, Jeremie Nikaes, Arnaud Lacurie, Claire Fousse,
David Amouyal
In-Reply-To: <vpqd3flzrow.fsf_-_@bauges.imag.fr>
Heya,
On Wed, Aug 31, 2011 at 14:33, Matthieu Moy
<Matthieu.Moy@grenoble-inp.fr> wrote:
> I was expecting this part to be more controversial, so I'm just
> repeating it to draw more attention ;-).
Eek! :)
> # Inform Git that we're done, otherwise Git won't close it's stdin,
> # and the next loop will be infinite.
> close(STDOUT);
> # Flush stdin before we terminate. If we don't, git fetch
> # (transport-helper.c's sendline function) will try to write to our
> # stdin, which may be closed, and git fetch will be killed. That's
> # probably a bug in transport-helper.c, but in the meantime ...
> while (<STDIN>) {};
Is this caused by you not reading the terminating '\n' that git sends
when all commands are done? We previously didn't do this for imports
(we couldn't, hence the new import/done behavior), so perhaps you just
need to fix that? It's entirely possible you've found a bug though.
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: done feature in remote-helpers (was Re: [PATCH 2/2] Add a remote helper to interact with mediawiki (fetch & push))
From: Sverre Rabbelier @ 2011-08-31 13:16 UTC (permalink / raw)
To: Matthieu Moy
Cc: Junio C Hamano, Jonathan Nieder, git, Jeremie Nikaes,
Arnaud Lacurie, Claire Fousse, David Amouyal
In-Reply-To: <vpq4o0xpvwy.fsf@bauges.imag.fr>
Heya,
On Wed, Aug 31, 2011 at 15:12, Matthieu Moy
<Matthieu.Moy@grenoble-inp.fr> wrote:
> Sverre Rabbelier <srabbelier@gmail.com> writes:
>
>> You can have multiple imports in the current system, you just need to
>> remember to add the trailing newline.
>>
>> import refs/heads/master
>> \n
>> import refs/heads/next
>> \n
>
> Then I'm lost. Isn't \n supposed to mean that the list of commands is
> over, and that the remote-helper should terminate?
No, a list of 'import' statements has to be followed by a \n, similar
to the push command. You can have multiple 'blocks' of import/push
commands, but each block has to be followed by a newline. Again, you
should read:
import A
import B
\n
import C
import D
\n
as:
import
A
B
\n
import
C
D
\n
> Also, who is "you" in your sentence? It can't be the remote helper
> (which reads this sequence), so it has to be Git's transport-helper.
Correct.
> Are you saying that the transport-helper should be modified to add \n
> after sending an import command?
As said above, it already does that. Each group of import statements
is terminated with a \n.
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: done feature in remote-helpers (was Re: [PATCH 2/2] Add a remote helper to interact with mediawiki (fetch & push))
From: Matthieu Moy @ 2011-08-31 13:12 UTC (permalink / raw)
To: Sverre Rabbelier
Cc: Junio C Hamano, Jonathan Nieder, git, Jeremie Nikaes,
Arnaud Lacurie, Claire Fousse, David Amouyal
In-Reply-To: <CAGdFq_hFPBeogpX0Qp8Knfssw8QzV+GwCAyH+zZhM2iEJfFYMw@mail.gmail.com>
Sverre Rabbelier <srabbelier@gmail.com> writes:
> You can have multiple imports in the current system, you just need to
> remember to add the trailing newline.
>
> import refs/heads/master
> \n
> import refs/heads/next
> \n
Then I'm lost. Isn't \n supposed to mean that the list of commands is
over, and that the remote-helper should terminate?
Also, who is "you" in your sentence? It can't be the remote helper
(which reads this sequence), so it has to be Git's transport-helper. Are
you saying that the transport-helper should be modified to add \n after
sending an import command?
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox