From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mike Crowe Subject: [PATCH v3] push: add recurseSubmodules config option Date: Tue, 1 Dec 2015 11:49:43 +0000 Message-ID: <1448970583-14513-1-git-send-email-mac@mcrowe.com> Cc: Mike Crowe To: git@vger.kernel.org X-From: git-owner@vger.kernel.org Tue Dec 01 12:50:01 2015 Return-path: Envelope-to: gcvg-git-2@plane.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1a3jRY-0002YQ-Lk for gcvg-git-2@plane.gmane.org; Tue, 01 Dec 2015 12:50:01 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754866AbbLALty (ORCPT ); Tue, 1 Dec 2015 06:49:54 -0500 Received: from relay.appriver.com ([207.97.230.34]:52567 "EHLO relay.appriver.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752698AbbLALtx (ORCPT ); Tue, 1 Dec 2015 06:49:53 -0500 Received: from [86.30.112.98] (HELO elite.brightsign) by relay.appriver.com (CommuniGate Pro SMTP 6.1.2) with ESMTP id 649073023; Tue, 01 Dec 2015 06:49:49 -0500 Received: from chuckie.brightsign ([172.30.1.25] helo=chuckie) by elite.brightsign with esmtp (Exim 4.84) (envelope-from ) id 1a3jRL-000Bym-Jj; Tue, 01 Dec 2015 11:49:47 +0000 Received: from mac by chuckie with local (Exim 4.84) (envelope-from ) id 1a3jRL-0003o3-IE; Tue, 01 Dec 2015 11:49:47 +0000 X-Mailer: git-send-email 2.1.4 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: The --recurse-submodules command line parameter has existed for some time but it has no config file equivalent. Following the style of the corresponding parameter for git fetch, invent push.recurseSubmodules to provide a default for this parameter. This also requires the addition of --recurse-submodules=no to allow the configuration to be overridden on the command line when required. The most straightforward way to implement this appears to be to make push use code in submodule-config in a similar way to fetch. Signed-off-by: Mike Crowe --- Changes in v3: * Incorporate feedback from Junio C Hamano: ** Declare recurse_submodules variable on a separate line. ** Accept multiple --recurse-submodules options on the command line and the last one wins. * Add extra tests for multiple --recurse-submodules options on command line and improve existing tests slightly. Changes in v2: * Incorporate feedback from Eric Sunshine: ** push.recurseSubmodules config option now supports 'no' value. ** --no-recurse-submodules is now a synonym for --recurse-submodules=no. ** use "git -c" rather than "git config" in tests to avoid leaving config options set if a test fails. * Fix several && chain failures in tests noticed by Stefan Beller. * Minor tweaks to documentation * Fix minor naming issues in tests Documentation/config.txt | 14 ++++ Documentation/git-push.txt | 24 +++--- builtin/push.c | 35 ++++---- submodule-config.c | 29 +++++++ submodule-config.h | 1 + submodule.h | 1 + t/t5531-deep-submodule-push.sh | 182 ++++++++++++++++++++++++++++++++++++++++- 7 files changed, 259 insertions(+), 27 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index b4b0194..8c02e43 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -2226,6 +2226,20 @@ push.gpgSign:: override a value from a lower-priority config file. An explicit command-line flag always overrides this config option. +push.recurseSubmodules:: + Make sure all submodule commits used by the revisions to be pushed + are available on a remote-tracking branch. If the value is 'check' + then Git will verify that all submodule commits that changed in the + revisions to be pushed are available on at least one remote of the + submodule. If any commits are missing, the push will be aborted and + exit with non-zero status. If the value is 'on-demand' then all + submodules that changed in the revisions to be pushed will be + pushed. If on-demand was not able to push all necessary revisions + it will also be aborted and exit with non-zero status. If the value + is 'no' then default behavior of ignoring submodules when pushing + is retained. You may override this configuration at time of push by + specifying '--recurse-submodules=check|on-demand|no'. + rebase.stat:: Whether to show a diffstat of what changed upstream since the last rebase. False by default. diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index 85a4d7d..4c775bc 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -257,16 +257,20 @@ origin +master` to force a push to the `master` branch). See the is specified. This flag forces progress status even if the standard error stream is not directed to a terminal. ---recurse-submodules=check|on-demand:: - Make sure all submodule commits used by the revisions to be - pushed are available on a remote-tracking branch. If 'check' is - used Git will verify that all submodule commits that changed in - the revisions to be pushed are available on at least one remote - of the submodule. If any commits are missing the push will be - aborted and exit with non-zero status. If 'on-demand' is used - all submodules that changed in the revisions to be pushed will - be pushed. If on-demand was not able to push all necessary - revisions it will also be aborted and exit with non-zero status. +--no-recurse-submodules:: +--recurse-submodules=check|on-demand|no:: + May be used to make sure all submodule commits used by the + revisions to be pushed are available on a remote-tracking branch. + If 'check' is used Git will verify that all submodule commits that + changed in the revisions to be pushed are available on at least one + remote of the submodule. If any commits are missing the push will + be aborted and exit with non-zero status. If 'on-demand' is used + all submodules that changed in the revisions to be pushed will be + pushed. If on-demand was not able to push all necessary revisions + it will also be aborted and exit with non-zero status. A value of + 'no' or using '--no-recurse-submodules' can be used to override the + push.recurseSubmodules configuration variable when no submodule + recursion is required. --[no-]verify:: Toggle the pre-push hook (see linkgit:githooks[5]). The diff --git a/builtin/push.c b/builtin/push.c index 3bda430..cc29277 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -9,6 +9,7 @@ #include "transport.h" #include "parse-options.h" #include "submodule.h" +#include "submodule-config.h" #include "send-pack.h" static const char * const push_usage[] = { @@ -21,6 +22,7 @@ static int deleterefs; static const char *receivepack; static int verbosity; static int progress = -1; +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static struct push_cas_option cas; @@ -452,22 +454,14 @@ static int do_push(const char *repo, int flags) static int option_parse_recurse_submodules(const struct option *opt, const char *arg, int unset) { - int *flags = opt->value; + int *recurse_submodules = opt->value; - if (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK | - TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND)) - die("%s can only be used once.", opt->long_name); - - if (arg) { - if (!strcmp(arg, "check")) - *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK; - else if (!strcmp(arg, "on-demand")) - *flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND; - else - die("bad %s argument: %s", opt->long_name, arg); - } else - die("option %s needs an argument (check|on-demand)", - opt->long_name); + if (unset) + *recurse_submodules = RECURSE_SUBMODULES_OFF; + else if (arg) + *recurse_submodules = parse_push_recurse_submodules_arg(opt->long_name, arg); + else + die("%s missing parameter", opt->long_name); return 0; } @@ -522,6 +516,10 @@ static int git_push_config(const char *k, const char *v, void *cb) return error("Invalid value for '%s'", k); } } + } else if (!strcmp(k, "push.recursesubmodules")) { + const char *value; + if (!git_config_get_value("push.recursesubmodules", &value)) + recurse_submodules = parse_push_recurse_submodules_arg(k, value); } return git_default_config(k, v, NULL); @@ -549,7 +547,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) 0, CAS_OPT_NAME, &cas, N_("refname>:recurse-on-demand-on-command-line && + git add recurse-on-demand-on-command-line && + git commit -m "Recurse on-demand on command line junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse on-demand on command line for gar/bage" && + git push --recurse-submodules=on-demand ../pub.git master && + # Check that the supermodule commit got there + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master && + # Check that the submodule commit got there too + cd gar/bage && + git diff --quiet origin/master master + ) +' + +test_expect_success 'push succeeds if submodule commit not on remote but using on-demand from config' ' + ( + cd work/gar/bage && + >recurse-on-demand-from-config && + git add recurse-on-demand-from-config && + git commit -m "Recurse on-demand from config junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse on-demand from config for gar/bage" && + git -c push.recurseSubmodules=on-demand push ../pub.git master && + # Check that the supermodule commit got there + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master && + # Check that the submodule commit got there too + cd gar/bage && + git diff --quiet origin/master master + ) +' + +test_expect_success 'push recurse-submodules cmdline overrides config' ' + ( + cd work/gar/bage && + >recurse-check-on-command-line-overriding-config && + git add recurse-check-on-command-line-overriding-config && + git commit -m "Recurse on command-line overridiing config junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse on command-line overriding config for gar/bage" && + test_must_fail git -c push.recurseSubmodules=on-demand push --recurse-submodules=check ../pub.git master && + # Check that the supermodule commit did not get there + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master^ && + # Check that the submodule commit did not get there + (cd gar/bage && git diff --quiet origin/master master^) && + # Now try the reverse which should succeed + git -c push.recurseSubmodules=check push --recurse-submodules=on-demand ../pub.git master && + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master && + (cd gar/bage && git diff --quiet origin/master master) + ) +' + +test_expect_success 'push recurse-submodules on cmdline overrides earlier cmdline' ' + ( + cd work/gar/bage && + >recurse-check-on-command-line-overriding-earlier-command-line && + git add recurse-check-on-command-line-overriding-earlier-command-line && + git commit -m "Recurse on command-line overridiing earlier command-line junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse on command-line overriding earlier command-line for gar/bage" && + test_must_fail git push --recurse-submodules=on-demand --recurse-submodules=check ../pub.git master && + # Check that the supermodule commit did not get there + git fetch ../pub.git && + git diff FETCH_HEAD master^ && + git diff --quiet FETCH_HEAD master^ && + # Check that the submodule commit did not get there + (cd gar/bage && git diff --quiet origin/master master^) && + # But the options in the other order should push the submodule + git push --recurse-submodules=check --recurse-submodules=on-demand ../pub.git master && + # Check that the submodule commit did get there + git fetch ../pub.git && + (cd gar/bage && git diff --quiet origin/master master) + ) +' + +test_expect_success 'push succeeds if submodule commit not on remote using on-demand from cmdline overriding config' ' + ( + cd work/gar/bage && + >recurse-on-demand-on-command-line-overriding-config && + git add recurse-on-demand-on-command-line-overriding-config && + git commit -m "Recurse on-demand on command-line overriding config junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse on-demand on command-line overriding config for gar/bage" && + git -c push.recurseSubmodules=check push --recurse-submodules=on-demand ../pub.git master && + # Check that the supermodule commit got there + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master && + # Check that the submodule commit got there + cd gar/bage && + git diff --quiet origin/master master + ) +' + +test_expect_success 'push succeeds if submodule commit disabling recursion from cmdline overriding config' ' + ( + cd work/gar/bage && + >recurse-disable-on-command-line-overriding-config && + git add recurse-disable-on-command-line-overriding-config && + git commit -m "Recurse disable on command-line overriding config junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse disable on command-line overriding config for gar/bage" && + git -c push.recurseSubmodules=check push --recurse-submodules=no ../pub.git master && + # Check that the supermodule commit got there + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master && + # But that the submodule commit did not + ( cd gar/bage && git diff --quiet origin/master master^ ) && + # Now push it to avoid confusing future tests + git push --recurse-submodules=on-demand ../pub.git master + ) +' + +test_expect_success 'push succeeds if submodule commit disabling recursion from cmdline (alternative form) overriding config' ' + ( + cd work/gar/bage && + >recurse-disable-on-command-line-alt-overriding-config && + git add recurse-disable-on-command-line-alt-overriding-config && + git commit -m "Recurse disable on command-line alternative overriding config junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse disable on command-line alternative overriding config for gar/bage" && + git -c push.recurseSubmodules=check push --no-recurse-submodules ../pub.git master && + # Check that the supermodule commit got there + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master && + # But that the submodule commit did not + ( cd gar/bage && git diff --quiet origin/master master^ ) && + # Now push it to avoid confusing future tests + git push --recurse-submodules=on-demand ../pub.git master + ) +' + +test_expect_success 'push fails if recurse submodules option passed as yes' ' + ( + cd work/gar/bage && + >recurse-push-fails-if-recurse-submodules-passed-as-yes && + git add recurse-push-fails-if-recurse-submodules-passed-as-yes && + git commit -m "Recurse push fails if recurse submodules option passed as yes" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse push fails if recurse submodules option passed as yes for gar/bage" && + test_must_fail git push --recurse-submodules=yes ../pub.git master && + test_must_fail git -c push.recurseSubmodules=yes push ../pub.git master && + git push --recurse-submodules=on-demand ../pub.git master + ) +' + test_expect_success 'push fails when commit on multiple branches if one branch has no remote' ' ( cd work/gar/bage && -- 2.1.4