Merge branch 'bw/push-options-recursively-to-submodules' into maint
"git push --recurse-submodules $there HEAD:$target" was not propagated down to the submodules, but now it is. * bw/push-options-recursively-to-submodules: submodule--helper: teach push-check to handle HEAD
This commit is contained in:
commit
eba2a68f25
@ -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)
|
static int push_check(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
struct remote *remote;
|
struct remote *remote;
|
||||||
|
const char *superproject_head;
|
||||||
|
char *head;
|
||||||
|
int detached_head = 0;
|
||||||
|
struct object_id head_oid;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 3)
|
||||||
die("submodule--helper push-check requires at least 1 argument");
|
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.
|
* 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)
|
if (rs->pattern || rs->matching)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/* LHS must match a single ref */
|
||||||
* LHS must match a single ref
|
switch (count_refspec_match(rs->src, local_refs, NULL)) {
|
||||||
* NEEDSWORK: add logic to special case 'HEAD' once
|
case 1:
|
||||||
* working with submodules in a detached head state
|
break;
|
||||||
* ceases to be the norm.
|
case 0:
|
||||||
*/
|
/*
|
||||||
if (count_refspec_match(rs->src, local_refs, NULL) != 1)
|
* 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",
|
die("src refspec '%s' must name a ref",
|
||||||
rs->src);
|
rs->src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free_refspec(refspec_nr, refspec);
|
free_refspec(refspec_nr, refspec);
|
||||||
}
|
}
|
||||||
|
free(head);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
18
submodule.c
18
submodule.c
@ -1015,7 +1015,8 @@ static int push_submodule(const char *path,
|
|||||||
* Perform a check in the submodule to see if the remote and refspec work.
|
* Perform a check in the submodule to see if the remote and refspec work.
|
||||||
* Die if the submodule can't be pushed.
|
* Die if the submodule can't be pushed.
|
||||||
*/
|
*/
|
||||||
static void submodule_push_check(const char *path, const struct remote *remote,
|
static void submodule_push_check(const char *path, const char *head,
|
||||||
|
const struct remote *remote,
|
||||||
const char **refspec, int refspec_nr)
|
const char **refspec, int refspec_nr)
|
||||||
{
|
{
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
@ -1023,6 +1024,7 @@ static void submodule_push_check(const char *path, const struct remote *remote,
|
|||||||
|
|
||||||
argv_array_push(&cp.args, "submodule--helper");
|
argv_array_push(&cp.args, "submodule--helper");
|
||||||
argv_array_push(&cp.args, "push-check");
|
argv_array_push(&cp.args, "push-check");
|
||||||
|
argv_array_push(&cp.args, head);
|
||||||
argv_array_push(&cp.args, remote->name);
|
argv_array_push(&cp.args, remote->name);
|
||||||
|
|
||||||
for (i = 0; i < refspec_nr; i++)
|
for (i = 0; i < refspec_nr; i++)
|
||||||
@ -1061,10 +1063,20 @@ int push_unpushed_submodules(struct oid_array *commits,
|
|||||||
* won't be propagated due to the remote being unconfigured (e.g. a URL
|
* won't be propagated due to the remote being unconfigured (e.g. a URL
|
||||||
* instead of a remote name).
|
* instead of a remote name).
|
||||||
*/
|
*/
|
||||||
if (remote->origin != REMOTE_UNCONFIGURED)
|
if (remote->origin != REMOTE_UNCONFIGURED) {
|
||||||
|
char *head;
|
||||||
|
struct object_id head_oid;
|
||||||
|
|
||||||
|
head = resolve_refdup("HEAD", 0, head_oid.hash, NULL);
|
||||||
|
if (!head)
|
||||||
|
die(_("Failed to resolve HEAD as a valid ref."));
|
||||||
|
|
||||||
for (i = 0; i < needs_pushing.nr; i++)
|
for (i = 0; i < needs_pushing.nr; i++)
|
||||||
submodule_push_check(needs_pushing.items[i].string,
|
submodule_push_check(needs_pushing.items[i].string,
|
||||||
remote, refspec, refspec_nr);
|
head, remote,
|
||||||
|
refspec, refspec_nr);
|
||||||
|
free(head);
|
||||||
|
}
|
||||||
|
|
||||||
/* Actually push the submodules */
|
/* Actually push the submodules */
|
||||||
for (i = 0; i < needs_pushing.nr; i++) {
|
for (i = 0; i < needs_pushing.nr; i++) {
|
||||||
|
@ -533,7 +533,8 @@ test_expect_success 'push propagating refspec to a submodule' '
|
|||||||
# Fails when refspec includes an object id
|
# Fails when refspec includes an object id
|
||||||
test_must_fail git -C work push --recurse-submodules=on-demand origin \
|
test_must_fail git -C work push --recurse-submodules=on-demand origin \
|
||||||
"$(git -C work rev-parse branch2):refs/heads/branch2" &&
|
"$(git -C work rev-parse branch2):refs/heads/branch2" &&
|
||||||
# Fails when refspec includes 'HEAD' as it is unsupported at this time
|
# Fails when refspec includes HEAD and parent and submodule do not
|
||||||
|
# have the same named branch checked out
|
||||||
test_must_fail git -C work push --recurse-submodules=on-demand origin \
|
test_must_fail git -C work push --recurse-submodules=on-demand origin \
|
||||||
HEAD:refs/heads/branch2 &&
|
HEAD:refs/heads/branch2 &&
|
||||||
|
|
||||||
@ -548,4 +549,26 @@ test_expect_success 'push propagating refspec to a submodule' '
|
|||||||
test_cmp expected_pub actual_pub
|
test_cmp expected_pub actual_pub
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'push propagating HEAD refspec to a submodule' '
|
||||||
|
git -C work/gar/bage checkout branch2 &&
|
||||||
|
> work/gar/bage/junk12 &&
|
||||||
|
git -C work/gar/bage add junk12 &&
|
||||||
|
git -C work/gar/bage commit -m "Twelfth junk" &&
|
||||||
|
|
||||||
|
git -C work checkout branch2 &&
|
||||||
|
git -C work add gar/bage &&
|
||||||
|
git -C work commit -m "updating gar/bage in branch2" &&
|
||||||
|
|
||||||
|
# Passes since the superproject and submodules HEAD are both on branch2
|
||||||
|
git -C work push --recurse-submodules=on-demand origin \
|
||||||
|
HEAD:refs/heads/branch2 &&
|
||||||
|
|
||||||
|
git -C submodule.git rev-parse branch2 >actual_submodule &&
|
||||||
|
git -C pub.git rev-parse branch2 >actual_pub &&
|
||||||
|
git -C work/gar/bage rev-parse branch2 >expected_submodule &&
|
||||||
|
git -C work rev-parse branch2 >expected_pub &&
|
||||||
|
test_cmp expected_submodule actual_submodule &&
|
||||||
|
test_cmp expected_pub actual_pub
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user