From: Brandon Williams <bmwill@google.com>
To: git@vger.kernel.org
Cc: Brandon Williams <bmwill@google.com>, jrnieder@gmail.com
Subject: [PATCH v3 5/5] push: propagate remote and refspec with --recurse-submodules
Date: Wed, 5 Apr 2017 10:47:19 -0700 [thread overview]
Message-ID: <20170405174719.1297-6-bmwill@google.com> (raw)
In-Reply-To: <20170405174719.1297-1-bmwill@google.com>
Teach "push --recurse-submodules" to propagate, if given a name as remote, the
provided remote and refspec recursively to the pushes performed in the
submodules. The push will therefore only succeed if all submodules have a
remote with such a name configured.
Note that "push --recurse-submodules" with a path or URL as remote will not
propagate the remote or refspec and instead use the default remote and refspec
configured in the submodule, preserving the current behavior.
Signed-off-by: Brandon Williams <bmwill@google.com>
---
submodule.c | 63 ++++++++++++++++++++++++++++++++++++++++--
submodule.h | 4 ++-
t/t5531-deep-submodule-push.sh | 52 ++++++++++++++++++++++++++++++++++
transport.c | 3 +-
4 files changed, 117 insertions(+), 5 deletions(-)
diff --git a/submodule.c b/submodule.c
index de444be61..49ab132d0 100644
--- a/submodule.c
+++ b/submodule.c
@@ -14,6 +14,7 @@
#include "blob.h"
#include "thread-utils.h"
#include "quote.h"
+#include "remote.h"
#include "worktree.h"
static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
@@ -783,6 +784,8 @@ int find_unpushed_submodules(struct sha1_array *commits,
}
static int push_submodule(const char *path,
+ const struct remote *remote,
+ const char **refspec, int refspec_nr,
const struct string_list *push_options,
int dry_run)
{
@@ -801,6 +804,14 @@ static int push_submodule(const char *path,
argv_array_pushf(&cp.args, "--push-option=%s",
item->string);
}
+
+ if (remote->origin != REMOTE_UNCONFIGURED) {
+ int i;
+ argv_array_push(&cp.args, remote->name);
+ for (i = 0; i < refspec_nr; i++)
+ argv_array_push(&cp.args, refspec[i]);
+ }
+
prepare_submodule_repo_env(&cp.env_array);
cp.git_cmd = 1;
cp.no_stdin = 1;
@@ -813,21 +824,67 @@ static int push_submodule(const char *path,
return 1;
}
+/*
+ * Perform a check in the submodule to see if the remote and refspec work.
+ * Die if the submodule can't be pushed.
+ */
+static void submodule_push_check(const char *path, const struct remote *remote,
+ const char **refspec, int refspec_nr)
+{
+ struct child_process cp = CHILD_PROCESS_INIT;
+ int i;
+
+ argv_array_push(&cp.args, "submodule--helper");
+ argv_array_push(&cp.args, "push-check");
+ argv_array_push(&cp.args, remote->name);
+
+ for (i = 0; i < refspec_nr; i++)
+ argv_array_push(&cp.args, refspec[i]);
+
+ prepare_submodule_repo_env(&cp.env_array);
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ cp.no_stdout = 1;
+ cp.dir = path;
+
+ /*
+ * Simply indicate if 'submodule--helper push-check' failed.
+ * More detailed error information will be provided by the
+ * child process.
+ */
+ if (run_command(&cp))
+ die("process for submodule '%s' failed", path);
+}
+
int push_unpushed_submodules(struct sha1_array *commits,
- const char *remotes_name,
+ const struct remote *remote,
+ const char **refspec, int refspec_nr,
const struct string_list *push_options,
int dry_run)
{
int i, ret = 1;
struct string_list needs_pushing = STRING_LIST_INIT_DUP;
- if (!find_unpushed_submodules(commits, remotes_name, &needs_pushing))
+ if (!find_unpushed_submodules(commits, remote->name, &needs_pushing))
return 1;
+ /*
+ * Verify that the remote and refspec can be propagated to all
+ * submodules. This check can be skipped if the remote and refspec
+ * won't be propagated due to the remote being unconfigured (e.g. a URL
+ * instead of a remote name).
+ */
+ if (remote->origin != REMOTE_UNCONFIGURED)
+ for (i = 0; i < needs_pushing.nr; i++)
+ submodule_push_check(needs_pushing.items[i].string,
+ remote, refspec, refspec_nr);
+
+ /* Actually push the submodules */
for (i = 0; i < needs_pushing.nr; i++) {
const char *path = needs_pushing.items[i].string;
fprintf(stderr, "Pushing submodule '%s'\n", path);
- if (!push_submodule(path, push_options, dry_run)) {
+ if (!push_submodule(path, remote, refspec, refspec_nr,
+ push_options, dry_run)) {
fprintf(stderr, "Unable to push submodule '%s'\n", path);
ret = 0;
}
diff --git a/submodule.h b/submodule.h
index 0e26430fd..127ff9be8 100644
--- a/submodule.h
+++ b/submodule.h
@@ -4,6 +4,7 @@
struct diff_options;
struct argv_array;
struct sha1_array;
+struct remote;
enum {
RECURSE_SUBMODULES_ONLY = -5,
@@ -91,7 +92,8 @@ extern int find_unpushed_submodules(struct sha1_array *commits,
const char *remotes_name,
struct string_list *needs_pushing);
extern int push_unpushed_submodules(struct sha1_array *commits,
- const char *remotes_name,
+ const struct remote *remote,
+ const char **refspec, int refspec_nr,
const struct string_list *push_options,
int dry_run);
extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
index f55137f76..57ba32262 100755
--- a/t/t5531-deep-submodule-push.sh
+++ b/t/t5531-deep-submodule-push.sh
@@ -475,4 +475,56 @@ test_expect_success 'push only unpushed submodules recursively' '
test_cmp expected_pub actual_pub
'
+test_expect_success 'push propagating the remotes name to a submodule' '
+ git -C work remote add origin ../pub.git &&
+ git -C work remote add pub ../pub.git &&
+
+ > work/gar/bage/junk10 &&
+ git -C work/gar/bage add junk10 &&
+ git -C work/gar/bage commit -m "Tenth junk" &&
+ git -C work add gar/bage &&
+ git -C work commit -m "Tenth junk added to gar/bage" &&
+
+ # Fails when submodule does not have a matching remote
+ test_must_fail git -C work push --recurse-submodules=on-demand pub master &&
+ # Succeeds when submodules has matching remote and refspec
+ git -C work push --recurse-submodules=on-demand origin master &&
+
+ git -C submodule.git rev-parse master >actual_submodule &&
+ git -C pub.git rev-parse master >actual_pub &&
+ git -C work/gar/bage rev-parse master >expected_submodule &&
+ git -C work rev-parse master >expected_pub &&
+ test_cmp expected_submodule actual_submodule &&
+ test_cmp expected_pub actual_pub
+'
+
+test_expect_success 'push propagating refspec to a submodule' '
+ > work/gar/bage/junk11 &&
+ git -C work/gar/bage add junk11 &&
+ git -C work/gar/bage commit -m "Eleventh junk" &&
+
+ git -C work checkout branch2 &&
+ git -C work add gar/bage &&
+ git -C work commit -m "updating gar/bage in branch2" &&
+
+ # Fails when submodule does not have a matching branch
+ test_must_fail git -C work push --recurse-submodules=on-demand origin branch2 &&
+ # Fails when refspec includes an object id
+ test_must_fail git -C work push --recurse-submodules=on-demand origin \
+ "$(git -C work rev-parse branch2):refs/heads/branch2" &&
+ # Fails when refspec includes 'HEAD' as it is unsupported at this time
+ test_must_fail git -C work push --recurse-submodules=on-demand origin \
+ HEAD:refs/heads/branch2 &&
+
+ git -C work/gar/bage branch branch2 master &&
+ git -C work push --recurse-submodules=on-demand origin 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
diff --git a/transport.c b/transport.c
index 64e60b635..a62e5118c 100644
--- a/transport.c
+++ b/transport.c
@@ -1030,7 +1030,8 @@ int transport_push(struct transport *transport,
sha1_array_append(&commits, ref->new_oid.hash);
if (!push_unpushed_submodules(&commits,
- transport->remote->name,
+ transport->remote,
+ refspec, refspec_nr,
transport->push_options,
pretend)) {
sha1_array_clear(&commits);
--
2.12.2.715.g7642488e1d-goog
next prev parent reply other threads:[~2017-04-05 17:49 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-31 23:11 [PATCH] push: propagate push-options with --recurse-submodules Brandon Williams
2017-03-31 23:20 ` Jonathan Nieder
2017-03-31 23:26 ` Brandon Williams
2017-03-31 23:56 ` [PATCH v2 0/2] propagate push-options Brandon Williams
2017-03-31 23:56 ` [PATCH v2 1/2] push: unmark a local variable as static Brandon Williams
2017-04-01 0:11 ` Jonathan Nieder
2017-04-01 0:16 ` Brandon Williams
2017-03-31 23:56 ` [PATCH v2 2/2] push: propagate push-options with --recurse-submodules Brandon Williams
2017-04-01 0:19 ` Jonathan Nieder
2017-04-06 0:17 ` Jacob Keller
2017-04-06 17:39 ` Brandon Williams
2017-04-05 17:47 ` [PATCH v3 0/5] propagating push-options, remote and refspec Brandon Williams
2017-04-05 17:47 ` [PATCH v3 1/5] push: unmark a local variable as static Brandon Williams
2017-04-05 17:47 ` [PATCH v3 2/5] push: propagate push-options with --recurse-submodules Brandon Williams
2017-04-05 17:47 ` [PATCH v3 3/5] remote: expose parse_push_refspec function Brandon Williams
2017-04-05 17:47 ` [PATCH v3 4/5] submodule--helper: add push-check subcommand Brandon Williams
2017-04-05 17:47 ` Brandon Williams [this message]
2017-04-11 7:44 ` [PATCH v3 0/5] propagating push-options, remote and refspec Junio C Hamano
2017-04-11 16:33 ` Brandon Williams
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170405174719.1297-6-bmwill@google.com \
--to=bmwill@google.com \
--cc=git@vger.kernel.org \
--cc=jrnieder@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.