From 175f6e59f6c74d5f8c80fe3a6678915cc5d35cb6 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 25 Aug 2010 12:34:57 +0200 Subject: [PATCH 1/3] checkout: respect diff.ignoreSubmodules setting When 'git checkout' reports uncommitted changes, it also does so for submodules. The default mode is now to look really hard into submodules, not only for different commits, but also for modified files. Since this can be pretty expensive when there are a lot (and large) submodules, there is the diff.ignoreSubmodules option. Let's respect that setting when 'git checkout' reports the uncommitted changes, since it does nothing else than a 'git diff --name-status'. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin/checkout.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index 1994be92c6..e73bfe3403 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -18,6 +18,7 @@ #include "xdiff-interface.h" #include "ll-merge.h" #include "resolve-undo.h" +#include "submodule.h" static const char * const checkout_usage[] = { "git checkout [options] ", @@ -36,6 +37,7 @@ struct checkout_opts { const char *new_orphan_branch; int new_branch_log; enum branch_track track; + struct diff_options diff_options; }; static int post_checkout_hook(struct commit *old, struct commit *new, @@ -274,12 +276,13 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec, return errs; } -static void show_local_changes(struct object *head) +static void show_local_changes(struct object *head, struct diff_options *opts) { struct rev_info rev; /* I think we want full paths, even if we're in a subdirectory. */ init_revisions(&rev, NULL); rev.abbrev = 0; + rev.diffopt.flags = opts->flags; rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS; if (diff_setup_done(&rev.diffopt) < 0) die("diff_setup_done failed"); @@ -456,7 +459,7 @@ static int merge_working_tree(struct checkout_opts *opts, die("unable to write new index file"); if (!opts->force && !opts->quiet) - show_local_changes(&new->commit->object); + show_local_changes(&new->commit->object, &opts->diff_options); return 0; } @@ -600,7 +603,12 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new) static int git_checkout_config(const char *var, const char *value, void *cb) { - return git_xmerge_config(var, value, cb); + if (!strcmp(var, "diff.ignoresubmodules")) { + struct checkout_opts *opts = cb; + handle_ignore_submodules_arg(&opts->diff_options, value); + return 0; + } + return git_xmerge_config(var, value, NULL); } static int interactive_checkout(const char *revision, const char **pathspec, @@ -681,7 +689,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) memset(&opts, 0, sizeof(opts)); memset(&new, 0, sizeof(new)); - git_config(git_checkout_config, NULL); + git_config(git_checkout_config, &opts); opts.track = BRANCH_TRACK_UNSPECIFIED; From 62ed0096423b098f9736f5397edad8aa7bf50210 Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Sat, 28 Aug 2010 16:49:25 +0200 Subject: [PATCH 2/3] checkout: Add test for diff.ignoreSubmodules While at it, document that checkout uses this flag too in the Documentation. Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- Documentation/config.txt | 3 ++- t/t2013-checkout-submodule.sh | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index cf5562192d..01b7e0ae6c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -829,7 +829,8 @@ diff.renames:: diff.ignoreSubmodules:: Sets the default value of --ignore-submodules. Note that this affects only 'git diff' Porcelain, and not lower level 'diff' - commands such as 'git diff-files'. + commands such as 'git diff-files'. 'git checkout' also honors + this setting when reporting uncommitted changes. diff.suppressBlankEmpty:: A boolean to inhibit the standard behavior of printing a space diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh index fda3f0af7e..3beb0b3ed7 100755 --- a/t/t2013-checkout-submodule.sh +++ b/t/t2013-checkout-submodule.sh @@ -39,4 +39,11 @@ test_expect_success '"checkout " updates the index only' ' git diff-files --quiet ' +test_expect_success '"checkout " honors diff.ignoreSubmodules' ' + git config diff.ignoreSubmodules dirty && + echo x> submodule/untracked && + git checkout HEAD >actual 2>&1 && + ! test -s actual +' + test_done From 23b4c7bcc58431beaf9c870a2d6b2ad4fb088a9f Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Sat, 28 Aug 2010 16:50:07 +0200 Subject: [PATCH 3/3] checkout: Use submodule.*.ignore settings from .git/config and .gitmodules For "git status" and the diff family the submodule.*.ignore settings from .git/config and .gitmodules can be used to override the default set via diff.ignoreSubmodules on a per-submodule basis. Let's do this consistently and teach checkout to use these settings too. Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- builtin/checkout.c | 5 +++++ t/t2013-checkout-submodule.sh | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/builtin/checkout.c b/builtin/checkout.c index e73bfe3403..829442932f 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -608,6 +608,10 @@ static int git_checkout_config(const char *var, const char *value, void *cb) handle_ignore_submodules_arg(&opts->diff_options, value); return 0; } + + if (!prefixcmp(var, "submodule.")) + return parse_submodule_config_option(var, value); + return git_xmerge_config(var, value, NULL); } @@ -689,6 +693,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) memset(&opts, 0, sizeof(opts)); memset(&new, 0, sizeof(new)); + gitmodules_config(); git_config(git_checkout_config, &opts); opts.track = BRANCH_TRACK_UNSPECIFIED; diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh index 3beb0b3ed7..70edbb33e2 100755 --- a/t/t2013-checkout-submodule.sh +++ b/t/t2013-checkout-submodule.sh @@ -46,4 +46,20 @@ test_expect_success '"checkout " honors diff.ignoreSubmodules' ' ! test -s actual ' +test_expect_success '"checkout " honors submodule.*.ignore from .gitmodules' ' + git config diff.ignoreSubmodules none && + git config -f .gitmodules submodule.submodule.path submodule && + git config -f .gitmodules submodule.submodule.ignore untracked && + git checkout HEAD >actual 2>&1 && + ! test -s actual +' + +test_expect_success '"checkout " honors submodule.*.ignore from .git/config' ' + git config -f .gitmodules submodule.submodule.ignore none && + git config submodule.submodule.path submodule && + git config submodule.submodule.ignore all && + git checkout HEAD >actual 2>&1 && + ! test -s actual +' + test_done