Submodules: Use "ignore" settings from .gitmodules too for diff and status
The .gitmodules file is parsed for "submodule.<name>.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 <Jens.Lehmann@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jens Lehmann committed
Aug 6, 2010 at 00:40 UTC
302ad7a9930a34413418b6436f96826070367647
13 files changed
+209
-10
Documentation/config.txt
+3
@@ -1752,6 +1752,9 @@ submodule.<name>.ignore::
1752
let submodules with modified tracked files in their work tree show up.
1753
Using "none" (the default when this option is not set) also shows
1754
submodules that have untracked files in their work tree as changed.
1755
+ This setting overrides any setting made in .gitmodules for this submodule,
1756
+ both settings can be overriden on the command line by using the
1757
+ "--ignore-submodule" option.
1758
1759
tar.umask::
1760
This variable can be used to restrict the permission bits of
Documentation/diff-options.txt
+1
-1
@@ -334,7 +334,7 @@ endif::git-format-patch[]
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
337
+ 'ignore' option in linkgit:git-config[1] or linkgit:gitmodules[5]. When
338
"untracked" is used submodules are not considered dirty when they only
339
contain untracked content (but they are still scanned for modified
340
content). Using "dirty" ignores all changes to the work tree of submodules,
Documentation/git-status.txt
+1
-1
@@ -59,7 +59,7 @@ specified.
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
62
+ 'ignore' option in linkgit:git-config[1] or linkgit:gitmodules[5]. When
63
"untracked" is used submodules are not considered dirty when they only
64
contain untracked content (but they are still scanned for modified
65
content). Using "dirty" ignores all changes to the work tree of submodules,
Documentation/gitmodules.txt
+15
@@ -44,6 +44,21 @@ submodule.<name>.update::
44
This config option is overridden if 'git submodule update' is given
45
the '--merge' or '--rebase' options.
46
47
+submodule.<name>.ignore::
48
+ Defines under what circumstances "git status" and the diff family show
49
+ a submodule as modified. When set to "all", it will never be considered
50
+ modified, "dirty" will ignore all changes to the submodules work tree and
51
+ takes only differences between the HEAD of the submodule and the commit
52
+ recorded in the superproject into account. "untracked" will additionally
53
+ let submodules with modified tracked files in their work tree show up.
54
+ Using "none" (the default when this option is not set) also shows
55
+ submodules that have untracked files in their work tree as changed.
56
+ If this option is also present in the submodules entry in .git/config of
57
+ the superproject, the setting there will override the one found in
58
+ .gitmodules.
59
+ Both settings can be overriden on the command line by using the
60
+ "--ignore-submodule" option.
61
+
62
63
EXAMPLES
64
--------
builtin/commit.c
+2
@@ -25,6 +25,7 @@
25
#include "rerere.h"
26
#include "unpack-trees.h"
27
#include "quote.h"
28
+#include "submodule.h"
29
30
static const char * const builtin_commit_usage[] = {
31
"git commit [options] [--] <filepattern>...",
@@ -1073,6 +1074,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
1074
status_format = STATUS_FORMAT_PORCELAIN;
1075
1076
wt_status_prepare(&s);
1077
+ gitmodules_config();
1078
git_config(git_status_config, &s);
1079
in_merge = file_exists(git_path("MERGE_HEAD"));
1080
argc = parse_options(argc, argv, prefix,
builtin/diff-files.c
+2
@@ -8,6 +8,7 @@
8
#include "commit.h"
9
#include "revision.h"
10
#include "builtin.h"
11
+#include "submodule.h"
12
13
static const char diff_files_usage[] =
14
"git diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
@@ -20,6 +21,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
21
unsigned options = 0;
22
23
init_revisions(&rev, prefix);
24
+ gitmodules_config();
25
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
26
rev.abbrev = 0;
27
builtin/diff-index.c
+2
@@ -3,6 +3,7 @@
3
#include "commit.h"
4
#include "revision.h"
5
#include "builtin.h"
6
+#include "submodule.h"
7
8
static const char diff_cache_usage[] =
9
"git diff-index [-m] [--cached] "
@@ -17,6 +18,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
18
int result;
19
20
init_revisions(&rev, prefix);
21
+ gitmodules_config();
22
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
23
rev.abbrev = 0;
24
builtin/diff-tree.c
+2
@@ -3,6 +3,7 @@
3
#include "commit.h"
4
#include "log-tree.h"
5
#include "builtin.h"
6
+#include "submodule.h"
7
8
static struct rev_info log_tree_opt;
9
@@ -112,6 +113,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
113
int read_stdin = 0;
114
115
init_revisions(opt, prefix);
116
+ gitmodules_config();
117
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
118
opt->abbrev = 0;
119
opt->diff = 1;
builtin/diff.c
+2
@@ -13,6 +13,7 @@
13
#include "revision.h"
14
#include "log-tree.h"
15
#include "builtin.h"
16
+#include "submodule.h"
17
18
struct blobinfo {
19
unsigned char sha1[20];
@@ -279,6 +280,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
280
*/
281
282
prefix = setup_git_directory_gently(&nongit);
283
+ gitmodules_config();
284
git_config(git_diff_ui_config, NULL);
285
286
if (diff_use_color_default == -1)
submodule.c
+19
@@ -62,6 +62,25 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
62
}
63
}
64
65
+static int submodule_config(const char *var, const char *value, void *cb)
66
+{
67
+ if (!prefixcmp(var, "submodule."))
68
+ return parse_submodule_config_option(var, value);
69
+ return 0;
70
+}
71
+
72
+void gitmodules_config(void)
73
+{
74
+ const char *work_tree = get_git_work_tree();
75
+ if (work_tree) {
76
+ struct strbuf gitmodules_path = STRBUF_INIT;
77
+ strbuf_addstr(&gitmodules_path, work_tree);
78
+ strbuf_addstr(&gitmodules_path, "/.gitmodules");
79
+ git_config_from_file(submodule_config, gitmodules_path.buf, NULL);
80
+ strbuf_release(&gitmodules_path);
81
+ }
82
+}
83
+
84
int parse_submodule_config_option(const char *var, const char *value)
85
{
86
int len;
submodule.h
+1
@@ -5,6 +5,7 @@ struct diff_options;
5
6
void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
7
const char *path);
8
+void gitmodules_config();
9
int parse_submodule_config_option(const char *var, const char *value);
10
void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
11
void show_submodule_summary(FILE *f, const char *path,
t/t4027-diff-submodule.sh
+76
@@ -139,6 +139,36 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)
139
git config --remove-section submodule.subname
140
'
141
142
+test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.gitmodules]' '
143
+ git config --add -f .gitmodules submodule.subname.ignore none &&
144
+ git config --add -f .gitmodules submodule.subname.path sub &&
145
+ git diff HEAD >actual &&
146
+ sed -e "1,/^@@/d" actual >actual.body &&
147
+ expect_from_to >expect.body $subprev $subprev-dirty &&
148
+ test_cmp expect.body actual.body &&
149
+ git config -f .gitmodules submodule.subname.ignore all &&
150
+ git config -f .gitmodules submodule.subname.path sub &&
151
+ git diff HEAD >actual2 &&
152
+ ! test -s actual2 &&
153
+ git config -f .gitmodules submodule.subname.ignore untracked &&
154
+ git diff HEAD >actual3 &&
155
+ sed -e "1,/^@@/d" actual3 >actual3.body &&
156
+ expect_from_to >expect.body $subprev $subprev-dirty &&
157
+ test_cmp expect.body actual3.body &&
158
+ git config -f .gitmodules submodule.subname.ignore dirty &&
159
+ git diff HEAD >actual4 &&
160
+ ! test -s actual4 &&
161
+ git config submodule.subname.ignore none &&
162
+ git config submodule.subname.path sub &&
163
+ git diff HEAD >actual &&
164
+ sed -e "1,/^@@/d" actual >actual.body &&
165
+ expect_from_to >expect.body $subprev $subprev-dirty &&
166
+ test_cmp expect.body actual.body &&
167
+ git config --remove-section submodule.subname &&
168
+ git config --remove-section -f .gitmodules submodule.subname &&
169
+ rm .gitmodules
170
+'
171
+
172
test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' '
173
(
174
cd sub &&
@@ -189,6 +219,28 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)
219
git config --remove-section submodule.subname
220
'
221
222
+test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.gitmodules]' '
223
+ git config --add -f .gitmodules submodule.subname.ignore all &&
224
+ git config --add -f .gitmodules submodule.subname.path sub &&
225
+ git diff HEAD >actual2 &&
226
+ ! test -s actual2 &&
227
+ git config -f .gitmodules submodule.subname.ignore untracked &&
228
+ git diff HEAD >actual3 &&
229
+ ! test -s actual3 &&
230
+ git config -f .gitmodules submodule.subname.ignore dirty &&
231
+ git diff HEAD >actual4 &&
232
+ ! test -s actual4 &&
233
+ git config submodule.subname.ignore none &&
234
+ git config submodule.subname.path sub &&
235
+ git diff HEAD >actual &&
236
+ sed -e "1,/^@@/d" actual >actual.body &&
237
+ expect_from_to >expect.body $subprev $subprev-dirty &&
238
+ test_cmp expect.body actual.body &&
239
+ git config --remove-section submodule.subname &&
240
+ git config --remove-section -f .gitmodules submodule.subname &&
241
+ rm .gitmodules
242
+'
243
+
244
test_expect_success 'git diff between submodule commits' '
245
git diff HEAD^..HEAD >actual &&
246
sed -e "1,/^@@/d" actual >actual.body &&
@@ -222,6 +274,30 @@ test_expect_success 'git diff between submodule commits [.git/config]' '
274
git config --remove-section submodule.subname
275
'
276
277
+test_expect_success 'git diff between submodule commits [.gitmodules]' '
278
+ git diff HEAD^..HEAD >actual &&
279
+ sed -e "1,/^@@/d" actual >actual.body &&
280
+ expect_from_to >expect.body $subtip $subprev &&
281
+ test_cmp expect.body actual.body &&
282
+ git config --add -f .gitmodules submodule.subname.ignore dirty &&
283
+ git config --add -f .gitmodules submodule.subname.path sub &&
284
+ git diff HEAD^..HEAD >actual &&
285
+ sed -e "1,/^@@/d" actual >actual.body &&
286
+ expect_from_to >expect.body $subtip $subprev &&
287
+ test_cmp expect.body actual.body &&
288
+ git config -f .gitmodules submodule.subname.ignore all &&
289
+ git diff HEAD^..HEAD >actual &&
290
+ ! test -s actual &&
291
+ git config submodule.subname.ignore dirty &&
292
+ git config submodule.subname.path sub &&
293
+ git diff HEAD^..HEAD >actual &&
294
+ sed -e "1,/^@@/d" actual >actual.body &&
295
+ expect_from_to >expect.body $subtip $subprev &&
296
+ git config --remove-section submodule.subname &&
297
+ git config --remove-section -f .gitmodules submodule.subname &&
298
+ rm .gitmodules
299
+'
300
+
301
test_expect_success 'git diff (empty submodule dir)' '
302
: >empty &&
303
rm -rf sub/* sub/.git &&
t/t7508-status.sh
+83
-8
@@ -848,12 +848,23 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un
848
test_cmp expect output
849
'
850
851
+test_expect_success '.gitmodules ignore=untracked suppresses submodules with untracked content' '
852
+ git config --add -f .gitmodules submodule.subname.ignore untracked &&
853
+ git config --add -f .gitmodules submodule.subname.path sm &&
854
+ git status > output &&
855
+ test_cmp expect output &&
856
+ git config -f .gitmodules --remove-section submodule.subname
857
+'
858
+
859
test_expect_success '.git/config ignore=untracked suppresses submodules with untracked content' '
860
+ git config --add -f .gitmodules submodule.subname.ignore none &&
861
+ git config --add -f .gitmodules submodule.subname.path sm &&
862
git config --add submodule.subname.ignore untracked &&
863
git config --add submodule.subname.path sm &&
864
git status > output &&
865
test_cmp expect output &&
856
- git config --remove-section submodule.subname
866
+ git config --remove-section submodule.subname &&
867
+ git config --remove-section -f .gitmodules submodule.subname
868
'
869
870
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
872
test_cmp expect output
873
'
874
875
+test_expect_success '.gitmodules ignore=dirty suppresses submodules with untracked content' '
876
+ git config --add -f .gitmodules submodule.subname.ignore dirty &&
877
+ git config --add -f .gitmodules submodule.subname.path sm &&
878
+ git status > output &&
879
+ test_cmp expect output &&
880
+ git config -f .gitmodules --remove-section submodule.subname
881
+'
882
+
883
test_expect_success '.git/config ignore=dirty suppresses submodules with untracked content' '
884
+ git config --add -f .gitmodules submodule.subname.ignore none &&
885
+ git config --add -f .gitmodules submodule.subname.path sm &&
886
git config --add submodule.subname.ignore dirty &&
887
git config --add submodule.subname.path sm &&
888
git status > output &&
889
test_cmp expect output &&
869
- git config --remove-section submodule.subname
890
+ git config --remove-section submodule.subname &&
891
+ git config -f .gitmodules --remove-section submodule.subname
892
'
893
894
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
897
test_cmp expect output
898
'
899
900
+test_expect_success '.gitmodules ignore=dirty suppresses submodules with modified content' '
901
+ git config --add -f .gitmodules submodule.subname.ignore dirty &&
902
+ git config --add -f .gitmodules submodule.subname.path sm &&
903
+ git status > output &&
904
+ test_cmp expect output &&
905
+ git config -f .gitmodules --remove-section submodule.subname
906
+'
907
+
908
test_expect_success '.git/config ignore=dirty suppresses submodules with modified content' '
909
+ git config --add -f .gitmodules submodule.subname.ignore none &&
910
+ git config --add -f .gitmodules submodule.subname.path sm &&
911
git config --add submodule.subname.ignore dirty &&
912
git config --add submodule.subname.path sm &&
913
git status > output &&
914
test_cmp expect output &&
883
- git config --remove-section submodule.subname
915
+ git config --remove-section submodule.subname &&
916
+ git config -f .gitmodules --remove-section submodule.subname
917
'
918
919
cat > expect << EOF
@@ -920,12 +953,23 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodules w
953
test_cmp expect output
954
'
955
956
+test_expect_success ".gitmodules ignore=untracked doesn't suppress submodules with modified content" '
957
+ git config --add -f .gitmodules submodule.subname.ignore untracked &&
958
+ git config --add -f .gitmodules submodule.subname.path sm &&
959
+ git status > output &&
960
+ test_cmp expect output &&
961
+ git config -f .gitmodules --remove-section submodule.subname
962
+'
963
+
964
test_expect_success ".git/config ignore=untracked doesn't suppress submodules with modified content" '
965
+ git config --add -f .gitmodules submodule.subname.ignore none &&
966
+ git config --add -f .gitmodules submodule.subname.path sm &&
967
git config --add submodule.subname.ignore untracked &&
968
git config --add submodule.subname.path sm &&
969
git status > output &&
970
test_cmp expect output &&
928
- git config --remove-section submodule.subname
971
+ git config --remove-section submodule.subname &&
972
+ git config -f .gitmodules --remove-section submodule.subname
973
'
974
975
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
1015
test_cmp expect output
1016
'
1017
1018
+test_expect_success ".gitmodules ignore=untracked doesn't suppress submodule summary" '
1019
+ git config --add -f .gitmodules submodule.subname.ignore untracked &&
1020
+ git config --add -f .gitmodules submodule.subname.path sm &&
1021
+ git status > output &&
1022
+ test_cmp expect output &&
1023
+ git config -f .gitmodules --remove-section submodule.subname
1024
+'
1025
+
1026
test_expect_success ".git/config ignore=untracked doesn't suppress submodule summary" '
1027
+ git config --add -f .gitmodules submodule.subname.ignore none &&
1028
+ git config --add -f .gitmodules submodule.subname.path sm &&
1029
git config --add submodule.subname.ignore untracked &&
1030
git config --add submodule.subname.path sm &&
1031
git status > output &&
1032
test_cmp expect output &&
979
- git config --remove-section submodule.subname
1033
+ git config --remove-section submodule.subname &&
1034
+ git config -f .gitmodules --remove-section submodule.subname
1035
'
1036
1037
test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" '
1038
git status --ignore-submodules=dirty > output &&
1039
test_cmp expect output
1040
'
1041
+test_expect_success ".gitmodules ignore=dirty doesn't suppress submodule summary" '
1042
+ git config --add -f .gitmodules submodule.subname.ignore dirty &&
1043
+ git config --add -f .gitmodules submodule.subname.path sm &&
1044
+ git status > output &&
1045
+ test_cmp expect output &&
1046
+ git config -f .gitmodules --remove-section submodule.subname
1047
+'
1048
1049
test_expect_success ".git/config ignore=dirty doesn't suppress submodule summary" '
1050
+ git config --add -f .gitmodules submodule.subname.ignore none &&
1051
+ git config --add -f .gitmodules submodule.subname.path sm &&
1052
git config --add submodule.subname.ignore dirty &&
1053
git config --add submodule.subname.path sm &&
1054
git status > output &&
1055
test_cmp expect output &&
992
- git config --remove-section submodule.subname
1056
+ git config --remove-section submodule.subname &&
1057
+ git config -f .gitmodules --remove-section submodule.subname
1058
'
1059
995
-
1060
cat > expect << EOF
1061
# On branch master
1062
# Changed but not updated:
@@ -1019,12 +1083,23 @@ test_expect_success "--ignore-submodules=all suppresses submodule summary" '
1083
test_cmp expect output
1084
'
1085
1086
+test_expect_failure '.gitmodules ignore=all suppresses submodule summary' '
1087
+ git config --add -f .gitmodules submodule.subname.ignore all &&
1088
+ git config --add -f .gitmodules submodule.subname.path sm &&
1089
+ git status > output &&
1090
+ test_cmp expect output &&
1091
+ git config -f .gitmodules --remove-section submodule.subname
1092
+'
1093
+
1094
test_expect_failure '.git/config ignore=all suppresses submodule summary' '
1095
+ git config --add -f .gitmodules submodule.subname.ignore none &&
1096
+ git config --add -f .gitmodules submodule.subname.path sm &&
1097
git config --add submodule.subname.ignore all &&
1098
git config --add submodule.subname.path sm &&
1099
git status > output &&
1100
test_cmp expect output &&
1027
- git config --remove-section submodule.subname
1101
+ git config --remove-section submodule.subname &&
1102
+ git config -f .gitmodules --remove-section submodule.subname
1103
'
1104
1105
test_done