From aee9c7d6540fe6f66fbbe7be420caa26ae0fa2d9 Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Fri, 6 Aug 2010 00:39:25 +0200 Subject: [PATCH 1/4] Submodules: Add the new "ignore" config option for diff and status The new "ignore" config option controls the default behavior for "git status" and the diff family. It specifies under what circumstances they consider submodules as modified and can be set separately for each submodule. The command line option "--ignore-submodules=" has been extended to accept the new parameter "none" for both status and diff. Users that chose submodules to get rid of long work tree scanning times might want to set the "dirty" option for those submodules. This brings back the pre 1.7.0 behavior, where submodule work trees were never scanned for modifications. By using "--ignore-submodules=none" on the command line the status and diff commands can be told to do a full scan. This option can be set to the following values (which have the same name and meaning as for the "--ignore-submodules" option of status and diff): "all": All changes to the submodule will be ignored. "dirty": Only differences of the commit recorded in the superproject and the submodules HEAD will be considered modifications, all changes to the work tree of the submodule will be ignored. When using this value, the submodule will not be scanned for work tree changes at all, leading to a performance benefit on large submodules. "untracked": Only untracked files in the submodules work tree are ignored, a changed HEAD and/or modified files in the submodule will mark it as modified. "none" (which is the default): Either untracked or modified files in a submodules work tree or a difference between the subdmodules HEAD and the commit recorded in the superproject will make it show up as changed. This value is added as a new parameter for the "--ignore-submodules" option of the diff family and "git status" so the user can override the settings in the configuration. Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- Documentation/config.txt | 10 ++++ Documentation/diff-options.txt | 6 +- Documentation/git-status.txt | 6 +- diff-lib.c | 15 +++-- diff.c | 35 ++++++++++-- diff.h | 1 + submodule.c | 57 ++++++++++++++++++- submodule.h | 3 + t/t4027-diff-submodule.sh | 76 +++++++++++++++++++++++++ t/t7508-status.sh | 100 +++++++++++++++++++++++++++++++-- wt-status.c | 8 ++- 11 files changed, 297 insertions(+), 20 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index e75434b3e..5ca09aed9 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1743,6 +1743,16 @@ submodule..update:: URL and other values found in the `.gitmodules` file. See linkgit:git-submodule[1] and linkgit:gitmodules[5] for details. +submodule..ignore:: + Defines under what circumstances "git status" and the diff family show + a submodule as modified. When set to "all", it will never be considered + modified, "dirty" will ignore all changes to the submodules work tree and + takes only differences between the HEAD of the submodule and the commit + recorded in the superproject into account. "untracked" will additionally + let submodules with modified tracked files in their work tree show up. + Using "none" (the default when this option is not set) also shows + submodules that have untracked files in their work tree as changed. + tar.umask:: This variable can be used to restrict the permission bits of tar archive entries. The default is 0002, which turns off the diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 2371262b1..9cf750662 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -330,7 +330,11 @@ endif::git-format-patch[] --ignore-submodules[=]:: Ignore changes to submodules in the diff generation. can be - either "untracked", "dirty" or "all", which is the default. When + either "none", "untracked", "dirty" or "all", which is the default + Using "none" will consider the submodule modified when it either contains + untracked or modified files or its HEAD differs from the commit recorded + in the superproject and can be used to override any settings of the + 'ignore' option in linkgit:git-config[1]. When "untracked" is used submodules are not considered dirty when they only contain untracked content (but they are still scanned for modified content). Using "dirty" ignores all changes to the work tree of submodules, diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 2fd054c10..a7a5d7941 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -55,7 +55,11 @@ specified. --ignore-submodules[=]:: Ignore changes to submodules when looking for changes. can be - either "untracked", "dirty" or "all", which is the default. When + either "none", "untracked", "dirty" or "all", which is the default. + Using "none" will consider the submodule modified when it either contains + untracked or modified files or its HEAD differs from the commit recorded + in the superproject and can be used to override any settings of the + 'ignore' option in linkgit:git-config[1]. When "untracked" is used submodules are not considered dirty when they only contain untracked content (but they are still scanned for modified content). Using "dirty" ignores all changes to the work tree of submodules, diff --git a/diff-lib.c b/diff-lib.c index 8b8978ae6..392ce2bef 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -68,11 +68,16 @@ static int match_stat_with_submodule(struct diff_options *diffopt, unsigned ce_option, unsigned *dirty_submodule) { int changed = ce_match_stat(ce, st, ce_option); - if (S_ISGITLINK(ce->ce_mode) - && !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES) - && !DIFF_OPT_TST(diffopt, IGNORE_DIRTY_SUBMODULES) - && (!changed || DIFF_OPT_TST(diffopt, DIRTY_SUBMODULES))) { - *dirty_submodule = is_submodule_modified(ce->name, DIFF_OPT_TST(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES)); + if (S_ISGITLINK(ce->ce_mode)) { + unsigned orig_flags = diffopt->flags; + if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG)) + set_diffopt_flags_from_submodule_config(diffopt, ce->name); + if (DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES)) + changed = 0; + else if (!DIFF_OPT_TST(diffopt, IGNORE_DIRTY_SUBMODULES) + && (!changed || DIFF_OPT_TST(diffopt, DIRTY_SUBMODULES))) + *dirty_submodule = is_submodule_modified(ce->name, DIFF_OPT_TST(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES)); + diffopt->flags = orig_flags; } return changed; } diff --git a/diff.c b/diff.c index 17873f3d9..820604731 100644 --- a/diff.c +++ b/diff.c @@ -141,6 +141,9 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return 0; } + if (!prefixcmp(var, "submodule.")) + return parse_submodule_config_option(var, value); + return git_color_default_config(var, value, cb); } @@ -3166,11 +3169,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, ALLOW_TEXTCONV); else if (!strcmp(arg, "--no-textconv")) DIFF_OPT_CLR(options, ALLOW_TEXTCONV); - else if (!strcmp(arg, "--ignore-submodules")) + else if (!strcmp(arg, "--ignore-submodules")) { + DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(options, "all"); - else if (!prefixcmp(arg, "--ignore-submodules=")) + } else if (!prefixcmp(arg, "--ignore-submodules=")) { + DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(options, arg + 20); - else if (!strcmp(arg, "--submodule")) + } else if (!strcmp(arg, "--submodule")) DIFF_OPT_SET(options, SUBMODULE_LOG); else if (!prefixcmp(arg, "--submodule=")) { if (!strcmp(arg + 12, "log")) @@ -4103,6 +4108,24 @@ int diff_result_code(struct diff_options *opt, int status) return result; } +/* + * Shall changes to this submodule be ignored? + * + * Submodule changes can be configured to be ignored separately for each path, + * but that configuration can be overridden from the command line. + */ +static int is_submodule_ignored(const char *path, struct diff_options *options) +{ + int ignored = 0; + unsigned orig_flags = options->flags; + if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG)) + set_diffopt_flags_from_submodule_config(options, path); + if (DIFF_OPT_TST(options, IGNORE_SUBMODULES)) + ignored = 1; + options->flags = orig_flags; + return ignored; +} + void diff_addremove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, @@ -4110,7 +4133,7 @@ void diff_addremove(struct diff_options *options, { struct diff_filespec *one, *two; - if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode)) + if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options)) return; /* This may look odd, but it is a preparation for @@ -4157,8 +4180,8 @@ void diff_change(struct diff_options *options, { struct diff_filespec *one, *two; - if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode) - && S_ISGITLINK(new_mode)) + if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) && + is_submodule_ignored(concatpath, options)) return; if (DIFF_OPT_TST(options, REVERSE_DIFF)) { diff --git a/diff.h b/diff.h index 063d10ac2..53ad34546 100644 --- a/diff.h +++ b/diff.h @@ -77,6 +77,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) #define DIFF_OPT_DIRTY_SUBMODULES (1 << 24) #define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25) #define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26) +#define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) diff --git a/submodule.c b/submodule.c index 61cb6e21d..ff2863074 100644 --- a/submodule.c +++ b/submodule.c @@ -6,6 +6,10 @@ #include "revision.h" #include "run-command.h" #include "diffcore.h" +#include "string-list.h" + +struct string_list config_name_for_path; +struct string_list config_ignore_for_name; static int add_submodule_odb(const char *path) { @@ -46,6 +50,57 @@ static int add_submodule_odb(const char *path) return ret; } +void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, + const char *path) +{ + struct string_list_item *path_option, *ignore_option; + path_option = unsorted_string_list_lookup(&config_name_for_path, path); + if (path_option) { + ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, path_option->util); + if (ignore_option) + handle_ignore_submodules_arg(diffopt, ignore_option->util); + } +} + +int parse_submodule_config_option(const char *var, const char *value) +{ + int len; + struct string_list_item *config; + struct strbuf submodname = STRBUF_INIT; + + var += 10; /* Skip "submodule." */ + + len = strlen(var); + if ((len > 5) && !strcmp(var + len - 5, ".path")) { + strbuf_add(&submodname, var, len - 5); + config = unsorted_string_list_lookup(&config_name_for_path, value); + if (config) + free(config->util); + else + config = string_list_append(&config_name_for_path, xstrdup(value)); + config->util = strbuf_detach(&submodname, NULL); + strbuf_release(&submodname); + } else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) { + if (strcmp(value, "untracked") && strcmp(value, "dirty") && + strcmp(value, "all") && strcmp(value, "none")) { + warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var); + return 0; + } + + strbuf_add(&submodname, var, len - 7); + config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf); + if (config) + free(config->util); + else + config = string_list_append(&config_ignore_for_name, + strbuf_detach(&submodname, NULL)); + strbuf_release(&submodname); + config->util = xstrdup(value); + return 0; + } + return 0; +} + void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *arg) { @@ -55,7 +110,7 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt, DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES); else if (!strcmp(arg, "dirty")) DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES); - else + else if (strcmp(arg, "none")) die("bad --ignore-submodules argument: %s", arg); } diff --git a/submodule.h b/submodule.h index 6fd3bb407..185a5ce6c 100644 --- a/submodule.h +++ b/submodule.h @@ -3,6 +3,9 @@ struct diff_options; +void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, + const char *path); +int parse_submodule_config_option(const char *var, const char *value); void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *); void show_submodule_summary(FILE *f, const char *path, unsigned char one[20], unsigned char two[20], diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 1bd8e5ee3..683672851 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -114,6 +114,31 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)' ! test -s actual4 ' +test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.git/config]' ' + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config submodule.subname.ignore all && + git diff HEAD >actual2 && + ! test -s actual2 && + git config submodule.subname.ignore untracked && + git diff HEAD >actual3 && + sed -e "1,/^@@/d" actual3 >actual3.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual3.body && + git config submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git diff HEAD --ignore-submodules=none >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname +' + test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' ' ( cd sub && @@ -146,6 +171,57 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)' ! test -s actual4 ' +test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.git/config]' ' + git config submodule.subname.ignore all && + git config submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config submodule.subname.ignore untracked && + git diff HEAD >actual3 && + ! test -s actual3 && + git config submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git diff --ignore-submodules=none HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname +' + +test_expect_success 'git diff between submodule commits' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git diff --ignore-submodules=dirty HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git diff --ignore-submodules HEAD^..HEAD >actual && + ! test -s actual +' + +test_expect_success 'git diff between submodule commits [.git/config]' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config submodule.subname.ignore dirty && + git config submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config submodule.subname.ignore all && + git diff HEAD^..HEAD >actual && + ! test -s actual && + git diff --ignore-submodules=dirty HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + git config --remove-section submodule.subname +' + test_expect_success 'git diff (empty submodule dir)' ' : >empty && rm -rf sub/* sub/.git && diff --git a/t/t7508-status.sh b/t/t7508-status.sh index a72fe3ae6..57bf2ee27 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -808,24 +808,38 @@ test_expect_success POSIXPERM 'status succeeds in a read-only repository' ' (exit $status) ' +(cd sm && echo > bar && git add bar && git commit -q -m 'Add bar' && cd .. && git add sm) +new_head=$(cd sm && git rev-parse --short=7 --verify HEAD) +touch .gitmodules + cat > expect << EOF # On branch master +# Changes to be committed: +# (use "git reset HEAD ..." to unstage) +# +# modified: sm +# # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: dir1/modified # +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# # Untracked files: # (use "git add ..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked # expect # output # untracked -no changes added to commit (use "git add" and/or "git commit -a") EOF test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' ' @@ -834,19 +848,48 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un test_cmp expect output ' +test_expect_success '.git/config ignore=untracked suppresses submodules with untracked content' ' + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname +' + test_expect_success '--ignore-submodules=dirty suppresses submodules with untracked content' ' git status --ignore-submodules=dirty > output && test_cmp expect output ' +test_expect_success '.git/config ignore=dirty suppresses submodules with untracked content' ' + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname +' + test_expect_success '--ignore-submodules=dirty suppresses submodules with modified content' ' echo modified > sm/foo && git status --ignore-submodules=dirty > output && test_cmp expect output ' +test_expect_success '.git/config ignore=dirty suppresses submodules with modified content' ' + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname +' + cat > expect << EOF # On branch master +# Changes to be committed: +# (use "git reset HEAD ..." to unstage) +# +# modified: sm +# # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) @@ -855,16 +898,21 @@ cat > expect << EOF # modified: dir1/modified # modified: sm (modified content) # +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# # Untracked files: # (use "git add ..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked # expect # output # untracked -no changes added to commit (use "git add" and/or "git commit -a") EOF test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" ' @@ -872,10 +920,23 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodules w test_cmp expect output ' +test_expect_success ".git/config ignore=untracked doesn't suppress submodules with modified content" ' + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname +' + head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 --verify HEAD) cat > expect << EOF # On branch master +# Changes to be committed: +# (use "git reset HEAD ..." to unstage) +# +# modified: sm +# # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) @@ -883,21 +944,26 @@ cat > expect << EOF # modified: dir1/modified # modified: sm (new commits) # +# Submodule changes to be committed: +# +# * sm $head...$new_head (1): +# > Add bar +# # Submodules changed but not updated: # -# * sm $head...$head2 (1): +# * sm $new_head...$head2 (1): # > 2nd commit # # Untracked files: # (use "git add ..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked # expect # output # untracked -no changes added to commit (use "git add" and/or "git commit -a") EOF test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" ' @@ -905,11 +971,28 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodule su test_cmp expect output ' +test_expect_success ".git/config ignore=untracked doesn't suppress submodule summary" ' + git config --add submodule.subname.ignore untracked && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname +' + test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" ' git status --ignore-submodules=dirty > output && test_cmp expect output ' +test_expect_success ".git/config ignore=dirty doesn't suppress submodule summary" ' + git config --add submodule.subname.ignore dirty && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname +' + + cat > expect << EOF # On branch master # Changed but not updated: @@ -921,6 +1004,7 @@ cat > expect << EOF # Untracked files: # (use "git add ..." to include in what will be committed) # +# .gitmodules # dir1/untracked # dir2/modified # dir2/untracked @@ -935,4 +1019,12 @@ test_expect_success "--ignore-submodules=all suppresses submodule summary" ' test_cmp expect output ' +test_expect_failure '.git/config ignore=all suppresses submodule summary' ' + git config --add submodule.subname.ignore all && + git config --add submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config --remove-section submodule.subname +' + test_done diff --git a/wt-status.c b/wt-status.c index 2f9e33c8f..54b6b03b9 100644 --- a/wt-status.c +++ b/wt-status.c @@ -313,8 +313,10 @@ static void wt_status_collect_changes_worktree(struct wt_status *s) DIFF_OPT_SET(&rev.diffopt, DIRTY_SUBMODULES); if (!s->show_untracked_files) DIFF_OPT_SET(&rev.diffopt, IGNORE_UNTRACKED_IN_SUBMODULES); - if (s->ignore_submodule_arg) + if (s->ignore_submodule_arg) { + DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg); + } rev.diffopt.format_callback = wt_status_collect_changed_cb; rev.diffopt.format_callback_data = s; rev.prune_data = s->pathspec; @@ -331,8 +333,10 @@ static void wt_status_collect_changes_index(struct wt_status *s) opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference; setup_revisions(0, NULL, &rev, &opt); - if (s->ignore_submodule_arg) + if (s->ignore_submodule_arg) { + DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg); + } rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = wt_status_collect_updated_cb; From 302ad7a9930a34413418b6436f96826070367647 Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Fri, 6 Aug 2010 00:40:48 +0200 Subject: [PATCH 2/4] Submodules: Use "ignore" settings from .gitmodules too for diff and status The .gitmodules file is parsed for "submodule..ignore" entries before looking for them in .git/config. Thus settings found in .git/config will override those from .gitmodules, thereby allowing the local developer to ignore settings given by the remote side while also letting upstream set defaults for those users who don't have special needs. Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- Documentation/config.txt | 3 ++ Documentation/diff-options.txt | 2 +- Documentation/git-status.txt | 2 +- Documentation/gitmodules.txt | 15 ++++++ builtin/commit.c | 2 + builtin/diff-files.c | 2 + builtin/diff-index.c | 2 + builtin/diff-tree.c | 2 + builtin/diff.c | 2 + submodule.c | 19 +++++++ submodule.h | 1 + t/t4027-diff-submodule.sh | 76 ++++++++++++++++++++++++++++ t/t7508-status.sh | 91 +++++++++++++++++++++++++++++++--- 13 files changed, 209 insertions(+), 10 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 5ca09aed9..c88a63764 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1752,6 +1752,9 @@ submodule..ignore:: let submodules with modified tracked files in their work tree show up. Using "none" (the default when this option is not set) also shows submodules that have untracked files in their work tree as changed. + This setting overrides any setting made in .gitmodules for this submodule, + both settings can be overriden on the command line by using the + "--ignore-submodule" option. tar.umask:: This variable can be used to restrict the permission bits of diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 9cf750662..faa467b03 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -334,7 +334,7 @@ endif::git-format-patch[] Using "none" will consider the submodule modified when it either contains untracked or modified files or its HEAD differs from the commit recorded in the superproject and can be used to override any settings of the - 'ignore' option in linkgit:git-config[1]. When + 'ignore' option in linkgit:git-config[1] or linkgit:gitmodules[5]. When "untracked" is used submodules are not considered dirty when they only contain untracked content (but they are still scanned for modified content). Using "dirty" ignores all changes to the work tree of submodules, diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index a7a5d7941..dae190a5f 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -59,7 +59,7 @@ specified. Using "none" will consider the submodule modified when it either contains untracked or modified files or its HEAD differs from the commit recorded in the superproject and can be used to override any settings of the - 'ignore' option in linkgit:git-config[1]. When + 'ignore' option in linkgit:git-config[1] or linkgit:gitmodules[5]. When "untracked" is used submodules are not considered dirty when they only contain untracked content (but they are still scanned for modified content). Using "dirty" ignores all changes to the work tree of submodules, diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt index 72a13d18e..8ae107da2 100644 --- a/Documentation/gitmodules.txt +++ b/Documentation/gitmodules.txt @@ -44,6 +44,21 @@ submodule..update:: This config option is overridden if 'git submodule update' is given the '--merge' or '--rebase' options. +submodule..ignore:: + Defines under what circumstances "git status" and the diff family show + a submodule as modified. When set to "all", it will never be considered + modified, "dirty" will ignore all changes to the submodules work tree and + takes only differences between the HEAD of the submodule and the commit + recorded in the superproject into account. "untracked" will additionally + let submodules with modified tracked files in their work tree show up. + Using "none" (the default when this option is not set) also shows + submodules that have untracked files in their work tree as changed. + If this option is also present in the submodules entry in .git/config of + the superproject, the setting there will override the one found in + .gitmodules. + Both settings can be overriden on the command line by using the + "--ignore-submodule" option. + EXAMPLES -------- diff --git a/builtin/commit.c b/builtin/commit.c index a78dbd83b..9456f4a58 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -25,6 +25,7 @@ #include "rerere.h" #include "unpack-trees.h" #include "quote.h" +#include "submodule.h" static const char * const builtin_commit_usage[] = { "git commit [options] [--] ...", @@ -1073,6 +1074,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) status_format = STATUS_FORMAT_PORCELAIN; wt_status_prepare(&s); + gitmodules_config(); git_config(git_status_config, &s); in_merge = file_exists(git_path("MERGE_HEAD")); argc = parse_options(argc, argv, prefix, diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 5b64011de..951c7c899 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -8,6 +8,7 @@ #include "commit.h" #include "revision.h" #include "builtin.h" +#include "submodule.h" static const char diff_files_usage[] = "git diff-files [-q] [-0/-1/2/3 |-c|--cc] [] [...]" @@ -20,6 +21,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) unsigned options = 0; init_revisions(&rev, prefix); + gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; diff --git a/builtin/diff-index.c b/builtin/diff-index.c index 04837494f..2eb32bd9d 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -3,6 +3,7 @@ #include "commit.h" #include "revision.h" #include "builtin.h" +#include "submodule.h" static const char diff_cache_usage[] = "git diff-index [-m] [--cached] " @@ -17,6 +18,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) int result; init_revisions(&rev, prefix); + gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 3c78bda56..0d2a3e9fa 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -3,6 +3,7 @@ #include "commit.h" #include "log-tree.h" #include "builtin.h" +#include "submodule.h" static struct rev_info log_tree_opt; @@ -112,6 +113,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) int read_stdin = 0; init_revisions(opt, prefix); + gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ opt->abbrev = 0; opt->diff = 1; diff --git a/builtin/diff.c b/builtin/diff.c index 89ae89cde..a43d32636 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -13,6 +13,7 @@ #include "revision.h" #include "log-tree.h" #include "builtin.h" +#include "submodule.h" struct blobinfo { unsigned char sha1[20]; @@ -279,6 +280,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) */ prefix = setup_git_directory_gently(&nongit); + gitmodules_config(); git_config(git_diff_ui_config, NULL); if (diff_use_color_default == -1) diff --git a/submodule.c b/submodule.c index ff2863074..dc0f95b73 100644 --- a/submodule.c +++ b/submodule.c @@ -62,6 +62,25 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, } } +static int submodule_config(const char *var, const char *value, void *cb) +{ + if (!prefixcmp(var, "submodule.")) + return parse_submodule_config_option(var, value); + return 0; +} + +void gitmodules_config(void) +{ + const char *work_tree = get_git_work_tree(); + if (work_tree) { + struct strbuf gitmodules_path = STRBUF_INIT; + strbuf_addstr(&gitmodules_path, work_tree); + strbuf_addstr(&gitmodules_path, "/.gitmodules"); + git_config_from_file(submodule_config, gitmodules_path.buf, NULL); + strbuf_release(&gitmodules_path); + } +} + int parse_submodule_config_option(const char *var, const char *value) { int len; diff --git a/submodule.h b/submodule.h index 185a5ce6c..8ac4037b5 100644 --- a/submodule.h +++ b/submodule.h @@ -5,6 +5,7 @@ struct diff_options; void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, const char *path); +void gitmodules_config(); int parse_submodule_config_option(const char *var, const char *value); void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *); void show_submodule_summary(FILE *f, const char *path, diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 683672851..1bc6e77a0 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -139,6 +139,36 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) git config --remove-section submodule.subname ' +test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.gitmodules]' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config -f .gitmodules submodule.subname.ignore all && + git config -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config -f .gitmodules submodule.subname.ignore untracked && + git diff HEAD >actual3 && + sed -e "1,/^@@/d" actual3 >actual3.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual3.body && + git config -f .gitmodules submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + rm .gitmodules +' + test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' ' ( cd sub && @@ -189,6 +219,28 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) git config --remove-section submodule.subname ' +test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.gitmodules]' ' + git config --add -f .gitmodules submodule.subname.ignore all && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD >actual2 && + ! test -s actual2 && + git config -f .gitmodules submodule.subname.ignore untracked && + git diff HEAD >actual3 && + ! test -s actual3 && + git config -f .gitmodules submodule.subname.ignore dirty && + git diff HEAD >actual4 && + ! test -s actual4 && + git config submodule.subname.ignore none && + git config submodule.subname.path sub && + git diff HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subprev $subprev-dirty && + test_cmp expect.body actual.body && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + rm .gitmodules +' + test_expect_success 'git diff between submodule commits' ' git diff HEAD^..HEAD >actual && sed -e "1,/^@@/d" actual >actual.body && @@ -222,6 +274,30 @@ test_expect_success 'git diff between submodule commits [.git/config]' ' git config --remove-section submodule.subname ' +test_expect_success 'git diff between submodule commits [.gitmodules]' ' + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + test_cmp expect.body actual.body && + git config -f .gitmodules submodule.subname.ignore all && + git diff HEAD^..HEAD >actual && + ! test -s actual && + git config submodule.subname.ignore dirty && + git config submodule.subname.path sub && + git diff HEAD^..HEAD >actual && + sed -e "1,/^@@/d" actual >actual.body && + expect_from_to >expect.body $subtip $subprev && + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname && + rm .gitmodules +' + test_expect_success 'git diff (empty submodule dir)' ' : >empty && rm -rf sub/* sub/.git && diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 57bf2ee27..1aae76261 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -848,12 +848,23 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un test_cmp expect output ' +test_expect_success '.gitmodules ignore=untracked suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_success '.git/config ignore=untracked suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore untracked && git config --add submodule.subname.path sm && git status > output && test_cmp expect output && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config --remove-section -f .gitmodules submodule.subname ' test_expect_success '--ignore-submodules=dirty suppresses submodules with untracked content' ' @@ -861,12 +872,23 @@ test_expect_success '--ignore-submodules=dirty suppresses submodules with untrac test_cmp expect output ' +test_expect_success '.gitmodules ignore=dirty suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_success '.git/config ignore=dirty suppresses submodules with untracked content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore dirty && git config --add submodule.subname.path sm && git status > output && test_cmp expect output && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname ' test_expect_success '--ignore-submodules=dirty suppresses submodules with modified content' ' @@ -875,12 +897,23 @@ test_expect_success '--ignore-submodules=dirty suppresses submodules with modifi test_cmp expect output ' +test_expect_success '.gitmodules ignore=dirty suppresses submodules with modified content' ' + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_success '.git/config ignore=dirty suppresses submodules with modified content' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore dirty && git config --add submodule.subname.path sm && git status > output && test_cmp expect output && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname ' cat > expect << EOF @@ -920,12 +953,23 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodules w test_cmp expect output ' +test_expect_success ".gitmodules ignore=untracked doesn't suppress submodules with modified content" ' + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_success ".git/config ignore=untracked doesn't suppress submodules with modified content" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore untracked && git config --add submodule.subname.path sm && git status > output && test_cmp expect output && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname ' head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 --verify HEAD) @@ -971,28 +1015,48 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodule su test_cmp expect output ' +test_expect_success ".gitmodules ignore=untracked doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore untracked && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_success ".git/config ignore=untracked doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore untracked && git config --add submodule.subname.path sm && git status > output && test_cmp expect output && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname ' test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" ' git status --ignore-submodules=dirty > output && test_cmp expect output ' +test_expect_success ".gitmodules ignore=dirty doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore dirty && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' test_expect_success ".git/config ignore=dirty doesn't suppress submodule summary" ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore dirty && git config --add submodule.subname.path sm && git status > output && test_cmp expect output && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname ' - cat > expect << EOF # On branch master # Changed but not updated: @@ -1019,12 +1083,23 @@ test_expect_success "--ignore-submodules=all suppresses submodule summary" ' test_cmp expect output ' +test_expect_failure '.gitmodules ignore=all suppresses submodule summary' ' + git config --add -f .gitmodules submodule.subname.ignore all && + git config --add -f .gitmodules submodule.subname.path sm && + git status > output && + test_cmp expect output && + git config -f .gitmodules --remove-section submodule.subname +' + test_expect_failure '.git/config ignore=all suppresses submodule summary' ' + git config --add -f .gitmodules submodule.subname.ignore none && + git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore all && git config --add submodule.subname.path sm && git status > output && test_cmp expect output && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config -f .gitmodules --remove-section submodule.subname ' test_done From be4f2b408e5a00d123a0ecb04b0c6c48be71dfa1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 5 Aug 2010 10:49:55 +0200 Subject: [PATCH 3/4] Add the 'diff.ignoreSubmodules' config setting When you have a lot of submodules checked out, the time penalty to check for dirty submodules can easily imply a multiplication of the total time by the factor 20. This makes the difference between almost instantaneous (< 2 seconds) and unbearably slow (> 50 seconds) here, since the disk caches are constantly overloaded. To this end, the submodule.*.ignore config option was introduced, but it is per-submodule. This commit introduces a global config setting to set a default (porcelain) value for the --ignore-submodules option, keeping the default at 'none'. It can be overridden by the submodule.*.ignore setting and by the --ignore-submodules option. Incidentally, this commit fixes an issue with the overriding logic: multiple --ignore-submodules options would not clear the previously set flags. While at it, fix a typo in the documentation for submodule.*.ignore. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/config.txt | 7 ++++++- diff.c | 6 +++++- submodule.c | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index c88a63764..cf5562192 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -826,6 +826,11 @@ diff.renames:: will enable basic rename detection. If set to "copies" or "copy", it will detect copies, as well. +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'. + diff.suppressBlankEmpty:: A boolean to inhibit the standard behavior of printing a space before each empty output line. Defaults to false. @@ -1754,7 +1759,7 @@ submodule..ignore:: submodules that have untracked files in their work tree as changed. This setting overrides any setting made in .gitmodules for this submodule, both settings can be overriden on the command line by using the - "--ignore-submodule" option. + "--ignore-submodules" option. tar.umask:: This variable can be used to restrict the permission bits of diff --git a/diff.c b/diff.c index 820604731..1ddfdfbc2 100644 --- a/diff.c +++ b/diff.c @@ -31,6 +31,7 @@ static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; static int diff_mnemonic_prefix; static int diff_no_prefix; +static struct diff_options default_diff_options; static char diff_colors[][COLOR_MAXLEN] = { GIT_COLOR_RESET, @@ -107,6 +108,9 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) if (!strcmp(var, "diff.wordregex")) return git_config_string(&diff_word_regex_cfg, var, value); + if (!strcmp(var, "diff.ignoresubmodules")) + handle_ignore_submodules_arg(&default_diff_options, value); + return git_diff_basic_config(var, value, cb); } @@ -2816,7 +2820,7 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o) void diff_setup(struct diff_options *options) { - memset(options, 0, sizeof(*options)); + memcpy(options, &default_diff_options, sizeof(*options)); memset(&diff_queued_diff, 0, sizeof(diff_queued_diff)); options->file = stdout; diff --git a/submodule.c b/submodule.c index dc0f95b73..7f0da48bc 100644 --- a/submodule.c +++ b/submodule.c @@ -123,6 +123,10 @@ int parse_submodule_config_option(const char *var, const char *value) void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *arg) { + DIFF_OPT_CLR(diffopt, IGNORE_SUBMODULES); + DIFF_OPT_CLR(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES); + DIFF_OPT_CLR(diffopt, IGNORE_DIRTY_SUBMODULES); + if (!strcmp(arg, "all")) DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES); else if (!strcmp(arg, "untracked")) From 90e14525f22c2980d4375dcb5d79e6d5da293a78 Mon Sep 17 00:00:00 2001 From: Jens Lehmann Date: Fri, 6 Aug 2010 01:27:15 +0200 Subject: [PATCH 4/4] Add tests for the diff.ignoreSubmodules config option Signed-off-by: Jens Lehmann Signed-off-by: Junio C Hamano --- t/t4027-diff-submodule.sh | 10 +++++++++- t/t7508-status.sh | 12 ++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 1bc6e77a0..d99814ac6 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -115,6 +115,9 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)' ' test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.git/config]' ' + git config diff.ignoreSubmodules all && + git diff HEAD >actual && + ! test -s actual && git config submodule.subname.ignore none && git config submodule.subname.path sub && git diff HEAD >actual && @@ -136,10 +139,14 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) sed -e "1,/^@@/d" actual >actual.body && expect_from_to >expect.body $subprev $subprev-dirty && test_cmp expect.body actual.body && - git config --remove-section submodule.subname + git config --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules ' test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.gitmodules]' ' + git config diff.ignoreSubmodules dirty && + git diff HEAD >actual && + ! test -s actual && git config --add -f .gitmodules submodule.subname.ignore none && git config --add -f .gitmodules submodule.subname.path sub && git diff HEAD >actual && @@ -166,6 +173,7 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) test_cmp expect.body actual.body && git config --remove-section submodule.subname && git config --remove-section -f .gitmodules submodule.subname && + git config --unset diff.ignoreSubmodules && rm .gitmodules ' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 1aae76261..9c14b853c 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -849,11 +849,15 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un ' test_expect_success '.gitmodules ignore=untracked suppresses submodules with untracked content' ' + git config diff.ignoreSubmodules dirty && + git status >output && + test_cmp expect output && git config --add -f .gitmodules submodule.subname.ignore untracked && git config --add -f .gitmodules submodule.subname.path sm && git status > output && test_cmp expect output && - git config -f .gitmodules --remove-section submodule.subname + git config -f .gitmodules --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules ' test_expect_success '.git/config ignore=untracked suppresses submodules with untracked content' ' @@ -873,11 +877,15 @@ test_expect_success '--ignore-submodules=dirty suppresses submodules with untrac ' test_expect_success '.gitmodules ignore=dirty suppresses submodules with untracked content' ' + git config diff.ignoreSubmodules dirty && + git status >output && + ! test -s actual && git config --add -f .gitmodules submodule.subname.ignore dirty && git config --add -f .gitmodules submodule.subname.path sm && git status > output && test_cmp expect output && - git config -f .gitmodules --remove-section submodule.subname + git config -f .gitmodules --remove-section submodule.subname && + git config --unset diff.ignoreSubmodules ' test_expect_success '.git/config ignore=dirty suppresses submodules with untracked content' '