Merge branch 'jc/push-follow-tag'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Mar 2013 21:00:40 +0000 (14:00 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Mar 2013 21:00:41 +0000 (14:00 -0700)
The new "--follow-tags" option tells "git push" to push relevant
annotated tags when pushing branches out.

* jc/push-follow-tag:
push: --follow-tags
commit.c: use clear_commit_marks_many() in in_merge_bases_many()
commit.c: add in_merge_bases_many()
commit.c: add clear_commit_marks_many()

1  2 
Documentation/git-push.txt
builtin/push.c
commit.h
remote.c
remote.h
t/t5516-fetch-push.sh
transport.c
transport.h
Simple merge
diff --cc builtin/push.c
index 42b129d36cf615ed264be0f1bff523a7fc327b12,34a82711d44102db96d451b924ae246f587c3001..5e4a0e958f3649c5a5a9f317876e8afd6f6bea6f
@@@ -436,7 -399,8 +436,9 @@@ int cmd_push(int argc, const char **arg
                OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
                OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
                        TRANSPORT_PUSH_PRUNE),
 +              OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
+               OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
+                       TRANSPORT_PUSH_FOLLOW_TAGS),
                OPT_END()
        };
  
diff --cc commit.h
Simple merge
diff --cc remote.c
Simple merge
diff --cc remote.h
Simple merge
index 6fd125aecf128a6c4a2ae8b986d5a311c6d0c133,4ff2eb2ba872a22f3f18259a2c8c68f7d7084cd5..d3dc5df7b145a23a8d0ab55f69d7ca7351d78274
@@@ -1016,65 -995,77 +1016,138 @@@ test_expect_success 'push --prune refsp
        ! check_push_result $the_first_commit tmp/foo tmp/bar
  '
  
 +for configsection in transfer receive
 +do
 +      test_expect_success "push to update a ref hidden by $configsection.hiderefs" '
 +              mk_test heads/master hidden/one hidden/two hidden/three &&
 +              (
 +                      cd testrepo &&
 +                      git config $configsection.hiderefs refs/hidden
 +              ) &&
 +
 +              # push to unhidden ref succeeds normally
 +              git push testrepo master:refs/heads/master &&
 +              check_push_result $the_commit heads/master &&
 +
 +              # push to update a hidden ref should fail
 +              test_must_fail git push testrepo master:refs/hidden/one &&
 +              check_push_result $the_first_commit hidden/one &&
 +
 +              # push to delete a hidden ref should fail
 +              test_must_fail git push testrepo :refs/hidden/two &&
 +              check_push_result $the_first_commit hidden/two &&
 +
 +              # idempotent push to update a hidden ref should fail
 +              test_must_fail git push testrepo $the_first_commit:refs/hidden/three &&
 +              check_push_result $the_first_commit hidden/three
 +      '
 +done
 +
 +test_expect_success 'fetch exact SHA1' '
 +      mk_test heads/master hidden/one &&
 +      git push testrepo master:refs/hidden/one &&
 +      (
 +              cd testrepo &&
 +              git config transfer.hiderefs refs/hidden
 +      ) &&
 +      check_push_result $the_commit hidden/one &&
 +
 +      mk_child child &&
 +      (
 +              cd child &&
 +
 +              # make sure $the_commit does not exist here
 +              git repack -a -d &&
 +              git prune &&
 +              test_must_fail git cat-file -t $the_commit &&
 +
 +              # fetching the hidden object should fail by default
 +              test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
 +              test_must_fail git rev-parse --verify refs/heads/copy &&
 +
 +              # the server side can allow it to succeed
 +              (
 +                      cd ../testrepo &&
 +                      git config uploadpack.allowtipsha1inwant true
 +              ) &&
 +
 +              git fetch -v ../testrepo $the_commit:refs/heads/copy &&
 +              result=$(git rev-parse --verify refs/heads/copy) &&
 +              test "$the_commit" = "$result"
 +      )
 +'
 +
+ test_expect_success 'fetch follows tags by default' '
+       mk_test heads/master &&
+       rm -fr src dst &&
+       git init src &&
+       (
+               cd src &&
+               git pull ../testrepo master &&
+               git tag -m "annotated" tag &&
+               git for-each-ref >tmp1 &&
+               (
+                       cat tmp1
+                       sed -n "s|refs/heads/master$|refs/remotes/origin/master|p" tmp1
+               ) |
+               sort -k 3 >../expect
+       ) &&
+       git init dst &&
+       (
+               cd dst &&
+               git remote add origin ../src &&
+               git config branch.master.remote origin &&
+               git config branch.master.merge refs/heads/master &&
+               git pull &&
+               git for-each-ref >../actual
+       ) &&
+       test_cmp expect actual
+ '
+ test_expect_success 'push does not follow tags by default' '
+       mk_test heads/master &&
+       rm -fr src dst &&
+       git init src &&
+       git init --bare dst &&
+       (
+               cd src &&
+               git pull ../testrepo master &&
+               git tag -m "annotated" tag &&
+               git checkout -b another &&
+               git commit --allow-empty -m "future commit" &&
+               git tag -m "future" future &&
+               git checkout master &&
+               git for-each-ref refs/heads/master >../expect &&
+               git push ../dst master
+       ) &&
+       (
+               cd dst &&
+               git for-each-ref >../actual
+       ) &&
+       test_cmp expect actual
+ '
+ test_expect_success 'push --follow-tag only pushes relevant tags' '
+       mk_test heads/master &&
+       rm -fr src dst &&
+       git init src &&
+       git init --bare dst &&
+       (
+               cd src &&
+               git pull ../testrepo master &&
+               git tag -m "annotated" tag &&
+               git checkout -b another &&
+               git commit --allow-empty -m "future commit" &&
+               git tag -m "future" future &&
+               git checkout master &&
+               git for-each-ref refs/heads/master refs/tags/tag >../expect
+               git push --follow-tag ../dst master
+       ) &&
+       (
+               cd dst &&
+               git for-each-ref >../actual
+       ) &&
+       test_cmp expect actual
+ '
  test_done
diff --cc transport.c
Simple merge
diff --cc transport.h
index a3450e97c0d0d94778a4b635efdd53b724eb70c2,8c493f7f637e1d7e555a7692282aca3d9a086efe..93544627087bdaed1373efb2205fc6f94b89527c
@@@ -104,7 -104,7 +104,8 @@@ struct transport 
  #define TRANSPORT_RECURSE_SUBMODULES_CHECK 64
  #define TRANSPORT_PUSH_PRUNE 128
  #define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256
 +#define TRANSPORT_PUSH_NO_HOOK 512
+ #define TRANSPORT_PUSH_FOLLOW_TAGS 1024
  
  #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
  #define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x)