Submodules: Add the new "ignore" config option for diff and status · wolfpython/git@aee9c7d · GitHub
Skip to content

Commit aee9c7d

Browse files
jlehmanngitster
authored andcommitted
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 <Jens.Lehmann@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 64fdc08 commit aee9c7d

11 files changed

Lines changed: 297 additions & 20 deletions

File tree

Documentation/config.txt

Lines changed: 10 additions & 0 deletions

Documentation/diff-options.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,11 @@ endif::git-format-patch[]
330330

331331
--ignore-submodules[=<when>]::
332332
Ignore changes to submodules in the diff generation. <when> can be
333-
either "untracked", "dirty" or "all", which is the default. When
333+
either "none", "untracked", "dirty" or "all", which is the default
334+
Using "none" will consider the submodule modified when it either contains
335+
untracked or modified files or its HEAD differs from the commit recorded
336+
in the superproject and can be used to override any settings of the
337+
'ignore' option in linkgit:git-config[1]. When
334338
"untracked" is used submodules are not considered dirty when they only
335339
contain untracked content (but they are still scanned for modified
336340
content). Using "dirty" ignores all changes to the work tree of submodules,

Documentation/git-status.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ specified.
5555

5656
--ignore-submodules[=<when>]::
5757
Ignore changes to submodules when looking for changes. <when> can be
58-
either "untracked", "dirty" or "all", which is the default. When
58+
either "none", "untracked", "dirty" or "all", which is the default.
59+
Using "none" will consider the submodule modified when it either contains
60+
untracked or modified files or its HEAD differs from the commit recorded
61+
in the superproject and can be used to override any settings of the
62+
'ignore' option in linkgit:git-config[1]. When
5963
"untracked" is used submodules are not considered dirty when they only
6064
contain untracked content (but they are still scanned for modified
6165
content). Using "dirty" ignores all changes to the work tree of submodules,

diff-lib.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,16 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
6868
unsigned ce_option, unsigned *dirty_submodule)
6969
{
7070
int changed = ce_match_stat(ce, st, ce_option);
71-
if (S_ISGITLINK(ce->ce_mode)
72-
&& !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES)
73-
&& !DIFF_OPT_TST(diffopt, IGNORE_DIRTY_SUBMODULES)
74-
&& (!changed || DIFF_OPT_TST(diffopt, DIRTY_SUBMODULES))) {
75-
*dirty_submodule = is_submodule_modified(ce->name, DIFF_OPT_TST(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES));
71+
if (S_ISGITLINK(ce->ce_mode)) {
72+
unsigned orig_flags = diffopt->flags;
73+
if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG))
74+
set_diffopt_flags_from_submodule_config(diffopt, ce->name);
75+
if (DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES))
76+
changed = 0;
77+
else if (!DIFF_OPT_TST(diffopt, IGNORE_DIRTY_SUBMODULES)
78+
&& (!changed || DIFF_OPT_TST(diffopt, DIRTY_SUBMODULES)))
79+
*dirty_submodule = is_submodule_modified(ce->name, DIFF_OPT_TST(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES));
80+
diffopt->flags = orig_flags;
7681
}
7782
return changed;
7883
}

diff.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
141141
return 0;
142142
}
143143

144+
if (!prefixcmp(var, "submodule."))
145+
return parse_submodule_config_option(var, value);
146+
144147
return git_color_default_config(var, value, cb);
145148
}
146149

@@ -3166,11 +3169,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
31663169
DIFF_OPT_SET(options, ALLOW_TEXTCONV);
31673170
else if (!strcmp(arg, "--no-textconv"))
31683171
DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
3169-
else if (!strcmp(arg, "--ignore-submodules"))
3172+
else if (!strcmp(arg, "--ignore-submodules")) {
3173+
DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
31703174
handle_ignore_submodules_arg(options, "all");
3171-
else if (!prefixcmp(arg, "--ignore-submodules="))
3175+
} else if (!prefixcmp(arg, "--ignore-submodules=")) {
3176+
DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
31723177
handle_ignore_submodules_arg(options, arg + 20);
3173-
else if (!strcmp(arg, "--submodule"))
3178+
} else if (!strcmp(arg, "--submodule"))
31743179
DIFF_OPT_SET(options, SUBMODULE_LOG);
31753180
else if (!prefixcmp(arg, "--submodule=")) {
31763181
if (!strcmp(arg + 12, "log"))
@@ -4103,14 +4108,32 @@ int diff_result_code(struct diff_options *opt, int status)
41034108
return result;
41044109
}
41054110

4111+
/*
4112+
* Shall changes to this submodule be ignored?
4113+
*
4114+
* Submodule changes can be configured to be ignored separately for each path,
4115+
* but that configuration can be overridden from the command line.
4116+
*/
4117+
static int is_submodule_ignored(const char *path, struct diff_options *options)
4118+
{
4119+
int ignored = 0;
4120+
unsigned orig_flags = options->flags;
4121+
if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG))
4122+
set_diffopt_flags_from_submodule_config(options, path);
4123+
if (DIFF_OPT_TST(options, IGNORE_SUBMODULES))
4124+
ignored = 1;
4125+
options->flags = orig_flags;
4126+
return ignored;
4127+
}
4128+
41064129
void diff_addremove(struct diff_options *options,
41074130
int addremove, unsigned mode,
41084131
const unsigned char *sha1,
41094132
const char *concatpath, unsigned dirty_submodule)
41104133
{
41114134
struct diff_filespec *one, *two;
41124135

4113-
if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
4136+
if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options))
41144137
return;
41154138

41164139
/* This may look odd, but it is a preparation for
@@ -4157,8 +4180,8 @@ void diff_change(struct diff_options *options,
41574180
{
41584181
struct diff_filespec *one, *two;
41594182

4160-
if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
4161-
&& S_ISGITLINK(new_mode))
4183+
if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) &&
4184+
is_submodule_ignored(concatpath, options))
41624185
return;
41634186

41644187
if (DIFF_OPT_TST(options, REVERSE_DIFF)) {

diff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
7777
#define DIFF_OPT_DIRTY_SUBMODULES (1 << 24)
7878
#define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25)
7979
#define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26)
80+
#define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
8081

8182
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
8283
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)

submodule.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
#include "revision.h"
77
#include "run-command.h"
88
#include "diffcore.h"
9+
#include "string-list.h"
10+
11+
struct string_list config_name_for_path;
12+
struct string_list config_ignore_for_name;
913

1014
static int add_submodule_odb(const char *path)
1115
{
@@ -46,6 +50,57 @@ static int add_submodule_odb(const char *path)
4650
return ret;
4751
}
4852

53+
void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
54+
const char *path)
55+
{
56+
struct string_list_item *path_option, *ignore_option;
57+
path_option = unsorted_string_list_lookup(&config_name_for_path, path);
58+
if (path_option) {
59+
ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, path_option->util);
60+
if (ignore_option)
61+
handle_ignore_submodules_arg(diffopt, ignore_option->util);
62+
}
63+
}
64+
65+
int parse_submodule_config_option(const char *var, const char *value)
66+
{
67+
int len;
68+
struct string_list_item *config;
69+
struct strbuf submodname = STRBUF_INIT;
70+
71+
var += 10; /* Skip "submodule." */
72+
73+
len = strlen(var);
74+
if ((len > 5) && !strcmp(var + len - 5, ".path")) {
75+
strbuf_add(&submodname, var, len - 5);
76+
config = unsorted_string_list_lookup(&config_name_for_path, value);
77+
if (config)
78+
free(config->util);
79+
else
80+
config = string_list_append(&config_name_for_path, xstrdup(value));
81+
config->util = strbuf_detach(&submodname, NULL);
82+
strbuf_release(&submodname);
83+
} else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) {
84+
if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
85+
strcmp(value, "all") && strcmp(value, "none")) {
86+
warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var);
87+
return 0;
88+
}
89+
90+
strbuf_add(&submodname, var, len - 7);
91+
config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf);
92+
if (config)
93+
free(config->util);
94+
else
95+
config = string_list_append(&config_ignore_for_name,
96+
strbuf_detach(&submodname, NULL));
97+
strbuf_release(&submodname);
98+
config->util = xstrdup(value);
99+
return 0;
100+
}
101+
return 0;
102+
}
103+
49104
void handle_ignore_submodules_arg(struct diff_options *diffopt,
50105
const char *arg)
51106
{
@@ -55,7 +110,7 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt,
55110
DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
56111
else if (!strcmp(arg, "dirty"))
57112
DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES);
58-
else
113+
else if (strcmp(arg, "none"))
59114
die("bad --ignore-submodules argument: %s", arg);
60115
}
61116

submodule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
struct diff_options;
55

6+
void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
7+
const char *path);
8+
int parse_submodule_config_option(const char *var, const char *value);
69
void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
710
void show_submodule_summary(FILE *f, const char *path,
811
unsigned char one[20], unsigned char two[20],

t/t4027-diff-submodule.sh

Lines changed: 76 additions & 0 deletions

0 commit comments

Comments
 (0)