Browse Source

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>
maint
Jens Lehmann 15 years ago committed by Junio C Hamano
parent
commit
302ad7a993
  1. 3
      Documentation/config.txt
  2. 2
      Documentation/diff-options.txt
  3. 2
      Documentation/git-status.txt
  4. 15
      Documentation/gitmodules.txt
  5. 2
      builtin/commit.c
  6. 2
      builtin/diff-files.c
  7. 2
      builtin/diff-index.c
  8. 2
      builtin/diff-tree.c
  9. 2
      builtin/diff.c
  10. 19
      submodule.c
  11. 1
      submodule.h
  12. 76
      t/t4027-diff-submodule.sh
  13. 91
      t/t7508-status.sh

3
Documentation/config.txt

@ -1752,6 +1752,9 @@ submodule.<name>.ignore::
let submodules with modified tracked files in their work tree show up. let submodules with modified tracked files in their work tree show up.
Using "none" (the default when this option is not set) also shows Using "none" (the default when this option is not set) also shows
submodules that have untracked files in their work tree as changed. 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:: tar.umask::
This variable can be used to restrict the permission bits of This variable can be used to restrict the permission bits of

2
Documentation/diff-options.txt

@ -334,7 +334,7 @@ endif::git-format-patch[]
Using "none" will consider the submodule modified when it either contains Using "none" will consider the submodule modified when it either contains
untracked or modified files or its HEAD differs from the commit recorded 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 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 "untracked" is used submodules are not considered dirty when they only
contain untracked content (but they are still scanned for modified contain untracked content (but they are still scanned for modified
content). Using "dirty" ignores all changes to the work tree of submodules, content). Using "dirty" ignores all changes to the work tree of submodules,

2
Documentation/git-status.txt

@ -59,7 +59,7 @@ specified.
Using "none" will consider the submodule modified when it either contains Using "none" will consider the submodule modified when it either contains
untracked or modified files or its HEAD differs from the commit recorded 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 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 "untracked" is used submodules are not considered dirty when they only
contain untracked content (but they are still scanned for modified contain untracked content (but they are still scanned for modified
content). Using "dirty" ignores all changes to the work tree of submodules, content). Using "dirty" ignores all changes to the work tree of submodules,

15
Documentation/gitmodules.txt

@ -44,6 +44,21 @@ submodule.<name>.update::
This config option is overridden if 'git submodule update' is given This config option is overridden if 'git submodule update' is given
the '--merge' or '--rebase' options. the '--merge' or '--rebase' options.


submodule.<name>.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 EXAMPLES
-------- --------

2
builtin/commit.c

@ -25,6 +25,7 @@
#include "rerere.h" #include "rerere.h"
#include "unpack-trees.h" #include "unpack-trees.h"
#include "quote.h" #include "quote.h"
#include "submodule.h"


static const char * const builtin_commit_usage[] = { static const char * const builtin_commit_usage[] = {
"git commit [options] [--] <filepattern>...", "git commit [options] [--] <filepattern>...",
@ -1073,6 +1074,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
status_format = STATUS_FORMAT_PORCELAIN; status_format = STATUS_FORMAT_PORCELAIN;


wt_status_prepare(&s); wt_status_prepare(&s);
gitmodules_config();
git_config(git_status_config, &s); git_config(git_status_config, &s);
in_merge = file_exists(git_path("MERGE_HEAD")); in_merge = file_exists(git_path("MERGE_HEAD"));
argc = parse_options(argc, argv, prefix, argc = parse_options(argc, argv, prefix,

2
builtin/diff-files.c

@ -8,6 +8,7 @@
#include "commit.h" #include "commit.h"
#include "revision.h" #include "revision.h"
#include "builtin.h" #include "builtin.h"
#include "submodule.h"


static const char diff_files_usage[] = static const char diff_files_usage[] =
"git diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]" "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)
unsigned options = 0; unsigned options = 0;


init_revisions(&rev, prefix); init_revisions(&rev, prefix);
gitmodules_config();
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
rev.abbrev = 0; rev.abbrev = 0;



2
builtin/diff-index.c

@ -3,6 +3,7 @@
#include "commit.h" #include "commit.h"
#include "revision.h" #include "revision.h"
#include "builtin.h" #include "builtin.h"
#include "submodule.h"


static const char diff_cache_usage[] = static const char diff_cache_usage[] =
"git diff-index [-m] [--cached] " "git diff-index [-m] [--cached] "
@ -17,6 +18,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
int result; int result;


init_revisions(&rev, prefix); init_revisions(&rev, prefix);
gitmodules_config();
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
rev.abbrev = 0; rev.abbrev = 0;



2
builtin/diff-tree.c

@ -3,6 +3,7 @@
#include "commit.h" #include "commit.h"
#include "log-tree.h" #include "log-tree.h"
#include "builtin.h" #include "builtin.h"
#include "submodule.h"


static struct rev_info log_tree_opt; 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; int read_stdin = 0;


init_revisions(opt, prefix); init_revisions(opt, prefix);
gitmodules_config();
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
opt->abbrev = 0; opt->abbrev = 0;
opt->diff = 1; opt->diff = 1;

2
builtin/diff.c

@ -13,6 +13,7 @@
#include "revision.h" #include "revision.h"
#include "log-tree.h" #include "log-tree.h"
#include "builtin.h" #include "builtin.h"
#include "submodule.h"


struct blobinfo { struct blobinfo {
unsigned char sha1[20]; 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); prefix = setup_git_directory_gently(&nongit);
gitmodules_config();
git_config(git_diff_ui_config, NULL); git_config(git_diff_ui_config, NULL);


if (diff_use_color_default == -1) if (diff_use_color_default == -1)

19
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 parse_submodule_config_option(const char *var, const char *value)
{ {
int len; int len;

1
submodule.h

@ -5,6 +5,7 @@ struct diff_options;


void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
const char *path); const char *path);
void gitmodules_config();
int parse_submodule_config_option(const char *var, const char *value); int parse_submodule_config_option(const char *var, const char *value);
void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *); void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
void show_submodule_summary(FILE *f, const char *path, void show_submodule_summary(FILE *f, const char *path,

76
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 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)' ' test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' '
( (
cd sub && cd sub &&
@ -189,6 +219,28 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)
git config --remove-section submodule.subname 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' ' test_expect_success 'git diff between submodule commits' '
git diff HEAD^..HEAD >actual && git diff HEAD^..HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body && 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 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)' ' test_expect_success 'git diff (empty submodule dir)' '
: >empty && : >empty &&
rm -rf sub/* sub/.git && rm -rf sub/* sub/.git &&

91
t/t7508-status.sh

@ -848,12 +848,23 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un
test_cmp expect output 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' ' 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.ignore untracked &&
git config --add submodule.subname.path sm && git config --add submodule.subname.path sm &&
git status > output && git status > output &&
test_cmp expect 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' ' 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_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' ' 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.ignore dirty &&
git config --add submodule.subname.path sm && git config --add submodule.subname.path sm &&
git status > output && git status > output &&
test_cmp expect 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' ' 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_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' ' 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.ignore dirty &&
git config --add submodule.subname.path sm && git config --add submodule.subname.path sm &&
git status > output && git status > output &&
test_cmp expect 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 cat > expect << EOF
@ -920,12 +953,23 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodules w
test_cmp expect output 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" ' 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.ignore untracked &&
git config --add submodule.subname.path sm && git config --add submodule.subname.path sm &&
git status > output && git status > output &&
test_cmp expect 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) 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_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" ' 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.ignore untracked &&
git config --add submodule.subname.path sm && git config --add submodule.subname.path sm &&
git status > output && git status > output &&
test_cmp expect 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" ' test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" '
git status --ignore-submodules=dirty > output && git status --ignore-submodules=dirty > output &&
test_cmp expect 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" ' 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.ignore dirty &&
git config --add submodule.subname.path sm && git config --add submodule.subname.path sm &&
git status > output && git status > output &&
test_cmp expect 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 cat > expect << EOF
# On branch master # On branch master
# Changed but not updated: # Changed but not updated:
@ -1019,12 +1083,23 @@ test_expect_success "--ignore-submodules=all suppresses submodule summary" '
test_cmp expect output 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' ' 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.ignore all &&
git config --add submodule.subname.path sm && git config --add submodule.subname.path sm &&
git status > output && git status > output &&
test_cmp expect 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 test_done

Loading…
Cancel
Save