From 5d3698ffb4ccf8b842814559007e011fc409650b Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Sat, 24 Nov 2012 04:17:01 +0100 Subject: [PATCH 01/15] fast-export: avoid importing blob marks We want to be able to import, and then export, using the same marks, so that we don't push things that the other side already received. Unfortunately, fast-export doesn't store blobs in the marks, but fast-import does. This creates a mismatch when fast export is reusing a mark that was previously stored by fast-import. There is no point in one tool saving blobs, and the other not, but for now let's just check in fast-export that the objects are indeed commits. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- builtin/fast-export.c | 4 ++++ t/t9350-fast-export.sh | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 12220ad8da..9b70ec1fcf 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -614,6 +614,10 @@ static void import_marks(char *input_file) if (object->flags & SHOWN) error("Object %s already has a mark", sha1_to_hex(sha1)); + if (object->type != OBJ_COMMIT) + /* only commits */ + continue; + mark_object(object, mark); if (last_idnum < mark) last_idnum = mark; diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 3e821f958b..5948b65f21 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -440,4 +440,18 @@ test_expect_success 'fast-export quotes pathnames' ' ) ' +test_expect_success 'test bidirectionality' ' + >marks-cur && + >marks-new && + git init marks-test && + git fast-export --export-marks=marks-cur --import-marks=marks-cur --branches | \ + git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks=marks-new && + (cd marks-test && + git reset --hard && + echo Wohlauf > file && + git commit -a -m "back in time") && + git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks=marks-new --branches | \ + git fast-import --export-marks=marks-cur --import-marks=marks-cur +' + test_done From 3b705268f54af35146d0b0f0562b8598521b8ced Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Sat, 24 Nov 2012 04:17:02 +0100 Subject: [PATCH 02/15] remote-testgit: fix direction of marks Basically this is what we want: == pull == testgit transport-helper * export -> import # testgit.marks git.marks == push == testgit transport-helper * import <- export # testgit.marks git.marks Each side should be agnostic of the other side. Because testgit.marks (our helper marks) could be anything, not necessarily a format parsable by fast-export or fast-import. In this test they happen to be compatible, because we use those tools, but in the real world it would be something completely different. For example, they might be mapping marks to mercurial revisions (certainly not parsable by fast-import/export). This is what we have: == pull == testgit transport-helper * export -> import # testgit.marks git.marks == push == testgit transport-helper * import <- export # git.marks testgit.marks The only reason this is working is that git.marks and testgit.marks are roughly the same. This new behavior used to not be possible before due to a bug in fast-export, but with the bug fixed, it works fine. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- git-remote-testgit.py | 2 +- git_remote_helpers/git/importer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git-remote-testgit.py b/git-remote-testgit.py index 5f3ebd244d..ade797bbb0 100644 --- a/git-remote-testgit.py +++ b/git-remote-testgit.py @@ -91,7 +91,7 @@ def do_capabilities(repo, args): if not os.path.exists(dirname): os.makedirs(dirname) - path = os.path.join(dirname, 'testgit.marks') + path = os.path.join(dirname, 'git.marks') print "*export-marks %s" % path if os.path.exists(path): diff --git a/git_remote_helpers/git/importer.py b/git_remote_helpers/git/importer.py index 5c6b595e16..e28cc8f986 100644 --- a/git_remote_helpers/git/importer.py +++ b/git_remote_helpers/git/importer.py @@ -39,7 +39,7 @@ class GitImporter(object): gitdir = self.repo.gitpath else: gitdir = os.path.abspath(os.path.join(dirname, '.git')) - path = os.path.abspath(os.path.join(dirname, 'git.marks')) + path = os.path.abspath(os.path.join(dirname, 'testgit.marks')) if not os.path.exists(dirname): os.makedirs(dirname) From 24a1ea5360faef3c6b742e15a72825877c57eb28 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Sat, 24 Nov 2012 04:17:03 +0100 Subject: [PATCH 03/15] remote-helpers: fix failure message This is remote-testgit, not remote-hg. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- t/t5800-remote-helpers.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh index e7dc668cef..d46fa406f3 100755 --- a/t/t5800-remote-helpers.sh +++ b/t/t5800-remote-helpers.sh @@ -8,7 +8,7 @@ test_description='Test remote-helper import and export commands' . ./test-lib.sh if ! test_have_prereq PYTHON ; then - skip_all='skipping git-remote-hg tests, python not available' + skip_all='skipping remote-testgit tests, python not available' test_done fi @@ -17,7 +17,7 @@ import sys if sys.hexversion < 0x02040000: sys.exit(1) ' || { - skip_all='skipping git-remote-hg tests, python version < 2.4' + skip_all='skipping remote-testgit tests, python version < 2.4' test_done } From d0ac3ffd9da8d1c3e629129030f74e1927faf575 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:00 +0100 Subject: [PATCH 04/15] Rename git-remote-testgit to git-remote-testpy This script is not really exercising the remote-helper functionality, but more the python framework for remote helpers that live in git_remote_helpers. It's also not a good example of how to write remote-helpers, unless you are planning to use python, and even then you might not want to use this framework. So let's use a more appropriate name: git-remote-testpy. A patch that replaces git-remote-testgit with a simpler version is on the way. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- .gitignore | 2 +- Makefile | 2 +- git-remote-testgit.py => git-remote-testpy.py | 0 ...00-remote-helpers.sh => t5800-remote-testpy.sh} | 14 +++++++------- 4 files changed, 9 insertions(+), 9 deletions(-) rename git-remote-testgit.py => git-remote-testpy.py (100%) rename t/{t5800-remote-helpers.sh => t5800-remote-testpy.sh} (87%) diff --git a/.gitignore b/.gitignore index f702415c12..956ae2260d 100644 --- a/.gitignore +++ b/.gitignore @@ -124,7 +124,7 @@ /git-remote-ftps /git-remote-fd /git-remote-ext -/git-remote-testgit +/git-remote-testpy /git-remote-testsvn /git-repack /git-replace diff --git a/Makefile b/Makefile index 9bc5e40365..68f1ac288b 100644 --- a/Makefile +++ b/Makefile @@ -470,7 +470,7 @@ SCRIPT_PERL += git-relink.perl SCRIPT_PERL += git-send-email.perl SCRIPT_PERL += git-svn.perl -SCRIPT_PYTHON += git-remote-testgit.py +SCRIPT_PYTHON += git-remote-testpy.py SCRIPT_PYTHON += git-p4.py SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ diff --git a/git-remote-testgit.py b/git-remote-testpy.py similarity index 100% rename from git-remote-testgit.py rename to git-remote-testpy.py diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-testpy.sh similarity index 87% rename from t/t5800-remote-helpers.sh rename to t/t5800-remote-testpy.sh index d46fa406f3..6750961507 100755 --- a/t/t5800-remote-helpers.sh +++ b/t/t5800-remote-testpy.sh @@ -3,12 +3,12 @@ # Copyright (c) 2010 Sverre Rabbelier # -test_description='Test remote-helper import and export commands' +test_description='Test python remote-helper framework' . ./test-lib.sh if ! test_have_prereq PYTHON ; then - skip_all='skipping remote-testgit tests, python not available' + skip_all='skipping python remote-helper tests, python not available' test_done fi @@ -17,7 +17,7 @@ import sys if sys.hexversion < 0x02040000: sys.exit(1) ' || { - skip_all='skipping remote-testgit tests, python version < 2.4' + skip_all='skipping python remote-helper tests, python version < 2.4' test_done } @@ -38,12 +38,12 @@ test_expect_success 'setup repository' ' ' test_expect_success 'cloning from local repo' ' - git clone "testgit::${PWD}/server" localclone && + git clone "testpy::${PWD}/server" localclone && test_cmp public/file localclone/file ' test_expect_success 'cloning from remote repo' ' - git clone "testgit::file://${PWD}/server" clone && + git clone "testpy::file://${PWD}/server" clone && test_cmp public/file clone/file ' @@ -73,11 +73,11 @@ test_expect_success 'pushing to local repo' ' ' # Generally, skip this test. It demonstrates a now-fixed race in -# git-remote-testgit, but is too slow to leave in for general use. +# git-remote-testpy, but is too slow to leave in for general use. : test_expect_success 'racily pushing to local repo' ' test_when_finished "rm -rf server2 localclone2" && cp -R server server2 && - git clone "testgit::${PWD}/server2" localclone2 && + git clone "testpy::${PWD}/server2" localclone2 && (cd localclone2 && echo content >>file && git commit -a -m three && From fc407f9821840041757975045c4a1ca01effa27a Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:01 +0100 Subject: [PATCH 05/15] Add new simplified git-remote-testgit Exercising the python remote helper framework is for another tool and another test. This is about testing the remote-helper interface. It's way simpler, it exercises the same features of remote helpers, it's easy to read and understand, and it doesn't depend on python. For now let's just copy the old remote-helpers test script, although some of those tests don't make sense. In addition, this script would be able to test other features not currently being tested. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- Documentation/git-remote-testgit.txt | 2 +- git-remote-testgit | 64 ++++++++++++ t/t5801-remote-helpers.sh | 139 +++++++++++++++++++++++++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100755 git-remote-testgit create mode 100755 t/t5801-remote-helpers.sh diff --git a/Documentation/git-remote-testgit.txt b/Documentation/git-remote-testgit.txt index 2a67d456a3..612a625ced 100644 --- a/Documentation/git-remote-testgit.txt +++ b/Documentation/git-remote-testgit.txt @@ -19,7 +19,7 @@ testcase for the remote-helper functionality, and as an example to show remote-helper authors one possible implementation. The best way to learn more is to read the comments and source code in -'git-remote-testgit.py'. +'git-remote-testgit'. SEE ALSO -------- diff --git a/git-remote-testgit b/git-remote-testgit new file mode 100755 index 0000000000..5042f5a11f --- /dev/null +++ b/git-remote-testgit @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# Copyright (c) 2012 Felipe Contreras + +alias=$1 +url=$2 + +# huh? +url="${url#file://}" + +dir="$GIT_DIR/testgit/$alias" +prefix="refs/testgit/$alias" +refspec="refs/heads/*:${prefix}/heads/*" + +gitmarks="$dir/git.marks" +testgitmarks="$dir/testgit.marks" + +export GIT_DIR="$url/.git" + +mkdir -p "$dir" + +test -e "$gitmarks" || > "$gitmarks" +test -e "$testgitmarks" || > "$testgitmarks" + +while read line +do + case $line in + capabilities) + echo 'import' + echo 'export' + echo "refspec $refspec" + echo "*import-marks $gitmarks" + echo "*export-marks $gitmarks" + echo + ;; + list) + git for-each-ref --format='? %(refname)' 'refs/heads/' + head=$(git symbolic-ref HEAD) + echo "@$head HEAD" + echo + ;; + import*) + # read all import lines + while true + do + ref="${line#* }" + refs="$refs $ref" + read line + test "${line%% *}" != "import" && break + done + + echo "feature import-marks=$gitmarks" + echo "feature export-marks=$gitmarks" + git fast-export --use-done-feature --{import,export}-marks="$testgitmarks" $refs | + sed -e "s#refs/heads/#${prefix}/heads/#g" + ;; + export) + git fast-import --{import,export}-marks="$testgitmarks" --quiet + echo + ;; + '') + exit + ;; + esac +done diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh new file mode 100755 index 0000000000..f52ab1466b --- /dev/null +++ b/t/t5801-remote-helpers.sh @@ -0,0 +1,139 @@ +#!/bin/sh +# +# Copyright (c) 2010 Sverre Rabbelier +# + +test_description='Test remote-helper import and export commands' + +. ./test-lib.sh + +if ! type "${BASH-bash}" >/dev/null 2>&1; then + skip_all='skipping remote-testgit tests, bash not available' + test_done +fi + +compare_refs() { + git --git-dir="$1/.git" rev-parse --verify $2 >expect && + git --git-dir="$3/.git" rev-parse --verify $4 >actual && + test_cmp expect actual +} + +test_expect_success 'setup repository' ' + git init --bare server/.git && + git clone server public && + (cd public && + echo content >file && + git add file && + git commit -m one && + git push origin master) +' + +test_expect_success 'cloning from local repo' ' + git clone "testgit::${PWD}/server" localclone && + test_cmp public/file localclone/file +' + +test_expect_success 'cloning from remote repo' ' + git clone "testgit::file://${PWD}/server" clone && + test_cmp public/file clone/file +' + +test_expect_success 'create new commit on remote' ' + (cd public && + echo content >>file && + git commit -a -m two && + git push) +' + +test_expect_success 'pulling from local repo' ' + (cd localclone && git pull) && + test_cmp public/file localclone/file +' + +test_expect_success 'pulling from remote remote' ' + (cd clone && git pull) && + test_cmp public/file clone/file +' + +test_expect_success 'pushing to local repo' ' + (cd localclone && + echo content >>file && + git commit -a -m three && + git push) && + compare_refs localclone HEAD server HEAD +' + +# Generally, skip this test. It demonstrates a now-fixed race in +# git-remote-testgit, but is too slow to leave in for general use. +: test_expect_success 'racily pushing to local repo' ' + test_when_finished "rm -rf server2 localclone2" && + cp -R server server2 && + git clone "testgit::${PWD}/server2" localclone2 && + (cd localclone2 && + echo content >>file && + git commit -a -m three && + GIT_REMOTE_TESTGIT_SLEEPY=2 git push) && + compare_refs localclone2 HEAD server2 HEAD +' + +test_expect_success 'synch with changes from localclone' ' + (cd clone && + git pull) +' + +test_expect_success 'pushing remote local repo' ' + (cd clone && + echo content >>file && + git commit -a -m four && + git push) && + compare_refs clone HEAD server HEAD +' + +test_expect_success 'fetch new branch' ' + (cd public && + git checkout -b new && + echo content >>file && + git commit -a -m five && + git push origin new + ) && + (cd localclone && + git fetch origin new + ) && + compare_refs public HEAD localclone FETCH_HEAD +' + +test_expect_success 'fetch multiple branches' ' + (cd localclone && + git fetch + ) && + compare_refs server master localclone refs/remotes/origin/master && + compare_refs server new localclone refs/remotes/origin/new +' + +test_expect_success 'push when remote has extra refs' ' + (cd clone && + echo content >>file && + git commit -a -m six && + git push + ) && + compare_refs clone master server master +' + +test_expect_success 'push new branch by name' ' + (cd clone && + git checkout -b new-name && + echo content >>file && + git commit -a -m seven && + git push origin new-name + ) && + compare_refs clone HEAD server refs/heads/new-name +' + +test_expect_failure 'push new branch with old:new refspec' ' + (cd clone && + git push origin new-name:new-refspec + ) && + compare_refs clone HEAD server refs/heads/new-refspec +' + +test_done From 984f37681c937be0c7c1135e86141a83920edcc1 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:02 +0100 Subject: [PATCH 06/15] remote-testgit: remove non-local functionality This only makes sense for the python remote helpers framework. The tests don't exercise any feature of transport helper. Remove them. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- git-remote-testgit | 3 --- t/t5801-remote-helpers.sh | 50 ++++++++++++++++----------------------- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/git-remote-testgit b/git-remote-testgit index 5042f5a11f..5117ab5fe0 100755 --- a/git-remote-testgit +++ b/git-remote-testgit @@ -4,9 +4,6 @@ alias=$1 url=$2 -# huh? -url="${url#file://}" - dir="$GIT_DIR/testgit/$alias" prefix="refs/testgit/$alias" refspec="refs/heads/*:${prefix}/heads/*" diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index f52ab1466b..2f7fc104ea 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -33,11 +33,6 @@ test_expect_success 'cloning from local repo' ' test_cmp public/file localclone/file ' -test_expect_success 'cloning from remote repo' ' - git clone "testgit::file://${PWD}/server" clone && - test_cmp public/file clone/file -' - test_expect_success 'create new commit on remote' ' (cd public && echo content >>file && @@ -50,11 +45,6 @@ test_expect_success 'pulling from local repo' ' test_cmp public/file localclone/file ' -test_expect_success 'pulling from remote remote' ' - (cd clone && git pull) && - test_cmp public/file clone/file -' - test_expect_success 'pushing to local repo' ' (cd localclone && echo content >>file && @@ -76,19 +66,6 @@ test_expect_success 'pushing to local repo' ' compare_refs localclone2 HEAD server2 HEAD ' -test_expect_success 'synch with changes from localclone' ' - (cd clone && - git pull) -' - -test_expect_success 'pushing remote local repo' ' - (cd clone && - echo content >>file && - git commit -a -m four && - git push) && - compare_refs clone HEAD server HEAD -' - test_expect_success 'fetch new branch' ' (cd public && git checkout -b new && @@ -102,6 +79,20 @@ test_expect_success 'fetch new branch' ' compare_refs public HEAD localclone FETCH_HEAD ' +# +# This is only needed because of a bug not detected by this script. It will be +# fixed shortly, but for now lets not cause regressions. +# +test_expect_success 'bump commit in public' ' + (cd public && + git checkout master && + git pull && + echo content >>file && + git commit -a -m four && + git push) && + compare_refs public HEAD server HEAD +' + test_expect_success 'fetch multiple branches' ' (cd localclone && git fetch @@ -111,29 +102,30 @@ test_expect_success 'fetch multiple branches' ' ' test_expect_success 'push when remote has extra refs' ' - (cd clone && + (cd localclone && + git reset --hard origin/master && echo content >>file && git commit -a -m six && git push ) && - compare_refs clone master server master + compare_refs localclone master server master ' test_expect_success 'push new branch by name' ' - (cd clone && + (cd localclone && git checkout -b new-name && echo content >>file && git commit -a -m seven && git push origin new-name ) && - compare_refs clone HEAD server refs/heads/new-name + compare_refs localclone HEAD server refs/heads/new-name ' test_expect_failure 'push new branch with old:new refspec' ' - (cd clone && + (cd localclone && git push origin new-name:new-refspec ) && - compare_refs clone HEAD server refs/heads/new-refspec + compare_refs localclone HEAD server refs/heads/new-refspec ' test_done From 0803d35940954ebfd33820bffa7a8ab9951ff143 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:03 +0100 Subject: [PATCH 07/15] remote-testgit: remove irrelevant test This was only to cover a bug that was fixed in remote-testpy not to resurface. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- t/t5801-remote-helpers.sh | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index 2f7fc104ea..6801529a89 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -53,19 +53,6 @@ test_expect_success 'pushing to local repo' ' compare_refs localclone HEAD server HEAD ' -# Generally, skip this test. It demonstrates a now-fixed race in -# git-remote-testgit, but is too slow to leave in for general use. -: test_expect_success 'racily pushing to local repo' ' - test_when_finished "rm -rf server2 localclone2" && - cp -R server server2 && - git clone "testgit::${PWD}/server2" localclone2 && - (cd localclone2 && - echo content >>file && - git commit -a -m three && - GIT_REMOTE_TESTGIT_SLEEPY=2 git push) && - compare_refs localclone2 HEAD server2 HEAD -' - test_expect_success 'fetch new branch' ' (cd public && git checkout -b new && From 3808b8515bc777f63348c3f4053314742c59ac51 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:04 +0100 Subject: [PATCH 08/15] remote-testgit: cleanup tests We don't need a bare 'server' and an intermediary 'public'. The repos can talk to each other directly; that's what we want to exercise. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- t/t5801-remote-helpers.sh | 63 ++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index 6801529a89..bc0b5f740a 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -19,100 +19,95 @@ compare_refs() { } test_expect_success 'setup repository' ' - git init --bare server/.git && - git clone server public && - (cd public && + git init server && + (cd server && echo content >file && git add file && - git commit -m one && - git push origin master) + git commit -m one) ' test_expect_success 'cloning from local repo' ' - git clone "testgit::${PWD}/server" localclone && - test_cmp public/file localclone/file + git clone "testgit::${PWD}/server" local && + test_cmp server/file local/file ' test_expect_success 'create new commit on remote' ' - (cd public && + (cd server && echo content >>file && - git commit -a -m two && - git push) + git commit -a -m two) ' test_expect_success 'pulling from local repo' ' - (cd localclone && git pull) && - test_cmp public/file localclone/file + (cd local && git pull) && + test_cmp server/file local/file ' test_expect_success 'pushing to local repo' ' - (cd localclone && + (cd local && echo content >>file && git commit -a -m three && git push) && - compare_refs localclone HEAD server HEAD + compare_refs local HEAD server HEAD ' test_expect_success 'fetch new branch' ' - (cd public && + (cd server && + git reset --hard && git checkout -b new && echo content >>file && - git commit -a -m five && - git push origin new + git commit -a -m five ) && - (cd localclone && + (cd local && git fetch origin new ) && - compare_refs public HEAD localclone FETCH_HEAD + compare_refs server HEAD local FETCH_HEAD ' # # This is only needed because of a bug not detected by this script. It will be # fixed shortly, but for now lets not cause regressions. # -test_expect_success 'bump commit in public' ' - (cd public && +test_expect_success 'bump commit in server' ' + (cd server && git checkout master && - git pull && echo content >>file && - git commit -a -m four && - git push) && - compare_refs public HEAD server HEAD + git commit -a -m four) && + compare_refs server HEAD server HEAD ' test_expect_success 'fetch multiple branches' ' - (cd localclone && + (cd local && git fetch ) && - compare_refs server master localclone refs/remotes/origin/master && - compare_refs server new localclone refs/remotes/origin/new + compare_refs server master local refs/remotes/origin/master && + compare_refs server new local refs/remotes/origin/new ' test_expect_success 'push when remote has extra refs' ' - (cd localclone && + (cd local && git reset --hard origin/master && echo content >>file && git commit -a -m six && git push ) && - compare_refs localclone master server master + compare_refs local master server master ' test_expect_success 'push new branch by name' ' - (cd localclone && + (cd local && git checkout -b new-name && echo content >>file && git commit -a -m seven && git push origin new-name ) && - compare_refs localclone HEAD server refs/heads/new-name + compare_refs local HEAD server refs/heads/new-name ' test_expect_failure 'push new branch with old:new refspec' ' - (cd localclone && + (cd local && git push origin new-name:new-refspec ) && - compare_refs localclone HEAD server refs/heads/new-refspec + compare_refs local HEAD server refs/heads/new-refspec ' test_done From ee10fbf90c74c14ae16a27f4bce8a2dd1704c9cb Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:05 +0100 Subject: [PATCH 09/15] remote-testgit: exercise more features Unfortunately a lot of these tests fail. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- git-remote-testgit | 38 +++++++++++++++++++--------- t/t5801-remote-helpers.sh | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/git-remote-testgit b/git-remote-testgit index 5117ab5fe0..efda74bee3 100755 --- a/git-remote-testgit +++ b/git-remote-testgit @@ -6,17 +6,25 @@ url=$2 dir="$GIT_DIR/testgit/$alias" prefix="refs/testgit/$alias" -refspec="refs/heads/*:${prefix}/heads/*" -gitmarks="$dir/git.marks" -testgitmarks="$dir/testgit.marks" +default_refspec="refs/heads/*:${prefix}/heads/*" + +refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}" + +test -z "$refspec" && prefix="refs" export GIT_DIR="$url/.git" mkdir -p "$dir" -test -e "$gitmarks" || > "$gitmarks" -test -e "$testgitmarks" || > "$testgitmarks" +if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS" +then + gitmarks="$dir/git.marks" + testgitmarks="$dir/testgit.marks" + test -e "$gitmarks" || >"$gitmarks" + test -e "$testgitmarks" || >"$testgitmarks" + testgitmarks_args=( "--"{import,export}"-marks=$testgitmarks" ) +fi while read line do @@ -24,9 +32,12 @@ do capabilities) echo 'import' echo 'export' - echo "refspec $refspec" - echo "*import-marks $gitmarks" - echo "*export-marks $gitmarks" + test -n "$refspec" && echo "refspec $refspec" + if test -n "$gitmarks" + then + echo "*import-marks $gitmarks" + echo "*export-marks $gitmarks" + fi echo ;; list) @@ -45,13 +56,16 @@ do test "${line%% *}" != "import" && break done - echo "feature import-marks=$gitmarks" - echo "feature export-marks=$gitmarks" - git fast-export --use-done-feature --{import,export}-marks="$testgitmarks" $refs | + if test -n "$gitmarks" + then + echo "feature import-marks=$gitmarks" + echo "feature export-marks=$gitmarks" + fi + git fast-export --use-done-feature "${testgitmarks_args[@]}" $refs | sed -e "s#refs/heads/#${prefix}/heads/#g" ;; export) - git fast-import --{import,export}-marks="$testgitmarks" --quiet + git fast-import "${testgitmarks_args[@]}" --quiet echo ;; '') diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index bc0b5f740a..12ae256640 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -110,4 +110,56 @@ test_expect_failure 'push new branch with old:new refspec' ' compare_refs local HEAD server refs/heads/new-refspec ' +test_expect_success 'cloning without refspec' ' + GIT_REMOTE_TESTGIT_REFSPEC="" \ + git clone "testgit::${PWD}/server" local2 && + compare_refs local2 HEAD server HEAD +' + +test_expect_success 'pulling without refspecs' ' + (cd local2 && + git reset --hard && + GIT_REMOTE_TESTGIT_REFSPEC="" git pull) && + compare_refs local2 HEAD server HEAD +' + +test_expect_failure 'pushing without refspecs' ' + test_when_finished "(cd local2 && git reset --hard origin)" && + (cd local2 && + echo content >>file && + git commit -a -m ten && + GIT_REMOTE_TESTGIT_REFSPEC="" git push) && + compare_refs local2 HEAD server HEAD +' + +test_expect_success 'pulling with straight refspec' ' + (cd local2 && + GIT_REMOTE_TESTGIT_REFSPEC="*:*" git pull) && + compare_refs local2 HEAD server HEAD +' + +test_expect_failure 'pushing with straight refspec' ' + test_when_finished "(cd local2 && git reset --hard origin)" && + (cd local2 && + echo content >>file && + git commit -a -m eleven && + GIT_REMOTE_TESTGIT_REFSPEC="*:*" git push) && + compare_refs local2 HEAD server HEAD +' + +test_expect_success 'pulling without marks' ' + (cd local2 && + GIT_REMOTE_TESTGIT_NO_MARKS=1 git pull) && + compare_refs local2 HEAD server HEAD +' + +test_expect_failure 'pushing without marks' ' + test_when_finished "(cd local2 && git reset --hard origin)" && + (cd local2 && + echo content >>file && + git commit -a -m twelve && + GIT_REMOTE_TESTGIT_NO_MARKS=1 git push) && + compare_refs local2 HEAD server HEAD +' + test_done From 93b5cf9cd12a0b9491559429969b351daa3638a5 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:06 +0100 Subject: [PATCH 10/15] remote-testgit: report success after an import Doesn't make a difference for the tests, but it does for the ones seeking reference. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- git-remote-testgit | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/git-remote-testgit b/git-remote-testgit index efda74bee3..6fb8780677 100755 --- a/git-remote-testgit +++ b/git-remote-testgit @@ -65,7 +65,20 @@ do sed -e "s#refs/heads/#${prefix}/heads/#g" ;; export) + before=$(git for-each-ref --format='%(refname) %(objectname)') + git fast-import "${testgitmarks_args[@]}" --quiet + + after=$(git for-each-ref --format='%(refname) %(objectname)') + + # figure out which refs were updated + join -e 0 -o '0 1.2 2.2' -a 2 <(echo "$before") <(echo "$after") | + while read ref a b + do + test $a == $b && continue + echo "ok $ref" + done + echo ;; '') From 1d3f9a30938e12b8ef7b807df7565b40b743d421 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:07 +0100 Subject: [PATCH 11/15] remote-testgit: implement the "done" feature manually People who want to write their own remote-helper will find it more useful to see clearly how they are supposed to advertise and implement the "done" feature themselves. Right now we are relying on fast-export to do that by using the --use-done-feature argument. However, people writing their own remote-helper would probably not have such an option, as they would probably be writing the fast-export functionality themselves. It should now be clearer to them. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- git-remote-testgit | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/git-remote-testgit b/git-remote-testgit index 6fb8780677..b395c8de59 100755 --- a/git-remote-testgit +++ b/git-remote-testgit @@ -61,8 +61,10 @@ do echo "feature import-marks=$gitmarks" echo "feature export-marks=$gitmarks" fi - git fast-export --use-done-feature "${testgitmarks_args[@]}" $refs | + echo "feature done" + git fast-export "${testgitmarks_args[@]}" $refs | sed -e "s#refs/heads/#${prefix}/heads/#g" + echo "done" ;; export) before=$(git for-each-ref --format='%(refname) %(objectname)') From 2d242de4fd76e31031ee36e7307ab1386e2bce7d Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:08 +0100 Subject: [PATCH 12/15] fast-export: trivial cleanup Setting 'commit' to 'commit' is a no-op. It might have been there to avoid a compiler warning, but if so, it was the compiler to blame, and it's certainly not there any more. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- builtin/fast-export.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 9b70ec1fcf..191936c179 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -483,7 +483,7 @@ static void get_tags_and_duplicates(struct object_array *pending, for (i = 0; i < pending->nr; i++) { struct object_array_entry *e = pending->objects + i; unsigned char sha1[20]; - struct commit *commit = commit; + struct commit *commit; char *full_name; if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1) From 9ff10fc86989940eb2c016511c293bc0ac50e6f6 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:11:09 +0100 Subject: [PATCH 13/15] fast-export: fix comparison in tests First the expected, then the actual, otherwise the diff would be the opposite of what we want. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- t/t9350-fast-export.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 5948b65f21..1f598622a6 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -303,7 +303,7 @@ test_expect_success 'dropping tag of filtered out object' ' ( cd limit-by-paths && git fast-export --tag-of-filtered-object=drop mytag -- there > output && - test_cmp output expected + test_cmp expected output ) ' @@ -320,7 +320,7 @@ test_expect_success 'rewriting tag of filtered out object' ' ( cd limit-by-paths && git fast-export --tag-of-filtered-object=rewrite mytag -- there > output && - test_cmp output expected + test_cmp expected output ) ' @@ -351,7 +351,7 @@ test_expect_failure 'no exact-ref revisions included' ' ( cd limit-by-paths && git fast-export master~2..master~1 > output && - test_cmp output expected + test_cmp expected output ) ' From 49266e8a11cffa1bb41217021470e33d26109bb2 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:23:59 +0100 Subject: [PATCH 14/15] fast-export: don't handle uninteresting refs They have been marked as UNINTERESTING for a reason, lets respect that. Currently the first ref is handled properly, but not the rest. Assuming that all the refs point at the same commit in the following example: % git fast-export master ^uninteresting ^foo ^bar reset refs/heads/bar from :0 reset refs/heads/foo from :0 reset refs/heads/uninteresting from :0 % git fast-export ^uninteresting ^foo ^bar master reset refs/heads/master from :0 reset refs/heads/bar from :0 reset refs/heads/foo from :0 Clearly this is wrong; the negative refs should be ignored. After this patch: % git fast-export ^uninteresting ^foo ^bar master # nothing % git fast-export master ^uninteresting ^foo ^bar # nothing And even more, it would only happen if the ref is pointing to exactly the same commit, but not otherwise: % git fast-export ^next next reset refs/heads/next from :0 % git fast-export ^next next^{commit} # nothing % git fast-export ^next next~0 # nothing % git fast-export ^next next~1 # nothing % git fast-export ^next next~2 # nothing The reason this happens is that before traversing the commits, fast-export checks if any of the refs point to the same object, and any duplicated ref gets added to a list in order to issue 'reset' commands after the traversing. Unfortunately, it's not even checking if the commit is flagged as UNINTERESTING. The fix of course, is to check it. However, in order to do it properly we need to get the UNINTERESTING flag from the command line, not from the commit object, because "^foo bar" will mark the commit 'bar' uninteresting if foo and bar points at the same commit. rev_cmdline_info, which was introduced exactly to handle this situation, contains all the information we need for get_tags_and_duplicates(), plus the ref flag. This way the rest of the positive refs will remain untouched; it's only the negative ones that change in behavior. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- builtin/fast-export.c | 11 +++++++---- t/t5801-remote-helpers.sh | 8 ++++++++ t/t9350-fast-export.sh | 30 ++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 191936c179..2547e6cb52 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -474,18 +474,21 @@ static void handle_tag(const char *name, struct tag *tag) (int)message_size, (int)message_size, message ? message : ""); } -static void get_tags_and_duplicates(struct object_array *pending, +static void get_tags_and_duplicates(struct rev_cmdline_info *info, struct string_list *extra_refs) { struct tag *tag; int i; - for (i = 0; i < pending->nr; i++) { - struct object_array_entry *e = pending->objects + i; + for (i = 0; i < info->nr; i++) { + struct rev_cmdline_entry *e = info->rev + i; unsigned char sha1[20]; struct commit *commit; char *full_name; + if (e->flags & UNINTERESTING) + continue; + if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1) continue; @@ -681,7 +684,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) if (import_filename && revs.prune_data.nr) full_tree = 1; - get_tags_and_duplicates(&revs.pending, &extra_refs); + get_tags_and_duplicates(&revs.cmdline, &extra_refs); if (prepare_revision_walk(&revs)) die("revision walk setup failed"); diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index 12ae256640..ece8fd5ab8 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -162,4 +162,12 @@ test_expect_failure 'pushing without marks' ' compare_refs local2 HEAD server HEAD ' +test_expect_success 'push all with existing object' ' + (cd local && + git branch dup2 master && + git push origin --all + ) && + compare_refs local dup2 server dup2 +' + test_done diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 1f598622a6..c8e41c1d42 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -454,4 +454,34 @@ test_expect_success 'test bidirectionality' ' git fast-import --export-marks=marks-cur --import-marks=marks-cur ' +cat > expected << EOF +blob +mark :13 +data 5 +bump + +commit refs/heads/master +mark :14 +author A U Thor 1112912773 -0700 +committer C O Mitter 1112912773 -0700 +data 5 +bump +from :12 +M 100644 :13 file + +EOF + +test_expect_success 'avoid uninteresting refs' ' + > tmp-marks && + git fast-export --import-marks=tmp-marks \ + --export-marks=tmp-marks master > /dev/null && + git tag v1.0 && + git branch uninteresting && + echo bump > file && + git commit -a -m bump && + git fast-export --import-marks=tmp-marks \ + --export-marks=tmp-marks ^uninteresting ^v1.0 master > actual && + test_cmp expected actual +' + test_done From f28e7c904ac82b0c5e43805529e7d5296fa4d13b Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 28 Nov 2012 23:24:00 +0100 Subject: [PATCH 15/15] fast-export: make sure updated refs get updated When an object has already been exported (and thus is in the marks) it's flagged as SHOWN, so it will not be exported again, even if in a later time it's exported through a different ref. We don't need the object to be exported again, but we want the ref updated, which doesn't happen. Since we can't know if a ref was exported or not, let's just assume that if the commit was marked (flags & SHOWN), the user still wants the ref updated. IOW: If it's specified in the command line, it will get updated, regardless of whether or not the object was marked. So: % git branch test master % git fast-export $mark_flags master % git fast-export $mark_flags test Would export 'test' properly. Additionally, this fixes issues with remote helpers; now they can push refs whose objects have already been exported, and a few other issues as well. Update the tests accordingly. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- builtin/fast-export.c | 10 +++++++--- t/t5801-remote-helpers.sh | 20 ++++++++------------ t/t9350-fast-export.sh | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 2547e6cb52..77dffd1ce3 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -526,10 +526,14 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info, typename(e->item->type)); continue; } - if (commit->util) - /* more than one name for the same object */ + + /* + * This ref will not be updated through a commit, lets make + * sure it gets properly updated eventually. + */ + if (commit->util || commit->object.flags & SHOWN) string_list_append(extra_refs, full_name)->util = commit; - else + if (!commit->util) commit->util = full_name; } } diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index ece8fd5ab8..f387027c05 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -63,18 +63,6 @@ test_expect_success 'fetch new branch' ' compare_refs server HEAD local FETCH_HEAD ' -# -# This is only needed because of a bug not detected by this script. It will be -# fixed shortly, but for now lets not cause regressions. -# -test_expect_success 'bump commit in server' ' - (cd server && - git checkout master && - echo content >>file && - git commit -a -m four) && - compare_refs server HEAD server HEAD -' - test_expect_success 'fetch multiple branches' ' (cd local && git fetch @@ -170,4 +158,12 @@ test_expect_success 'push all with existing object' ' compare_refs local dup2 server dup2 ' +test_expect_success 'push ref with existing object' ' + (cd local && + git branch dup master && + git push origin dup + ) && + compare_refs local dup server dup +' + test_done diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index c8e41c1d42..9320b4f94c 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -484,4 +484,19 @@ test_expect_success 'avoid uninteresting refs' ' test_cmp expected actual ' +cat > expected << EOF +reset refs/heads/master +from :14 + +EOF + +test_expect_success 'refs are updated even if no commits need to be exported' ' + > tmp-marks && + git fast-export --import-marks=tmp-marks \ + --export-marks=tmp-marks master > /dev/null && + git fast-export --import-marks=tmp-marks \ + --export-marks=tmp-marks master > actual && + test_cmp expected actual +' + test_done