* RE: [PATCH v2] fix 'make test' for HP NonStop
From: Joachim Schmitz @ 2012-10-30 9:21 UTC (permalink / raw)
To: 'Jeff King'; +Cc: git
In-Reply-To: <20121029070642.GD5102@sigill.intra.peff.net>
> From: Jeff King [mailto:peff@peff.net]
> Sent: Monday, October 29, 2012 8:07 AM
> To: Joachim Schmitz
> Cc: git@vger.kernel.org
> Subject: Re: [PATCH v2] fix 'make test' for HP NonStop
>
> On Thu, Oct 25, 2012 at 12:57:10PM +0200, Joachim Schmitz wrote:
>
> > diff --git a/Makefile b/Makefile
> > index f69979e..35380dd 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -1381,6 +1381,15 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
> > MKDIR_WO_TRAILING_SLASH = YesPlease
> > # RFE 10-120912-4693 submitted to HP NonStop development.
> > NO_SETITIMER = UnfortunatelyYes
> > +
> > + # for 'make test'
> > + # some test don't work with /bin/diff, some fail with /bin/tar
> > + # some need bash, and some need /usr/local/bin in PATH first
> > + SHELL_PATH=/usr/local/bin/bash
> > + SANE_TOOL_PATH=/usr/local/bin
>
> I think we can drop these comments, as the reasoning really should just
> go in the commit message.
OK by me.
> > + # as of H06.25/J06.14, we might better use this
> > + #SHELL_PATH=/usr/coreutils/bin/bash
> > + #SANE_TOOL_PATH=/usr/coreutils/bin:/usr/local/bin
>
> Is there any reason not to put both into the default SANE_TOOL_PATH? If
> /usr/coreutils/bin does not exist on older versions, it will be a
> harmless no-op. I guess we arestuck with picking one $SHELL_PATH,
> though.
And because of that have to modify something anyway...
But I don't really mind about an extended SANE_TOOL_PATH
> -Peff
Bye, Jojo
-- 8< --
This fixes the vast majority of test failures on HP NonStop.
Some test don't work with /bin/diff, some fail with /bin/tar,
so let's put /usr/local/bin in PATH first.
Some tests fail with /bin/sh (link to /bin/ksh) so use bash instead
Signed-off-by: Joachim Schmitz <jojo@schmitz-digital.de>
---
Makefile | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Makefile b/Makefile
index f69979e..35380dd 100644
--- a/Makefile
+++ b/Makefile
@@ -1381,6 +1381,10 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
MKDIR_WO_TRAILING_SLASH = YesPlease
# RFE 10-120912-4693 submitted to HP NonStop development.
NO_SETITIMER = UnfortunatelyYes
+ SANE_TOOL_PATH=/usr/coreutils/bin:/usr/local/bin
+ SHELL_PATH=/usr/local/bin/bash
+ # as of H06.25/J06.14, we might better use this
+ #SHELL_PATH=/usr/coreutils/bin/bash
endif
ifneq (,$(findstring MINGW,$(uname_S)))
pathsep = ;
^ permalink raw reply related
* Re: Links broken in ref docs.
From: Mike Norman @ 2012-10-30 8:07 UTC (permalink / raw)
To: Kevin; +Cc: Scott Chacon, Andrew Ardill, git
In-Reply-To: <CAO54GHBvWoqZRbDwhQnmjGsBLKfGiv-JTpAakrAjiqEXYHHXPQ@mail.gmail.com>
Not seen any recently. I'm guessing the dev is in the path of
hurricane Sandy? (Not sarcasm, btw.)
On Tue, Oct 30, 2012 at 1:04 AM, Kevin <ikke@ikke.info> wrote:
> Any follow-up on this?
>
> On Tue, Oct 23, 2012 at 7:11 AM, Scott Chacon <schacon@gmail.com> wrote:
>>
>> So, this is due to the major AWS outage today. git-scm.com is hosted
>> on Heroku and thus on AWS. Heroku is continuing to bring up their
>> database systems in the wake of the massive AWS outage. Once that is
>> back online, git-scm.com will also be back online.
>>
>> As for the git-fetch issue, we'll look into it once Heroku is back online.
>>
>> Scott
^ permalink raw reply
* Re: Links broken in ref docs.
From: Kevin @ 2012-10-30 8:04 UTC (permalink / raw)
To: Scott Chacon; +Cc: Mike Norman, Andrew Ardill, git
In-Reply-To: <CAP2yMaKzLHiqpUtfcNtSFo8aqnbvS9RvCzC-DZvQMBgXvte5jw@mail.gmail.com>
Any follow-up on this?
On Tue, Oct 23, 2012 at 7:11 AM, Scott Chacon <schacon@gmail.com> wrote:
>
> So, this is due to the major AWS outage today. git-scm.com is hosted
> on Heroku and thus on AWS. Heroku is continuing to bring up their
> database systems in the wake of the massive AWS outage. Once that is
> back online, git-scm.com will also be back online.
>
> As for the git-fetch issue, we'll look into it once Heroku is back online.
>
> Scott
^ permalink raw reply
* Re: [PATCH] test-lib: avoid full path to store test results
From: Jonathan Nieder @ 2012-10-30 7:01 UTC (permalink / raw)
To: Elia Pinto
Cc: Felipe Contreras, git, Junio C Hamano, Jeff King,
Ævar Arnfjörð Bjarmason, Johannes Sixt
In-Reply-To: <CA+EOSB=Rr8czjVJfA+F6DmHjDUBy0QQ-wd4t-3Uwb1Ksoadr0Q@mail.gmail.com>
Elia Pinto wrote:
> The shell word splitting done in base is a bashism, iow not portable.
No, ${varname##glob} is in POSIX and we already use it here and there.
See Documentation/CodingGuidelines:
- We use ${parameter#word} and its [#%] siblings, and their
doubled "longest matching" form.
Thanks for looking the patch over.
Jonathan
^ permalink raw reply
* Re: [git-users] Git clone fails with "bad pack header", how to get remote log
From: kevin molcard @ 2012-10-30 7:01 UTC (permalink / raw)
To: Konstantin Khomoutov; +Cc: git-users, git
In-Reply-To: <20121029211854.b58c791d30a6c8d68665e574@domain007.com>
Hi Konstantin,
thanks for the reply.
The versions of git are:
- on remote: 1.5.6.5
- on windows build machine: 1.7.11.msysgit.1
- on mac build machine: 1.7.3.4
I will try to install latest git version on my remote server and get
back to you.
thanks again
Kevin
On 10/29/12 6:18 PM, Konstantin Khomoutov wrote:
> On Mon, 29 Oct 2012 09:52:54 -0700 (PDT)
> Kevin Molcard <kev2041@gmail.com> wrote:
>
>> I have a problem with my build system.
>>
>> I have a remote server with a relatively large repository (around 12
>> GB, each branch having a size of 3 GB).
>>
>> I have also 2 build servers (Mac, Windows) that are cloning the repo
>> from the remote.
>>
>> Sometimes (very often when several git clone are sent at the same
>> time), I have the following error:
>>
>> remote: internal server error
>> fatal: protocol error: bad pack header
>>
>> I know that it happens when the remote is compressing objects (thanks
>> to `--progress -v` flags) because the last line of the log before the
>> erro is:
>> remote: Compressing objects: 93% (17959/19284) [K
>>
>> * So I have 2 questions, does anybody what is the problem and what
>> should I do?
>> * Is there a way to get a more precise log from the remote to debug
>> this problem?
> This reminds me of a bug fixed in 1.7.12.1 [1]:
>
> * When "git push" triggered the automatic gc on the receiving end, a
> message from "git prune" that said it was removing cruft leaked to
> the standard output, breaking the communication protocol.
>
> In any case, bugs should be reported to the main Git list (which is
> git at vger.kernel.org), not here.
> I'm Cc'ing the main Git list so you'll get any responses from there, if
> any.
>
> Kevin, please answer to this message (keeping all the Ccs -- use "Reply
> to group" or "Reply to all" in your MUA) and describe exactly what Git
> versions on which platforms your have.
>
> 1. https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.12.1.txt
>
^ permalink raw reply
* Re: [PATCH] test-lib: avoid full path to store test results
From: Elia Pinto @ 2012-10-30 6:58 UTC (permalink / raw)
To: Felipe Contreras, git, Junio C Hamano, Jeff King, Jonathan Nieder,
Ævar Arnfjörð Bjarmason, Johannes Sixt
In-Reply-To: <1351570377-894-1-git-send-email-felipe.contreras@gmail.com>
The shell word splitting done in base is a bashism, iow not portable.
Best
2012/10/30, Felipe Contreras <felipe.contreras@gmail.com>:
> No reason to use the full path in case this is used externally.
>
> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
> ---
> t/test-lib.sh | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/t/test-lib.sh b/t/test-lib.sh
> index 514282c..5a3d665 100644
> --- a/t/test-lib.sh
> +++ b/t/test-lib.sh
> @@ -389,7 +389,8 @@ test_done () {
> then
> test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
> mkdir -p "$test_results_dir"
> - test_results_path="$test_results_dir/${0%.sh}-$$.counts"
> + base=${0##*/}
> + test_results_path="$test_results_dir/${base%.sh}-$$.counts"
>
> cat >>"$test_results_path" <<-EOF
> total $test_count
> --
> 1.8.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Inviato dal mio dispositivo mobile
^ permalink raw reply
* Re: [PATCH v5 12/14] remote-hg: add biridectional tests
From: Felipe Contreras @ 2012-10-30 4:49 UTC (permalink / raw)
To: Junio C Hamano
Cc: Ilari Liusvaara, Sverre Rabbelier, Daniel Barkalow,
Michael J Gruber, Johannes Schindelin, Jeff King, git
In-Reply-To: <CAPc5daUuCsiQd4MoQzQm_aQ6c88b_E8vYfA5btXMW4yCBX8E=g@mail.gmail.com>
On Tue, Oct 30, 2012 at 5:47 AM, Junio C Hamano <gitster@pobox.com> wrote:
> What's the copyright status of the part this borrows from? Is there an
> in-file copyright notice needed to *name* the original author?
>
> The set-up part may become easier to read if done with here document.
>
> Pardon terseness, typo and HTML from a tablet.
I'm the original author. Some chunks are borrowed from the hg-git
project, but they had no copyright, I'll contact them and ask.
Cheers.
--
Felipe Contreras
^ permalink raw reply
* Re: [PATCH] test-lib: avoid full path to store test results
From: Jonathan Nieder @ 2012-10-30 4:46 UTC (permalink / raw)
To: Felipe Contreras
Cc: git, Junio C Hamano, Jeff King,
Ævar Arnfjörð Bjarmason, Johannes Sixt
In-Reply-To: <1351570377-894-1-git-send-email-felipe.contreras@gmail.com>
Hi,
Felipe Contreras wrote:
> No reason to use the full path in case this is used externally.
>
> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
"No reason not to" is not a reason to do anything. What symptoms does
this prevent? Could you describe the benefit of this patch in a
paragraph starting "Now you can ..."?
Thanks,
Jonathan
^ permalink raw reply
* Re: [PATCH] test-lib: avoid full path to store test results
From: Felipe Contreras @ 2012-10-30 4:39 UTC (permalink / raw)
To: Jeff King
Cc: git, Junio C Hamano, Jonathan Nieder,
Ævar Arnfjörð, Johannes Sixt
In-Reply-To: <20121030042850.GA23263@sigill.intra.peff.net>
On Tue, Oct 30, 2012 at 5:28 AM, Jeff King <peff@peff.net> wrote:
> On Tue, Oct 30, 2012 at 05:12:57AM +0100, Felipe Contreras wrote:
>
>> No reason to use the full path in case this is used externally.
>
> I think it is not just "no reason to", but it is actively wrong to use a
> full path, as we do not take care to "mkdir -p" the intervening path
> components.
>
> However, this never comes up in practice, because all of the test
> scripts assume you are running them from the test directory (i.e.,
> they will fail otherwise because they will not find ./test-lib.sh).
>
> Is this in support of putting remote-hg tests in contrib/? I had
> expected you to just put
>
> export TEST_DIRECTORY="$(pwd)/../../../t"
> . "$TEST_DIRECTORY/test-lib.sh"
If there was a single script and we didn't want reports, sure, but
this is not too bad:
TESTS := $(wildcard test*.sh)
export T := $(addprefix $(CURDIR)/,$(TESTS))
export MAKE := $(MAKE) -e
export PATH := $(CURDIR):$(PATH)
test:
$(MAKE) -C ../../t $@
$(TESTS):
$(MAKE) -C ../../t $(CURDIR)/$@
.PHONY: $(TESTS)
I just sent the new remote-hg patch series with that.
Cheers.
--
Felipe Contreras
^ permalink raw reply
* [PATCH v5 13/14] remote-hg: add tests to compare with hg-git
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
The base commands come from the tests of the hg-git project.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/test-hg-git.sh | 460 +++++++++++++++++++++++++++++++++++++++
1 file changed, 460 insertions(+)
create mode 100755 contrib/remote-hg/test-hg-git.sh
diff --git a/contrib/remote-hg/test-hg-git.sh b/contrib/remote-hg/test-hg-git.sh
new file mode 100755
index 0000000..2b7acb0
--- /dev/null
+++ b/contrib/remote-hg/test-hg-git.sh
@@ -0,0 +1,460 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test remote-hg output compared to hg-git'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+ skip_all='skipping remote-hg tests; python not available'
+ test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+ skip_all='skipping remote-hg tests; mercurial not available'
+ test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import hggit'; then
+ skip_all='skipping remote-hg tests; hg-git not available'
+ test_done
+fi
+
+# clone to a git repo with git
+git_clone_git () {
+ hg -R $1 bookmark -f -r tip master &&
+ git clone -q "hg::$PWD/$1" $2
+}
+
+# clone to an hg repo with git
+hg_clone_git () {
+ (
+ hg init $2 &&
+ cd $1 &&
+ git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
+ ) &&
+
+ (cd $2 && hg -q update)
+}
+
+# clone to a git repo with hg
+git_clone_hg () {
+ (
+ git init -q $2 &&
+ cd $1 &&
+ hg bookmark -f -r tip master &&
+ hg -q push -r master ../$2 || true
+ )
+}
+
+# clone to an hg repo with hg
+hg_clone_hg () {
+ hg -q clone $1 $2
+}
+
+# push an hg repo with git
+hg_push_git () {
+ (
+ cd $2
+ old=$(git symbolic-ref --short HEAD)
+ git checkout -q -b tmp &&
+ git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
+ git checkout -q $old &&
+ git branch -q -D tmp 2> /dev/null || true
+ )
+}
+
+# push an hg git repo with hg
+hg_push_hg () {
+ (
+ cd $1 &&
+ hg -q push ../$2 || true
+ )
+}
+
+hg_log () {
+ hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+}
+
+git_log () {
+ git --git-dir=$1/.git fast-export --branches
+}
+
+test_expect_success 'setup' '
+ (
+ echo "[ui]"
+ echo "username = A U Thor <author@example.com>"
+ echo "[defaults]"
+ echo "backout = -d \"0 0\""
+ echo "commit = -d \"0 0\""
+ echo "debugrawcommit = -d \"0 0\""
+ echo "tag = -d \"0 0\""
+ echo "[extensions]"
+ echo "hgext.bookmarks ="
+ echo "hggit ="
+ ) >> "$HOME"/.hgrc &&
+ git config --global receive.denycurrentbranch warn
+ git config --global remote-hg.hg-git-compat true
+
+ export HGEDITOR=/usr/bin/true
+
+ export GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
+ export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+'
+
+test_expect_success 'merge conflict 1' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ hg init hgrepo1 &&
+ cd hgrepo1 &&
+ echo A > afile &&
+ hg add afile &&
+ hg ci -m "origin" &&
+
+ echo B > afile &&
+ hg ci -m "A->B" &&
+
+ hg up -r0 &&
+ echo C > afile &&
+ hg ci -m "A->C" &&
+
+ hg merge -r1 || true &&
+ echo C > afile &&
+ hg resolve -m afile &&
+ hg ci -m "merge to C"
+ ) &&
+
+ for x in hg git; do
+ git_clone_$x hgrepo1 gitrepo-$x &&
+ hg_clone_$x gitrepo-$x hgrepo2-$x &&
+ hg_log hgrepo2-$x > hg-log-$x &&
+ git_log gitrepo-$x > git-log-$x
+ done &&
+
+ test_cmp hg-log-hg hg-log-git &&
+ test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'merge conflict 2' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ hg init hgrepo1 &&
+ cd hgrepo1 &&
+ echo A > afile &&
+ hg add afile &&
+ hg ci -m "origin" &&
+
+ echo B > afile &&
+ hg ci -m "A->B" &&
+
+ hg up -r0 &&
+ echo C > afile &&
+ hg ci -m "A->C" &&
+
+ hg merge -r1 || true &&
+ echo B > afile &&
+ hg resolve -m afile &&
+ hg ci -m "merge to B"
+ ) &&
+
+ for x in hg git; do
+ git_clone_$x hgrepo1 gitrepo-$x &&
+ hg_clone_$x gitrepo-$x hgrepo2-$x &&
+ hg_log hgrepo2-$x > hg-log-$x &&
+ git_log gitrepo-$x > git-log-$x
+ done &&
+
+ test_cmp hg-log-hg hg-log-git &&
+ test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'converged merge' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ hg init hgrepo1 &&
+ cd hgrepo1 &&
+ echo A > afile &&
+ hg add afile &&
+ hg ci -m "origin" &&
+
+ echo B > afile &&
+ hg ci -m "A->B" &&
+
+ echo C > afile &&
+ hg ci -m "B->C" &&
+
+ hg up -r0 &&
+ echo C > afile &&
+ hg ci -m "A->C" &&
+
+ hg merge -r2 || true &&
+ hg ci -m "merge"
+ ) &&
+
+ for x in hg git; do
+ git_clone_$x hgrepo1 gitrepo-$x &&
+ hg_clone_$x gitrepo-$x hgrepo2-$x &&
+ hg_log hgrepo2-$x > hg-log-$x &&
+ git_log gitrepo-$x > git-log-$x
+ done &&
+
+ test_cmp hg-log-hg hg-log-git &&
+ test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'encoding' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add älphà" &&
+
+ export GIT_AUTHOR_NAME="tést èncödîng" &&
+ echo beta > beta &&
+ git add beta &&
+ git commit -m "add beta" &&
+
+ echo gamma > gamma &&
+ git add gamma &&
+ git commit -m "add gämmâ" &&
+
+ : TODO git config i18n.commitencoding latin-1 &&
+ echo delta > delta &&
+ git add delta &&
+ git commit -m "add déltà"
+ ) &&
+
+ for x in hg git; do
+ hg_clone_$x gitrepo hgrepo-$x &&
+ git_clone_$x hgrepo-$x gitrepo2-$x &&
+
+ HGENCODING=utf-8 hg_log hgrepo-$x > hg-log-$x &&
+ git_log gitrepo2-$x > git-log-$x
+ done &&
+
+ test_cmp hg-log-hg hg-log-git &&
+ test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'file removal' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ echo beta > beta &&
+ git add beta &&
+ git commit -m "add beta"
+ mkdir foo &&
+ echo blah > foo/bar &&
+ git add foo &&
+ git commit -m "add foo" &&
+ git rm alpha &&
+ git commit -m "remove alpha" &&
+ git rm foo/bar &&
+ git commit -m "remove foo/bar"
+ ) &&
+
+ for x in hg git; do
+ (
+ hg_clone_$x gitrepo hgrepo-$x &&
+ cd hgrepo-$x &&
+ hg_log . &&
+ hg manifest -r 3 &&
+ hg manifest
+ ) > output-$x &&
+
+ git_clone_$x hgrepo-$x gitrepo2-$x &&
+ git_log gitrepo2-$x > log-$x
+ done &&
+
+ test_cmp output-hg output-git &&
+ test_cmp log-hg log-git
+'
+
+test_expect_success 'git tags' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+ git config receive.denyCurrentBranch ignore &&
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ git tag alpha &&
+
+ echo beta > beta &&
+ git add beta &&
+ git commit -m "add beta" &&
+ git tag -a -m "added tag beta" beta
+ ) &&
+
+ for x in hg git; do
+ hg_clone_$x gitrepo hgrepo-$x &&
+ hg_log hgrepo-$x > log-$x
+ done &&
+
+ test_cmp log-hg log-git
+'
+
+test_expect_success 'hg author' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ for x in hg git; do
+ (
+ git init -q gitrepo-$x &&
+ cd gitrepo-$x &&
+
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ git checkout -q -b not-master
+ ) &&
+
+ (
+ hg_clone_$x gitrepo-$x hgrepo-$x &&
+ cd hgrepo-$x &&
+
+ hg co master &&
+ echo beta > beta &&
+ hg add beta &&
+ hg commit -u "test" -m "add beta" &&
+
+ echo gamma >> beta &&
+ hg commit -u "test <test@example.com> (comment)" -m "modify beta" &&
+
+ echo gamma > gamma &&
+ hg add gamma &&
+ hg commit -u "<test@example.com>" -m "add gamma" &&
+
+ echo delta > delta &&
+ hg add delta &&
+ hg commit -u "name<test@example.com>" -m "add delta" &&
+
+ echo epsilon > epsilon &&
+ hg add epsilon &&
+ hg commit -u "name <test@example.com" -m "add epsilon" &&
+
+ echo zeta > zeta &&
+ hg add zeta &&
+ hg commit -u " test " -m "add zeta" &&
+
+ echo eta > eta &&
+ hg add eta &&
+ hg commit -u "test < test@example.com >" -m "add eta" &&
+
+ echo theta > theta &&
+ hg add theta &&
+ hg commit -u "test >test@example.com>" -m "add theta"
+ ) &&
+
+ hg_push_$x hgrepo-$x gitrepo-$x &&
+ hg_clone_$x gitrepo-$x hgrepo2-$x &&
+
+ hg_log hgrepo2-$x > hg-log-$x &&
+ git_log gitrepo-$x > git-log-$x
+ done &&
+
+ test_cmp git-log-hg git-log-git &&
+
+ test_cmp hg-log-hg hg-log-git &&
+ test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'hg branch' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ for x in hg git; do
+ (
+ git init -q gitrepo-$x &&
+ cd gitrepo-$x &&
+
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -q -m "add alpha" &&
+ git checkout -q -b not-master
+ ) &&
+
+ (
+ hg_clone_$x gitrepo-$x hgrepo-$x &&
+
+ cd hgrepo-$x &&
+ hg -q co master &&
+ hg mv alpha beta &&
+ hg -q commit -m "rename alpha to beta" &&
+ hg branch gamma | grep -v "permanent and global" &&
+ hg -q commit -m "started branch gamma"
+ ) &&
+
+ hg_push_$x hgrepo-$x gitrepo-$x &&
+ hg_clone_$x gitrepo-$x hgrepo2-$x &&
+
+ hg_log hgrepo2-$x > hg-log-$x &&
+ git_log gitrepo-$x > git-log-$x
+ done &&
+
+ test_cmp hg-log-hg hg-log-git &&
+ test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'hg tags' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ for x in hg git; do
+ (
+ git init -q gitrepo-$x &&
+ cd gitrepo-$x &&
+
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ git checkout -q -b not-master
+ ) &&
+
+ (
+ hg_clone_$x gitrepo-$x hgrepo-$x &&
+
+ cd hgrepo-$x &&
+ hg co master &&
+ hg tag alpha
+ ) &&
+
+ hg_push_$x hgrepo-$x gitrepo-$x &&
+ hg_clone_$x gitrepo-$x hgrepo2-$x &&
+
+ (
+ git --git-dir=gitrepo-$x/.git tag -l &&
+ hg_log hgrepo2-$x &&
+ cat hgrepo2-$x/.hgtags
+ ) > output-$x
+ done &&
+
+ test_cmp output-hg output-git
+'
+
+test_done
--
1.8.0
^ permalink raw reply related
* [PATCH v5 14/14] remote-hg: add extra author test
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
For hg.hg.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/test-hg-git.sh | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/contrib/remote-hg/test-hg-git.sh b/contrib/remote-hg/test-hg-git.sh
index 2b7acb0..a9f5cb2 100755
--- a/contrib/remote-hg/test-hg-git.sh
+++ b/contrib/remote-hg/test-hg-git.sh
@@ -368,7 +368,11 @@ test_expect_success 'hg author' '
echo theta > theta &&
hg add theta &&
- hg commit -u "test >test@example.com>" -m "add theta"
+ hg commit -u "test >test@example.com>" -m "add theta" &&
+
+ echo iota > iota &&
+ hg add iota &&
+ hg commit -u "test <test <at> example <dot> com>" -m "add iota"
) &&
hg_push_$x hgrepo-$x gitrepo-$x &&
--
1.8.0
^ permalink raw reply related
* [PATCH v5 12/14] remote-hg: add biridectional tests
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Base commands from hg-git tests:
https://bitbucket.org/durin42/hg-git/src
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/Makefile | 13 +++
contrib/remote-hg/test.sh | 241 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 254 insertions(+)
create mode 100644 contrib/remote-hg/Makefile
create mode 100755 contrib/remote-hg/test.sh
diff --git a/contrib/remote-hg/Makefile b/contrib/remote-hg/Makefile
new file mode 100644
index 0000000..9a76575
--- /dev/null
+++ b/contrib/remote-hg/Makefile
@@ -0,0 +1,13 @@
+TESTS := $(wildcard test*.sh)
+
+export T := $(addprefix $(CURDIR)/,$(TESTS))
+export MAKE := $(MAKE) -e
+export PATH := $(CURDIR):$(PATH)
+
+test:
+ $(MAKE) -C ../../t $@
+
+$(TESTS):
+ $(MAKE) -C ../../t $(CURDIR)/$@
+
+.PHONY: $(TESTS)
diff --git a/contrib/remote-hg/test.sh b/contrib/remote-hg/test.sh
new file mode 100755
index 0000000..4ea2b24
--- /dev/null
+++ b/contrib/remote-hg/test.sh
@@ -0,0 +1,241 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test remote-hg'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+ skip_all='skipping remote-hg tests; python not available'
+ test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+ skip_all='skipping remote-hg tests; mercurial not available'
+ test_done
+fi
+
+# clone to a git repo
+git_clone () {
+ hg -R $1 bookmark -f -r tip master &&
+ git clone -q "hg::$PWD/$1" $2
+}
+
+# clone to an hg repo
+hg_clone () {
+ (
+ hg init $2 &&
+ cd $1 &&
+ git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
+ ) &&
+
+ (cd $2 && hg -q update)
+}
+
+# push an hg repo
+hg_push () {
+ (
+ cd $2
+ old=$(git symbolic-ref --short HEAD)
+ git checkout -q -b tmp &&
+ git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
+ git checkout -q $old &&
+ git branch -q -D tmp 2> /dev/null || true
+ )
+}
+
+hg_log () {
+ hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+}
+
+test_expect_success 'setup' '
+ (
+ echo "[ui]"
+ echo "username = A U Thor <author@example.com>"
+ echo "[defaults]"
+ echo "backout = -d \"0 0\""
+ echo "commit = -d \"0 0\""
+ echo "debugrawcommit = -d \"0 0\""
+ echo "tag = -d \"0 0\""
+ ) >> "$HOME"/.hgrc &&
+ git config --global remote-hg.hg-git-compat true
+
+ export HGEDITOR=/usr/bin/true
+
+ export GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
+ export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+'
+
+test_expect_success 'encoding' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add älphà" &&
+
+ export GIT_AUTHOR_NAME="tést èncödîng" &&
+ echo beta > beta &&
+ git add beta &&
+ git commit -m "add beta" &&
+
+ echo gamma > gamma &&
+ git add gamma &&
+ git commit -m "add gämmâ" &&
+
+ : TODO git config i18n.commitencoding latin-1 &&
+ echo delta > delta &&
+ git add delta &&
+ git commit -m "add déltà"
+ ) &&
+
+ hg_clone gitrepo hgrepo &&
+ git_clone hgrepo gitrepo2 &&
+ hg_clone gitrepo2 hgrepo2 &&
+
+ HGENCODING=utf-8 hg_log hgrepo > expected &&
+ HGENCODING=utf-8 hg_log hgrepo2 > actual &&
+
+ test_cmp expected actual
+'
+
+test_expect_success 'file removal' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ echo beta > beta &&
+ git add beta &&
+ git commit -m "add beta"
+ mkdir foo &&
+ echo blah > foo/bar &&
+ git add foo &&
+ git commit -m "add foo" &&
+ git rm alpha &&
+ git commit -m "remove alpha" &&
+ git rm foo/bar &&
+ git commit -m "remove foo/bar"
+ ) &&
+
+ hg_clone gitrepo hgrepo &&
+ git_clone hgrepo gitrepo2 &&
+ hg_clone gitrepo2 hgrepo2 &&
+
+ hg_log hgrepo > expected &&
+ hg_log hgrepo2 > actual &&
+
+ test_cmp expected actual
+'
+
+test_expect_success 'git tags' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+ git config receive.denyCurrentBranch ignore &&
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ git tag alpha &&
+
+ echo beta > beta &&
+ git add beta &&
+ git commit -m "add beta" &&
+ git tag -a -m "added tag beta" beta
+ ) &&
+
+ hg_clone gitrepo hgrepo &&
+ git_clone hgrepo gitrepo2 &&
+ hg_clone gitrepo2 hgrepo2 &&
+
+ hg_log hgrepo > expected &&
+ hg_log hgrepo2 > actual &&
+
+ test_cmp expected actual
+'
+
+test_expect_success 'hg branch' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -q -m "add alpha" &&
+ git checkout -q -b not-master
+ ) &&
+
+ (
+ hg_clone gitrepo hgrepo &&
+
+ cd hgrepo &&
+ hg -q co master &&
+ hg mv alpha beta &&
+ hg -q commit -m "rename alpha to beta" &&
+ hg branch gamma | grep -v "permanent and global" &&
+ hg -q commit -m "started branch gamma"
+ ) &&
+
+ hg_push hgrepo gitrepo &&
+ hg_clone gitrepo hgrepo2 &&
+
+ : TODO, avoid "master" bookmark &&
+ (cd hgrepo2 && hg checkout gamma) &&
+
+ hg_log hgrepo > expected &&
+ hg_log hgrepo2 > actual &&
+
+ test_cmp expected actual
+'
+
+test_expect_success 'hg tags' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ git init -q gitrepo &&
+ cd gitrepo &&
+
+ echo alpha > alpha &&
+ git add alpha &&
+ git commit -m "add alpha" &&
+ git checkout -q -b not-master
+ ) &&
+
+ (
+ hg_clone gitrepo hgrepo &&
+
+ cd hgrepo &&
+ hg co master &&
+ hg tag alpha
+ ) &&
+
+ hg_push hgrepo gitrepo &&
+ hg_clone gitrepo hgrepo2 &&
+
+ hg_log hgrepo > expected &&
+ hg_log hgrepo2 > actual &&
+
+ test_cmp expected actual
+'
+
+test_done
--
1.8.0
^ permalink raw reply related
* [PATCH v5 10/14] remote-hg: fake bookmark when there's none
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Or at least no current bookmark.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index c2efadf..c41ec95 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -422,12 +422,20 @@ def list_branch_head(repo, cur):
g_head = (head, 'branches', repo[tip])
def list_bookmark_head(repo, cur):
- global g_head
+ global g_head, bmarks
head = bookmarks.readcurrent(repo)
- if not head:
- return
- node = repo[head]
+ if head:
+ node = repo[head]
+ else:
+ # fake bookmark from current branch
+ head = cur
+ tip = get_branch_tip(repo, head)
+ if not tip:
+ return
+ node = repo[tip]
+ bmarks[head] = node
+
print "@refs/heads/%s HEAD" % head
g_head = (head, 'bookmarks', node)
--
1.8.0
^ permalink raw reply related
* [PATCH v5 11/14] remote-hg: add support for fake remote
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Helpful while testing.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index c41ec95..61c1072 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -248,7 +248,13 @@ def get_repo(url, alias):
myui = ui.ui()
myui.setconfig('ui', 'interactive', 'off')
- if hg.islocal(url):
+ if url.startswith("remote://"):
+ remote = True
+ url = "file://%s" % url[9:]
+ else:
+ remote = False
+
+ if hg.islocal(url) and not remote:
repo = hg.repository(myui, url)
else:
local_path = os.path.join(dirname, 'clone')
--
1.8.0
^ permalink raw reply related
* [PATCH v5 09/14] remote-hg: add compat for hg-git author fixes
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 59 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 53 insertions(+), 6 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index e49f9ed..c2efadf 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -17,6 +17,7 @@ import os
import json
import shutil
import subprocess
+import urllib
#
# If you want to switch to hg-git compatibility mode:
@@ -35,6 +36,7 @@ import subprocess
NAME_RE = re.compile('^([^<>]+)')
AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+AUTHOR_HG_RE = re.compile('^(.*?) ?<(.+?)(?:>(.+)?)?$')
RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
def die(msg, *args):
@@ -152,12 +154,20 @@ class Parser:
return sys.stdin.read(size)
def get_author(self):
+ global bad_mail
+
+ ex = None
m = RAW_AUTHOR_RE.match(self.line)
if not m:
return None
_, name, email, date, tz = m.groups()
+ if name and 'ext:' in name:
+ m = re.match('^(.+?) ext:\((.+)\)$', name)
+ if m:
+ name = m.group(1)
+ ex = urllib.unquote(m.group(2))
- if email != 'unknown':
+ if email != bad_mail:
if name:
user = '%s <%s>' % (name, email)
else:
@@ -165,6 +175,9 @@ class Parser:
else:
user = name
+ if ex:
+ user += ex
+
tz = int(tz)
tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
return (user, int(date), -tz)
@@ -180,9 +193,9 @@ def get_filechanges(repo, ctx, parents):
changed, added, removed = [set(sum(e, [])) for e in zip(*l)]
return added | changed, removed
-def fixup_user(user):
- user = user.replace('"', '')
+def fixup_user_git(user):
name = mail = None
+ user = user.replace('"', '')
m = AUTHOR_RE.match(user)
if m:
name = m.group(1)
@@ -191,11 +204,41 @@ def fixup_user(user):
m = NAME_RE.match(user)
if m:
name = m.group(1).strip()
+ return (name, mail)
+
+def fixup_user_hg(user):
+ def sanitize(name):
+ # stole this from hg-git
+ return re.sub('[<>\n]', '?', name.lstrip('< ').rstrip('> '))
+
+ m = AUTHOR_HG_RE.match(user)
+ if m:
+ name = sanitize(m.group(1))
+ mail = sanitize(m.group(2))
+ ex = m.group(3)
+ if ex:
+ name += ' ext:(' + urllib.quote(ex) + ')'
+ else:
+ name = sanitize(user)
+ if '@' in user:
+ mail = name
+ else:
+ mail = None
+
+ return (name, mail)
+
+def fixup_user(user):
+ global mode, bad_mail
+
+ if mode == 'git':
+ name, mail = fixup_user_git(user)
+ else:
+ name, mail = fixup_user_hg(user)
if not name:
- name = 'Unknown'
+ name = bad_name
if not mail:
- mail = 'unknown'
+ mail = bad_mail
return '%s <%s>' % (name, mail)
@@ -649,7 +692,7 @@ def do_export(parser):
def main(args):
global prefix, dirname, branches, bmarks
global marks, blob_marks, parsed_refs
- global peer, mode
+ global peer, mode, bad_mail, bad_name
alias = args[1]
url = args[2]
@@ -665,8 +708,12 @@ def main(args):
if hg_git_compat:
mode = 'hg'
+ bad_mail = 'none@none'
+ bad_name = ''
else:
mode = 'git'
+ bad_mail = 'unknown'
+ bad_name = 'Unknown'
if alias[4:] == url:
is_tmp = True
--
1.8.0
^ permalink raw reply related
* [PATCH v5 08/14] remote-hg: add support for hg-git compat mode
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 102 +++++++++++++++++++++++++++++++++++++---
1 file changed, 95 insertions(+), 7 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index c28f4b4..e49f9ed 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -16,6 +16,22 @@ import sys
import os
import json
import shutil
+import subprocess
+
+#
+# If you want to switch to hg-git compatibility mode:
+# git config --global remote-hg.hg-git-compat true
+#
+# git:
+# Sensible defaults for git.
+# hg bookmarks are exported as git branches, hg branches are prefixed
+# with 'branches/'.
+#
+# hg:
+# Emulate hg-git.
+# Only hg bookmarks are exported as git branches.
+# Commits are modified to preserve hg information and allow biridectionality.
+#
NAME_RE = re.compile('^([^<>]+)')
AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
@@ -212,7 +228,7 @@ def mark_to_rev(mark):
return marks.to_rev(mark)
def export_ref(repo, name, kind, head):
- global prefix, marks
+ global prefix, marks, mode
ename = '%s/%s' % (kind, name)
tip = marks.get_tip(ename)
@@ -247,6 +263,33 @@ def export_ref(repo, name, kind, head):
else:
modified, removed = get_filechanges(repo, c, parents)
+ if mode == 'hg':
+ extra_msg = ''
+
+ if rev_branch != 'default':
+ extra_msg += 'branch : %s\n' % rev_branch
+
+ renames = []
+ for f in c.files():
+ if f not in c.manifest():
+ continue
+ rename = c.filectx(f).renamed()
+ if rename:
+ renames.append((rename[0], f))
+
+ for e in renames:
+ extra_msg += "rename : %s => %s\n" % e
+
+ for key, value in extra.iteritems():
+ if key in ('author', 'committer', 'encoding', 'message', 'branch', 'hg-git'):
+ continue
+ else:
+ extra_msg += "extra : %s : %s\n" % (key, urllib.quote(value))
+
+ desc += '\n'
+ if extra_msg:
+ desc += '\n--HG--\n' + extra_msg
+
if len(parents) == 0 and rev:
print 'reset %s/%s' % (prefix, ename)
@@ -335,8 +378,18 @@ def list_branch_head(repo, cur):
print "@refs/heads/%s HEAD" % head
g_head = (head, 'branches', repo[tip])
+def list_bookmark_head(repo, cur):
+ global g_head
+
+ head = bookmarks.readcurrent(repo)
+ if not head:
+ return
+ node = repo[head]
+ print "@refs/heads/%s HEAD" % head
+ g_head = (head, 'bookmarks', node)
+
def do_list(parser):
- global branches, bmarks
+ global branches, bmarks, mode
repo = parser.repo
for branch in repo.branchmap():
@@ -349,9 +402,13 @@ def do_list(parser):
cur = repo.dirstate.branch()
- list_branch_head(repo, cur)
- for branch in branches:
- print "? refs/heads/branches/%s" % branch
+ if mode != 'hg':
+ list_branch_head(repo, cur)
+ for branch in branches:
+ print "? refs/heads/branches/%s" % branch
+ else:
+ list_bookmark_head(repo, cur)
+
for bmark in bmarks:
print "? refs/heads/%s" % bmark
@@ -417,6 +474,7 @@ def get_merge_files(repo, p1, p2, files):
def parse_commit(parser):
global marks, blob_marks, bmarks, parsed_refs
+ global mode
from_mark = merge_mark = None
@@ -463,7 +521,9 @@ def parse_commit(parser):
return of['ctx']
is_exec = of['mode'] == 'x'
is_link = of['mode'] == 'l'
- return context.memfilectx(f, of['data'], is_link, is_exec, None)
+ rename = of.get('rename', None)
+ return context.memfilectx(f, of['data'],
+ is_link, is_exec, rename)
repo = parser.repo
@@ -490,6 +550,21 @@ def parse_commit(parser):
if merge_mark:
get_merge_files(repo, p1, p2, files)
+ if mode == 'hg':
+ i = data.find('\n--HG--\n')
+ if i >= 0:
+ tmp = data[i + len('\n--HG--\n'):].strip()
+ for k, v in [e.split(' : ') for e in tmp.split('\n')]:
+ if k == 'rename':
+ old, new = v.split(' => ', 1)
+ files[new]['rename'] = old
+ elif k == 'branch':
+ extra[k] = v
+ elif k == 'extra':
+ ek, ev = v.split(' : ', 1)
+ extra[ek] = urllib.unquote(ev)
+ data = data[:i]
+
ctx = context.memctx(repo, (p1, p2), data,
files.keys(), getfilectx,
user, (date, tz), extra)
@@ -574,12 +649,25 @@ def do_export(parser):
def main(args):
global prefix, dirname, branches, bmarks
global marks, blob_marks, parsed_refs
- global peer
+ global peer, mode
alias = args[1]
url = args[2]
peer = None
+ cmd = ['git', 'config', '--get', 'remote-hg.hg-git-compat']
+ hg_git_compat = False
+ try:
+ if subprocess.check_output(cmd) == 'true\n':
+ hg_git_compat = True
+ except subprocess.CalledProcessError:
+ pass
+
+ if hg_git_compat:
+ mode = 'hg'
+ else:
+ mode = 'git'
+
if alias[4:] == url:
is_tmp = True
alias = util.sha1(alias).hexdigest()
--
1.8.0
^ permalink raw reply related
* [PATCH v5 07/14] remote-hg: match hg merge behavior
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index 29824be..c28f4b4 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -409,6 +409,12 @@ def parse_blob(parser):
parser.next()
return
+def get_merge_files(repo, p1, p2, files):
+ for e in repo[p1].files():
+ if e not in files:
+ f = { 'ctx' : repo[p1][e] }
+ files[e] = f
+
def parse_commit(parser):
global marks, blob_marks, bmarks, parsed_refs
@@ -453,6 +459,8 @@ def parse_commit(parser):
of = files[f]
if 'deleted' in of:
raise IOError
+ if 'ctx' in of:
+ return of['ctx']
is_exec = of['mode'] == 'x'
is_link = of['mode'] == 'l'
return context.memfilectx(f, of['data'], is_link, is_exec, None)
@@ -475,6 +483,13 @@ def parse_commit(parser):
else:
p2 = '\0' * 20
+ #
+ # If files changed from any of the parents, hg wants to know, but in git if
+ # nothing changed from the first parent, nothing changed.
+ #
+ if merge_mark:
+ get_merge_files(repo, p1, p2, files)
+
ctx = context.memctx(repo, (p1, p2), data,
files.keys(), getfilectx,
user, (date, tz), extra)
--
1.8.0
^ permalink raw reply related
* [PATCH v5 06/14] remote-hg: make sure the encoding is correct
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Independently of the environment.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index 4d49923..29824be 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -9,7 +9,7 @@
# Then you can clone with:
# git clone hg::/path/to/mercurial/repo/
-from mercurial import hg, ui, bookmarks, context, util
+from mercurial import hg, ui, bookmarks, context, util, encoding
import re
import sys
@@ -373,6 +373,9 @@ def do_import(parser):
print "feature export-marks=%s" % path
sys.stdout.flush()
+ tmp = encoding.encoding
+ encoding.encoding = 'utf-8'
+
# lets get all the import lines
while parser.check('import'):
ref = parser[1]
@@ -391,6 +394,8 @@ def do_import(parser):
parser.next()
+ encoding.encoding = tmp
+
print 'done'
def parse_blob(parser):
@@ -474,8 +479,13 @@ def parse_commit(parser):
files.keys(), getfilectx,
user, (date, tz), extra)
+ tmp = encoding.encoding
+ encoding.encoding = 'utf-8'
+
node = repo.commitctx(ctx)
+ encoding.encoding = tmp
+
rev = repo[node].rev()
parsed_refs[ref] = node
--
1.8.0
^ permalink raw reply related
* [PATCH v5 05/14] remote-hg: add support to push URLs
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index 959ab80..4d49923 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -9,12 +9,13 @@
# Then you can clone with:
# git clone hg::/path/to/mercurial/repo/
-from mercurial import hg, ui, bookmarks, context
+from mercurial import hg, ui, bookmarks, context, util
import re
import sys
import os
import json
+import shutil
NAME_RE = re.compile('^([^<>]+)')
AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
@@ -554,6 +555,12 @@ def main(args):
url = args[2]
peer = None
+ if alias[4:] == url:
+ is_tmp = True
+ alias = util.sha1(alias).hexdigest()
+ else:
+ is_tmp = False
+
gitdir = os.environ['GIT_DIR']
dirname = os.path.join(gitdir, 'hg', alias)
branches = {}
@@ -584,6 +591,9 @@ def main(args):
die('unhandled command: %s' % line)
sys.stdout.flush()
- marks.store()
+ if not is_tmp:
+ marks.store()
+ else:
+ shutil.rmtree(dirname)
sys.exit(main(sys.argv))
--
1.8.0
^ permalink raw reply related
* [PATCH v5 04/14] remote-hg: add support for remote pushing
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index 337ba40..959ab80 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -183,7 +183,7 @@ def fixup_user(user):
return '%s <%s>' % (name, mail)
def get_repo(url, alias):
- global dirname
+ global dirname, peer
myui = ui.ui()
myui.setconfig('ui', 'interactive', 'off')
@@ -511,7 +511,7 @@ def parse_tag(parser):
# nothing to do
def do_export(parser):
- global parsed_refs
+ global parsed_refs, peer
parser.next()
@@ -542,12 +542,17 @@ def do_export(parser):
print
+ if peer:
+ parser.repo.push(peer, force=False)
+
def main(args):
global prefix, dirname, branches, bmarks
global marks, blob_marks, parsed_refs
+ global peer
alias = args[1]
url = args[2]
+ peer = None
gitdir = os.environ['GIT_DIR']
dirname = os.path.join(gitdir, 'hg', alias)
--
1.8.0
^ permalink raw reply related
* [PATCH v5 03/14] remote-hg: add support for pushing
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 215 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 213 insertions(+), 2 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index 9e29daa..337ba40 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -9,7 +9,7 @@
# Then you can clone with:
# git clone hg::/path/to/mercurial/repo/
-from mercurial import hg, ui, bookmarks
+from mercurial import hg, ui, bookmarks, context
import re
import sys
@@ -18,6 +18,7 @@ import json
NAME_RE = re.compile('^([^<>]+)')
AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
def die(msg, *args):
sys.stderr.write('ERROR: %s\n' % (msg % args))
@@ -32,12 +33,17 @@ def gitmode(flags):
def gittz(tz):
return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
+def hgmode(mode):
+ m = { '0100755': 'x', '0120000': 'l' }
+ return m.get(mode, '')
+
class Marks:
def __init__(self, path):
self.path = path
self.tips = {}
self.marks = {}
+ self.rev_marks = {}
self.last_mark = 0
self.load()
@@ -52,6 +58,9 @@ class Marks:
self.marks = tmp['marks']
self.last_mark = tmp['last-mark']
+ for rev, mark in self.marks.iteritems():
+ self.rev_marks[mark] = int(rev)
+
def dict(self):
return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
@@ -64,11 +73,19 @@ class Marks:
def from_rev(self, rev):
return self.marks[str(rev)]
+ def to_rev(self, mark):
+ return self.rev_marks[mark]
+
def next_mark(self, rev):
self.last_mark += 1
self.marks[str(rev)] = self.last_mark
return self.last_mark
+ def new_mark(self, rev, mark):
+ self.marks[str(rev)] = mark
+ self.rev_marks[mark] = rev
+ self.last_mark = mark
+
def is_marked(self, rev):
return self.marks.has_key(str(rev))
@@ -106,6 +123,35 @@ class Parser:
if self.line == 'done':
self.line = None
+ def get_mark(self):
+ i = self.line.index(':') + 1
+ return int(self.line[i:])
+
+ def get_data(self):
+ if not self.check('data'):
+ return None
+ i = self.line.index(' ') + 1
+ size = int(self.line[i:])
+ return sys.stdin.read(size)
+
+ def get_author(self):
+ m = RAW_AUTHOR_RE.match(self.line)
+ if not m:
+ return None
+ _, name, email, date, tz = m.groups()
+
+ if email != 'unknown':
+ if name:
+ user = '%s <%s>' % (name, email)
+ else:
+ user = '<%s>' % (email)
+ else:
+ user = name
+
+ tz = int(tz)
+ tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
+ return (user, int(date), -tz)
+
def export_file(fc):
d = fc.data()
print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
@@ -160,6 +206,10 @@ def rev_to_mark(rev):
global marks
return marks.from_rev(rev)
+def mark_to_rev(mark):
+ global marks
+ return marks.to_rev(mark)
+
def export_ref(repo, name, kind, head):
global prefix, marks
@@ -249,9 +299,17 @@ def do_capabilities(parser):
global prefix, dirname
print "import"
+ print "export"
print "refspec refs/heads/branches/*:%s/branches/*" % prefix
print "refspec refs/heads/*:%s/bookmarks/*" % prefix
print "refspec refs/tags/*:%s/tags/*" % prefix
+
+ path = os.path.join(dirname, 'marks-git')
+
+ if os.path.exists(path):
+ print "*import-marks %s" % path
+ print "*export-marks %s" % path
+
print
def get_branch_tip(repo, branch):
@@ -334,8 +392,159 @@ def do_import(parser):
print 'done'
+def parse_blob(parser):
+ global blob_marks
+
+ parser.next()
+ mark = parser.get_mark()
+ parser.next()
+ data = parser.get_data()
+ blob_marks[mark] = data
+ parser.next()
+ return
+
+def parse_commit(parser):
+ global marks, blob_marks, bmarks, parsed_refs
+
+ from_mark = merge_mark = None
+
+ a = parser.line.split(' ')
+ ref = a[1]
+ parser.next()
+
+ commit_mark = parser.get_mark()
+ parser.next()
+ author = parser.get_author()
+ parser.next()
+ committer = parser.get_author()
+ parser.next()
+ data = parser.get_data()
+ parser.next()
+ if parser.check('from'):
+ from_mark = parser.get_mark()
+ parser.next()
+ if parser.check('merge'):
+ merge_mark = parser.get_mark()
+ parser.next()
+ if parser.check('merge'):
+ die('octopus merges are not supported yet')
+
+ files = {}
+
+ for line in parser:
+ if parser.check('M'):
+ t, m, mark_ref, path = line.split(' ')
+ mark = int(mark_ref[1:])
+ f = { 'mode' : hgmode(m), 'data' : blob_marks[mark] }
+ elif parser.check('D'):
+ t, path = line.split(' ')
+ f = { 'deleted' : True }
+ else:
+ die('Unknown file command: %s' % line)
+ files[path] = f
+
+ def getfilectx(repo, memctx, f):
+ of = files[f]
+ if 'deleted' in of:
+ raise IOError
+ is_exec = of['mode'] == 'x'
+ is_link = of['mode'] == 'l'
+ return context.memfilectx(f, of['data'], is_link, is_exec, None)
+
+ repo = parser.repo
+
+ user, date, tz = author
+ extra = {}
+
+ if committer != author:
+ extra['committer'] = "%s %u %u" % committer
+
+ if from_mark:
+ p1 = repo.changelog.node(mark_to_rev(from_mark))
+ else:
+ p1 = '\0' * 20
+
+ if merge_mark:
+ p2 = repo.changelog.node(mark_to_rev(merge_mark))
+ else:
+ p2 = '\0' * 20
+
+ ctx = context.memctx(repo, (p1, p2), data,
+ files.keys(), getfilectx,
+ user, (date, tz), extra)
+
+ node = repo.commitctx(ctx)
+
+ rev = repo[node].rev()
+
+ parsed_refs[ref] = node
+
+ marks.new_mark(rev, commit_mark)
+
+def parse_reset(parser):
+ a = parser.line.split(' ')
+ ref = a[1]
+ parser.next()
+ # ugh
+ if parser.check('commit'):
+ parse_commit(parser)
+ return
+ if not parser.check('from'):
+ return
+ from_mark = parser.get_mark()
+ parser.next()
+
+ node = parser.repo.changelog.node(mark_to_rev(from_mark))
+ parsed_refs[ref] = node
+
+def parse_tag(parser):
+ a = parser.line.split(' ')
+ name = a[1]
+ parser.next()
+ from_mark = parser.get_mark()
+ parser.next()
+ tagger = parser.get_author()
+ parser.next()
+ data = parser.get_data()
+ parser.next()
+
+ # nothing to do
+
+def do_export(parser):
+ global parsed_refs
+
+ parser.next()
+
+ for line in parser.each_block('done'):
+ if parser.check('blob'):
+ parse_blob(parser)
+ elif parser.check('commit'):
+ parse_commit(parser)
+ elif parser.check('reset'):
+ parse_reset(parser)
+ elif parser.check('tag'):
+ parse_tag(parser)
+ elif parser.check('feature'):
+ pass
+ else:
+ die('unhandled export command: %s' % line)
+
+ for ref, node in parsed_refs.iteritems():
+ if ref.startswith('refs/heads/branches'):
+ pass
+ elif ref.startswith('refs/heads/'):
+ bmark = ref[len('refs/heads/'):]
+ bookmarks.pushbookmark(parser.repo, bmark, '', node)
+ elif ref.startswith('refs/tags/'):
+ tag = ref[len('refs/tags/'):]
+ parser.repo.tag([tag], node, None, True, None, {})
+ print "ok %s" % ref
+
+ print
+
def main(args):
- global prefix, dirname, marks, branches, bmarks
+ global prefix, dirname, branches, bmarks
+ global marks, blob_marks, parsed_refs
alias = args[1]
url = args[2]
@@ -344,6 +553,8 @@ def main(args):
dirname = os.path.join(gitdir, 'hg', alias)
branches = {}
bmarks = {}
+ blob_marks = {}
+ parsed_refs = {}
repo = get_repo(url, alias)
prefix = 'refs/hg/%s' % alias
--
1.8.0
^ permalink raw reply related
* [PATCH v5 01/14] Add new remote-hg transport helper
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 359 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 359 insertions(+)
create mode 100755 contrib/remote-hg/git-remote-hg
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
new file mode 100755
index 0000000..67d39fa
--- /dev/null
+++ b/contrib/remote-hg/git-remote-hg
@@ -0,0 +1,359 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+# Inspired by Rocco Rutte's hg-fast-export
+
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# git clone hg::/path/to/mercurial/repo/
+
+from mercurial import hg, ui
+
+import re
+import sys
+import os
+import json
+
+NAME_RE = re.compile('^([^<>]+)')
+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+
+def die(msg, *args):
+ sys.stderr.write('ERROR: %s\n' % (msg % args))
+ sys.exit(1)
+
+def warn(msg, *args):
+ sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+def gitmode(flags):
+ return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
+
+def gittz(tz):
+ return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
+
+class Marks:
+
+ def __init__(self, path):
+ self.path = path
+ self.tips = {}
+ self.marks = {}
+ self.last_mark = 0
+
+ self.load()
+
+ def load(self):
+ if not os.path.exists(self.path):
+ return
+
+ tmp = json.load(open(self.path))
+
+ self.tips = tmp['tips']
+ self.marks = tmp['marks']
+ self.last_mark = tmp['last-mark']
+
+ def dict(self):
+ return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
+
+ def store(self):
+ json.dump(self.dict(), open(self.path, 'w'))
+
+ def __str__(self):
+ return str(self.dict())
+
+ def from_rev(self, rev):
+ return self.marks[str(rev)]
+
+ def next_mark(self, rev):
+ self.last_mark += 1
+ self.marks[str(rev)] = self.last_mark
+ return self.last_mark
+
+ def is_marked(self, rev):
+ return self.marks.has_key(str(rev))
+
+ def get_tip(self, branch):
+ return self.tips.get(branch, 0)
+
+ def set_tip(self, branch, tip):
+ self.tips[branch] = tip
+
+class Parser:
+
+ def __init__(self, repo):
+ self.repo = repo
+ self.line = self.get_line()
+
+ def get_line(self):
+ return sys.stdin.readline().strip()
+
+ def __getitem__(self, i):
+ return self.line.split()[i]
+
+ def check(self, word):
+ return self.line.startswith(word)
+
+ def each_block(self, separator):
+ while self.line != separator:
+ yield self.line
+ self.line = self.get_line()
+
+ def __iter__(self):
+ return self.each_block('')
+
+ def next(self):
+ self.line = self.get_line()
+ if self.line == 'done':
+ self.line = None
+
+def export_file(fc):
+ d = fc.data()
+ print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
+ print "data %d" % len(d)
+ print d
+
+def get_filechanges(repo, ctx, parents):
+ l = [repo.status(p, ctx)[:3] for p in parents]
+ changed, added, removed = [set(sum(e, [])) for e in zip(*l)]
+ return added | changed, removed
+
+def fixup_user(user):
+ user = user.replace('"', '')
+ name = mail = None
+ m = AUTHOR_RE.match(user)
+ if m:
+ name = m.group(1)
+ mail = m.group(2).strip()
+ else:
+ m = NAME_RE.match(user)
+ if m:
+ name = m.group(1).strip()
+
+ if not name:
+ name = 'Unknown'
+ if not mail:
+ mail = 'unknown'
+
+ return '%s <%s>' % (name, mail)
+
+def get_repo(url, alias):
+ global dirname
+
+ myui = ui.ui()
+ myui.setconfig('ui', 'interactive', 'off')
+
+ if hg.islocal(url):
+ repo = hg.repository(myui, url)
+ else:
+ local_path = os.path.join(dirname, 'clone')
+ if not os.path.exists(local_path):
+ peer, dstpeer = hg.clone(myui, {}, url, local_path, update=False, pull=True)
+ repo = dstpeer.local()
+ else:
+ repo = hg.repository(myui, local_path)
+ peer = hg.peer(myui, {}, url)
+ repo.pull(peer, heads=None, force=True)
+
+ return repo
+
+def rev_to_mark(rev):
+ global marks
+ return marks.from_rev(rev)
+
+def export_ref(repo, name, kind, head):
+ global prefix, marks
+
+ ename = '%s/%s' % (kind, name)
+ tip = marks.get_tip(ename)
+
+ # mercurial takes too much time checking this
+ if tip and tip == head.rev():
+ # nothing to do
+ return
+ revs = repo.revs('%u:%u' % (tip, head))
+ count = 0
+
+ revs = [rev for rev in revs if not marks.is_marked(rev)]
+
+ for rev in revs:
+
+ c = repo[rev]
+ (manifest, user, (time, tz), files, desc, extra) = repo.changelog.read(c.node())
+ rev_branch = extra['branch']
+
+ author = "%s %d %s" % (fixup_user(user), time, gittz(tz))
+ if 'committer' in extra:
+ user, time, tz = extra['committer'].rsplit(' ', 2)
+ committer = "%s %s %s" % (user, time, gittz(int(tz)))
+ else:
+ committer = author
+
+ parents = [p for p in repo.changelog.parentrevs(rev) if p >= 0]
+
+ if len(parents) == 0:
+ modified = c.manifest().keys()
+ removed = []
+ else:
+ modified, removed = get_filechanges(repo, c, parents)
+
+ if len(parents) == 0 and rev:
+ print 'reset %s/%s' % (prefix, ename)
+
+ print "commit %s/%s" % (prefix, ename)
+ print "mark :%d" % (marks.next_mark(rev))
+ print "author %s" % (author)
+ print "committer %s" % (committer)
+ print "data %d" % (len(desc))
+ print desc
+
+ if len(parents) > 0:
+ print "from :%s" % (rev_to_mark(parents[0]))
+ if len(parents) > 1:
+ print "merge :%s" % (rev_to_mark(parents[1]))
+
+ for f in removed:
+ print "D %s" % (f)
+ for f in modified:
+ export_file(c.filectx(f))
+ print
+
+ count += 1
+ if (count % 100 == 0):
+ print "progress revision %d '%s' (%d/%d)" % (rev, name, count, len(revs))
+ print "#############################################################"
+
+ # make sure the ref is updated
+ print "reset %s/%s" % (prefix, ename)
+ print "from :%u" % rev_to_mark(rev)
+ print
+
+ marks.set_tip(ename, rev)
+
+def export_tag(repo, tag):
+ export_ref(repo, tag, 'tags', repo[tag])
+
+def export_branch(repo, branch):
+ tip = get_branch_tip(repo, branch)
+ head = repo[tip]
+ export_ref(repo, branch, 'branches', head)
+
+def export_head(repo):
+ global g_head
+ export_ref(repo, g_head[0], g_head[1], g_head[2])
+
+def do_capabilities(parser):
+ global prefix, dirname
+
+ print "import"
+ print "refspec refs/heads/branches/*:%s/branches/*" % prefix
+ print "refspec refs/tags/*:%s/tags/*" % prefix
+ print
+
+def get_branch_tip(repo, branch):
+ global branches
+
+ heads = branches.get(branch, None)
+ if not heads:
+ return None
+
+ # verify there's only one head
+ if (len(heads) > 1):
+ warn("Branch '%s' has more than one head, consider merging" % branch)
+ return repo.branchtip(branch)
+
+ return heads[0]
+
+def list_branch_head(repo, cur):
+ global g_head
+
+ tip = get_branch_tip(repo, cur)
+ head = 'branches/' + cur
+ print "@refs/heads/%s HEAD" % head
+ g_head = (head, 'branches', repo[tip])
+
+def do_list(parser):
+ global branches
+
+ repo = parser.repo
+ for branch in repo.branchmap():
+ heads = repo.branchheads(branch)
+ if len(heads):
+ branches[branch] = heads
+
+ cur = repo.dirstate.branch()
+
+ list_branch_head(repo, cur)
+ for branch in branches:
+ print "? refs/heads/branches/%s" % branch
+
+ for tag, node in repo.tagslist():
+ if tag == 'tip':
+ continue
+ print "? refs/tags/%s" % tag
+
+ print
+
+def do_import(parser):
+ repo = parser.repo
+
+ path = os.path.join(dirname, 'marks-git')
+
+ print "feature done"
+ if os.path.exists(path):
+ print "feature import-marks=%s" % path
+ print "feature export-marks=%s" % path
+ sys.stdout.flush()
+
+ # lets get all the import lines
+ while parser.check('import'):
+ ref = parser[1]
+
+ if (ref == 'HEAD'):
+ export_head(repo)
+ elif ref.startswith('refs/heads/branches/'):
+ branch = ref[len('refs/heads/branches/'):]
+ export_branch(repo, branch)
+ elif ref.startswith('refs/tags/'):
+ tag = ref[len('refs/tags/'):]
+ export_tag(repo, tag)
+
+ parser.next()
+
+ print 'done'
+
+def main(args):
+ global prefix, dirname, marks, branches
+
+ alias = args[1]
+ url = args[2]
+
+ gitdir = os.environ['GIT_DIR']
+ dirname = os.path.join(gitdir, 'hg', alias)
+ branches = {}
+
+ repo = get_repo(url, alias)
+ prefix = 'refs/hg/%s' % alias
+
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+
+ marks_path = os.path.join(dirname, 'marks-hg')
+ marks = Marks(marks_path)
+
+ parser = Parser(repo)
+ for line in parser:
+ if parser.check('capabilities'):
+ do_capabilities(parser)
+ elif parser.check('list'):
+ do_list(parser)
+ elif parser.check('import'):
+ do_import(parser)
+ elif parser.check('export'):
+ do_export(parser)
+ else:
+ die('unhandled command: %s' % line)
+ sys.stdout.flush()
+
+ marks.store()
+
+sys.exit(main(sys.argv))
--
1.8.0
^ permalink raw reply related
* [PATCH v5 02/14] remote-hg: add support for bookmarks
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
In-Reply-To: <1351571736-4682-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
contrib/remote-hg/git-remote-hg | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
index 67d39fa..9e29daa 100755
--- a/contrib/remote-hg/git-remote-hg
+++ b/contrib/remote-hg/git-remote-hg
@@ -9,7 +9,7 @@
# Then you can clone with:
# git clone hg::/path/to/mercurial/repo/
-from mercurial import hg, ui
+from mercurial import hg, ui, bookmarks
import re
import sys
@@ -232,6 +232,10 @@ def export_ref(repo, name, kind, head):
def export_tag(repo, tag):
export_ref(repo, tag, 'tags', repo[tag])
+def export_bookmark(repo, bmark):
+ head = bmarks[bmark]
+ export_ref(repo, bmark, 'bookmarks', head)
+
def export_branch(repo, branch):
tip = get_branch_tip(repo, branch)
head = repo[tip]
@@ -246,6 +250,7 @@ def do_capabilities(parser):
print "import"
print "refspec refs/heads/branches/*:%s/branches/*" % prefix
+ print "refspec refs/heads/*:%s/bookmarks/*" % prefix
print "refspec refs/tags/*:%s/tags/*" % prefix
print
@@ -272,7 +277,7 @@ def list_branch_head(repo, cur):
g_head = (head, 'branches', repo[tip])
def do_list(parser):
- global branches
+ global branches, bmarks
repo = parser.repo
for branch in repo.branchmap():
@@ -280,11 +285,16 @@ def do_list(parser):
if len(heads):
branches[branch] = heads
+ for bmark, node in bookmarks.listbookmarks(repo).iteritems():
+ bmarks[bmark] = repo[node]
+
cur = repo.dirstate.branch()
list_branch_head(repo, cur)
for branch in branches:
print "? refs/heads/branches/%s" % branch
+ for bmark in bmarks:
+ print "? refs/heads/%s" % bmark
for tag, node in repo.tagslist():
if tag == 'tip':
@@ -313,6 +323,9 @@ def do_import(parser):
elif ref.startswith('refs/heads/branches/'):
branch = ref[len('refs/heads/branches/'):]
export_branch(repo, branch)
+ elif ref.startswith('refs/heads/'):
+ bmark = ref[len('refs/heads/'):]
+ export_bookmark(repo, bmark)
elif ref.startswith('refs/tags/'):
tag = ref[len('refs/tags/'):]
export_tag(repo, tag)
@@ -322,7 +335,7 @@ def do_import(parser):
print 'done'
def main(args):
- global prefix, dirname, marks, branches
+ global prefix, dirname, marks, branches, bmarks
alias = args[1]
url = args[2]
@@ -330,6 +343,7 @@ def main(args):
gitdir = os.environ['GIT_DIR']
dirname = os.path.join(gitdir, 'hg', alias)
branches = {}
+ bmarks = {}
repo = get_repo(url, alias)
prefix = 'refs/hg/%s' % alias
--
1.8.0
^ permalink raw reply related
* [PATCH v5 00/14] New remote-hg helper
From: Felipe Contreras @ 2012-10-30 4:35 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Sverre Rabbelier, Johannes Schindelin,
Ilari Liusvaara, Daniel Barkalow, Jeff King, Michael J Gruber,
Felipe Contreras
Hi,
I've ported the tests from hg-git and made sure that the output from remote-hg
matches the output of hg-git. With these extensive tests I would consider this
one ready for wide use. Not only do the tests pass, I've compared the generated
repos of a few projects, and the SHA-1's are exactly the same :)
This remote-hg has advantages other tools don't have:
* Uses transport-helper (git clone hg::path)
* The code is small
* The code is simple
* No external dependencies (other than mercurial)
* It's easy to install (put into your path)
* Has extensive tests
* Active development
* Has compatibility with hg-git
* The required patches are available
* No changes necesary to git core
One important alternative is the one written by Sverre Rabbelier that is now
maintained and distributed in msysgit. It's hard to evaluate this option as
there isn't a branch specific to this remote helper so it would be possible to
evaluate the necessary patches.
To use it add it to your $PATH (e.g. ~/bin).
% git clone hd:///full/path/or/url/to/hg/repo
To run the tests:
% make -C contrib/remote-hg tests
The only caveat is that you need 'python' in your $PATH.
Changes since v4:
* Add new simple biridectional tests (no need for hg-git)
* Move tests to contrib directory
* Add dependency checks to the tests
* Trivial fixes
Changes since v3:
* New extensive tests
* Add compatibility mode with hg-git
* Added support for boomkars
* Add mercurial information to the git msg (branch, renames, extra, etc.)
Changes since v2:
* Added support for pushing
* Tests copied from original remote-hg
* Custom default -> master renames removed
* Code reorganized
Changes since v1:
* Improved documentation
* Use more common 'python' binary
* Warn, don't barf when a branch has multiple heads
* Fixed marks to fetch after cloned
* Support for cloning/pulling remote repositories
* Use a more appropriate internal directory (e.g. .git/hg/origin)
* Fixes for python3
Felipe Contreras (14):
Add new remote-hg transport helper
remote-hg: add support for bookmarks
remote-hg: add support for pushing
remote-hg: add support for remote pushing
remote-hg: add support to push URLs
remote-hg: make sure the encoding is correct
remote-hg: match hg merge behavior
remote-hg: add support for hg-git compat mode
remote-hg: add compat for hg-git author fixes
remote-hg: fake bookmark when there's none
remote-hg: add support for fake remote
remote-hg: add biridectional tests
remote-hg: add tests to compare with hg-git
remote-hg: add extra author test
contrib/remote-hg/Makefile | 13 +
contrib/remote-hg/git-remote-hg | 773 +++++++++++++++++++++++++++++++++++++++
contrib/remote-hg/test-hg-git.sh | 464 +++++++++++++++++++++++
contrib/remote-hg/test.sh | 241 ++++++++++++
4 files changed, 1491 insertions(+)
create mode 100644 contrib/remote-hg/Makefile
create mode 100755 contrib/remote-hg/git-remote-hg
create mode 100755 contrib/remote-hg/test-hg-git.sh
create mode 100755 contrib/remote-hg/test.sh
--
1.8.0
^ permalink raw reply
* Re: [PATCH] test-lib: avoid full path to store test results
From: Jeff King @ 2012-10-30 4:28 UTC (permalink / raw)
To: Felipe Contreras
Cc: git, Junio C Hamano, Jonathan Nieder,
Ævar Arnfjörð Bjarmason, Johannes Sixt
In-Reply-To: <1351570377-894-1-git-send-email-felipe.contreras@gmail.com>
On Tue, Oct 30, 2012 at 05:12:57AM +0100, Felipe Contreras wrote:
> No reason to use the full path in case this is used externally.
I think it is not just "no reason to", but it is actively wrong to use a
full path, as we do not take care to "mkdir -p" the intervening path
components.
However, this never comes up in practice, because all of the test
scripts assume you are running them from the test directory (i.e.,
they will fail otherwise because they will not find ./test-lib.sh).
Is this in support of putting remote-hg tests in contrib/? I had
expected you to just put
export TEST_DIRECTORY="$(pwd)/../../../t"
. "$TEST_DIRECTORY/test-lib.sh"
into the test script in contrib/remote-hg/t. I guess you are doing
something like:
cd ../../../t && ../contrib/remote-hg/t/twhatever...
but the former seems much simpler to invoke (and if the goal is to get
your test-results in the right place, setting TEST_OUTPUT_DIRECTORY is
the best way to do that).
If this is part of the remote-hg series, I'd prefer to just see it as
part of the re-roll. It's much easier to evaluate it in context.
Or are you really just doing:
cd git/t
$PWD/t0000-basic.sh
I guess there is nothing wrong with that, though there is no reason not
to use "./" instead of $PWD.
-Peff
^ 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