summaryrefslogtreecommitdiff
path: root/builtin/submodule--helper.c
diff options
context:
space:
mode:
authorBrandon Williams <bmwill@google.com>2017-07-20 17:40:37 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-07-20 21:58:26 (GMT)
commitc7be7201a7b71f590325f0d858f909a4c0b443f6 (patch)
tree1880ae1f4b6a9811f249c43f62e1c62167f613ae /builtin/submodule--helper.c
parent06bf4ad1db92c32af38e16d9b7f928edbd647780 (diff)
downloadgit-c7be7201a7b71f590325f0d858f909a4c0b443f6.zip
git-c7be7201a7b71f590325f0d858f909a4c0b443f6.tar.gz
git-c7be7201a7b71f590325f0d858f909a4c0b443f6.tar.bz2
submodule--helper: teach push-check to handle HEAD
In 06bf4ad1d (push: propagate remote and refspec with --recurse-submodules) push was taught how to propagate a refspec down to submodules when the '--recurse-submodules' flag is given. The only refspecs that are allowed to be propagated are ones which name a ref which exists in both the superproject and the submodule, with the caveat that 'HEAD' was disallowed. This patch teaches push-check (the submodule helper which determines if a refspec can be propagated to a submodule) to permit propagating 'HEAD' if and only if the superproject and the submodule both have the same named branch checked out and the submodule is not in a detached head state. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/submodule--helper.c')
-rw-r--r--builtin/submodule--helper.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6ee9622..825400d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1108,9 +1108,28 @@ static int resolve_remote_submodule_branch(int argc, const char **argv,
static int push_check(int argc, const char **argv, const char *prefix)
{
struct remote *remote;
+ const char *superproject_head;
+ char *head;
+ int detached_head = 0;
+ struct object_id head_oid;
- if (argc < 2)
- die("submodule--helper push-check requires at least 1 argument");
+ if (argc < 3)
+ die("submodule--helper push-check requires at least 2 arguments");
+
+ /*
+ * superproject's resolved head ref.
+ * if HEAD then the superproject is in a detached head state, otherwise
+ * it will be the resolved head ref.
+ */
+ superproject_head = argv[1];
+ argv++;
+ argc--;
+ /* Get the submodule's head ref and determine if it is detached */
+ head = resolve_refdup("HEAD", 0, head_oid.hash, NULL);
+ if (!head)
+ die(_("Failed to resolve HEAD as a valid ref."));
+ if (!strcmp(head, "HEAD"))
+ detached_head = 1;
/*
* The remote must be configured.
@@ -1133,18 +1152,30 @@ static int push_check(int argc, const char **argv, const char *prefix)
if (rs->pattern || rs->matching)
continue;
- /*
- * LHS must match a single ref
- * NEEDSWORK: add logic to special case 'HEAD' once
- * working with submodules in a detached head state
- * ceases to be the norm.
- */
- if (count_refspec_match(rs->src, local_refs, NULL) != 1)
+ /* LHS must match a single ref */
+ switch (count_refspec_match(rs->src, local_refs, NULL)) {
+ case 1:
+ break;
+ case 0:
+ /*
+ * If LHS matches 'HEAD' then we need to ensure
+ * that it matches the same named branch
+ * checked out in the superproject.
+ */
+ if (!strcmp(rs->src, "HEAD")) {
+ if (!detached_head &&
+ !strcmp(head, superproject_head))
+ break;
+ die("HEAD does not match the named branch in the superproject");
+ }
+ default:
die("src refspec '%s' must name a ref",
rs->src);
+ }
}
free_refspec(refspec_nr, refspec);
}
+ free(head);
return 0;
}