builtin/read-tree: add --recurse-submodules switch
authorStefan Beller <sbeller@google.com>
Tue, 14 Mar 2017 21:46:42 +0000 (14:46 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 16 Mar 2017 21:07:16 +0000 (14:07 -0700)
A new known failure mode is introduced[1], which is actually not
a failure but a feature in read-tree. Unlike checkout for which
the recursive submodule tests were originally written, read-tree does
warn about ignored untracked files that would be overwritten.
For the sake of keeping the test library for submodules generic, just
mark the test as a failure.

[1] KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-read-tree.txt
builtin/read-tree.c
t/lib-submodule-update.sh
t/t1013-read-tree-submodule.sh

index fa1d557..ed9d63e 100644 (file)
@@ -115,6 +115,12 @@ OPTIONS
        directories the index file and index output file are
        located in.
 
+--[no-]recurse-submodules::
+       Using --recurse-submodules will update the content of all initialized
+       submodules according to the commit recorded in the superproject by
+       calling read-tree recursively, also setting the submodules HEAD to be
+       detached at that commit.
+
 --no-sparse-checkout::
        Disable sparse checkout support even if `core.sparseCheckout`
        is true.
index 8ba64bc..23e212e 100644 (file)
 #include "builtin.h"
 #include "parse-options.h"
 #include "resolve-undo.h"
+#include "submodule.h"
+#include "submodule-config.h"
 
 static int nr_trees;
 static int read_empty;
 static struct tree *trees[MAX_UNPACK_TREES];
+static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
 
 static int list_tree(unsigned char *sha1)
 {
@@ -96,6 +99,23 @@ static int debug_merge(const struct cache_entry * const *stages,
        return 0;
 }
 
+static int option_parse_recurse_submodules(const struct option *opt,
+                                          const char *arg, int unset)
+{
+       if (unset) {
+               recurse_submodules = RECURSE_SUBMODULES_OFF;
+               return 0;
+       }
+       if (arg)
+               recurse_submodules =
+                       parse_update_recurse_submodules_arg(opt->long_name,
+                                                           arg);
+       else
+               recurse_submodules = RECURSE_SUBMODULES_ON;
+
+       return 0;
+}
+
 static struct lock_file lock_file;
 
 int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
@@ -137,6 +157,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
                         N_("skip applying sparse checkout filter")),
                OPT_BOOL(0, "debug-unpack", &opts.debug_unpack,
                         N_("debug unpack-trees")),
+               { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
+                           "checkout", "control recursive updating of submodules",
+                           PARSE_OPT_OPTARG, option_parse_recurse_submodules },
                OPT_END()
        };
 
@@ -152,6 +175,12 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
 
        hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
 
+       if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) {
+               gitmodules_config();
+               git_config(submodule_config, NULL);
+               set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON);
+       }
+
        prefix_set = opts.prefix ? 1 : 0;
        if (1 < opts.merge + opts.reset + prefix_set)
                die("Which one? -m, --reset, or --prefix?");
index 4e775a3..fb4f7b0 100755 (executable)
@@ -792,6 +792,11 @@ test_submodule_switch_recursing () {
        then
                RESULTR=failure
        fi
+       RESULTOI=success
+       if test "$KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED" = 1
+       then
+               RESULTOI=failure
+       fi
        ######################### Appearing submodule #########################
        # Switching to a commit letting a submodule appear checks it out ...
        test_expect_success "$command: added submodule is checked out" '
@@ -832,7 +837,7 @@ test_submodule_switch_recursing () {
                )
        '
        # ... but an ignored file is fine.
-       test_expect_success "$command: added submodule removes an untracked ignored file" '
+       test_expect_$RESULTOI "$command: added submodule removes an untracked ignored file" '
                test_when_finished "rm submodule_update/.git/info/exclude" &&
                prolog &&
                reset_work_tree_to_interested no_submodule &&
index 20526ae..de1ba02 100755 (executable)
@@ -5,6 +5,14 @@ test_description='read-tree can handle submodules'
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-submodule-update.sh
 
+KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED=1
+KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1
+KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1
+
+test_submodule_switch_recursing "git read-tree --recurse-submodules -u -m"
+
+test_submodule_forced_switch_recursing "git read-tree --recurse-submodules -u --reset"
+
 test_submodule_switch "git read-tree -u -m"
 
 test_submodule_forced_switch "git read-tree -u --reset"