Merge branch 'jl/submodule-ignore-diff'

* jl/submodule-ignore-diff:
  Add tests for the diff.ignoreSubmodules config option
  Add the 'diff.ignoreSubmodules' config setting
  Submodules: Use "ignore" settings from .gitmodules too for diff and status
  Submodules: Add the new "ignore" config option for diff and status

Conflicts:
	diff.c
This commit is contained in:
Junio C Hamano 2010-08-18 12:36:25 -07:00
Родитель 06d11b2e8d 90e14525f2
Коммит cc34bb0b02
17 изменённых файлов: 526 добавлений и 21 удалений

Просмотреть файл

@ -826,6 +826,11 @@ diff.renames::
will enable basic rename detection. If set to "copies" or will enable basic rename detection. If set to "copies" or
"copy", it will detect copies, as well. "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:: diff.suppressBlankEmpty::
A boolean to inhibit the standard behavior of printing a space A boolean to inhibit the standard behavior of printing a space
before each empty output line. Defaults to false. before each empty output line. Defaults to false.
@ -1749,6 +1754,19 @@ submodule.<name>.update::
URL and other values found in the `.gitmodules` file. See URL and other values found in the `.gitmodules` file. See
linkgit:git-submodule[1] and linkgit:gitmodules[5] for details. linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
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.
This setting overrides any setting made in .gitmodules for this submodule,
both settings can be overriden on the command line by using the
"--ignore-submodules" 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
tar archive entries. The default is 0002, which turns off the tar archive entries. The default is 0002, which turns off the

Просмотреть файл

@ -355,7 +355,11 @@ endif::git-format-patch[]
--ignore-submodules[=<when>]:: --ignore-submodules[=<when>]::
Ignore changes to submodules in the diff generation. <when> can be Ignore changes to submodules in the diff generation. <when> 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] 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,

Просмотреть файл

@ -55,7 +55,11 @@ specified.
--ignore-submodules[=<when>]:: --ignore-submodules[=<when>]::
Ignore changes to submodules when looking for changes. <when> can be Ignore changes to submodules when looking for changes. <when> 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] 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,

Просмотреть файл

@ -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
-------- --------

Просмотреть файл

@ -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,

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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)

Просмотреть файл

@ -68,11 +68,16 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
unsigned ce_option, unsigned *dirty_submodule) unsigned ce_option, unsigned *dirty_submodule)
{ {
int changed = ce_match_stat(ce, st, ce_option); int changed = ce_match_stat(ce, st, ce_option);
if (S_ISGITLINK(ce->ce_mode) if (S_ISGITLINK(ce->ce_mode)) {
&& !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES) unsigned orig_flags = diffopt->flags;
&& !DIFF_OPT_TST(diffopt, IGNORE_DIRTY_SUBMODULES) if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG))
&& (!changed || DIFF_OPT_TST(diffopt, DIRTY_SUBMODULES))) { 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)); *dirty_submodule = is_submodule_modified(ce->name, DIFF_OPT_TST(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES));
diffopt->flags = orig_flags;
} }
return changed; return changed;
} }

41
diff.c
Просмотреть файл

@ -31,6 +31,7 @@ static const char *external_diff_cmd_cfg;
int diff_auto_refresh_index = 1; int diff_auto_refresh_index = 1;
static int diff_mnemonic_prefix; static int diff_mnemonic_prefix;
static int diff_no_prefix; static int diff_no_prefix;
static struct diff_options default_diff_options;
static char diff_colors[][COLOR_MAXLEN] = { static char diff_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET, 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")) if (!strcmp(var, "diff.wordregex"))
return git_config_string(&diff_word_regex_cfg, var, value); 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); return git_diff_basic_config(var, value, cb);
} }
@ -141,6 +145,9 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
return 0; return 0;
} }
if (!prefixcmp(var, "submodule."))
return parse_submodule_config_option(var, value);
return git_color_default_config(var, value, cb); return git_color_default_config(var, value, cb);
} }
@ -2819,7 +2826,7 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
void diff_setup(struct diff_options *options) void diff_setup(struct diff_options *options)
{ {
memset(options, 0, sizeof(*options)); memcpy(options, &default_diff_options, sizeof(*options));
options->file = stdout; options->file = stdout;
@ -3171,11 +3178,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
DIFF_OPT_SET(options, ALLOW_TEXTCONV); DIFF_OPT_SET(options, ALLOW_TEXTCONV);
else if (!strcmp(arg, "--no-textconv")) else if (!strcmp(arg, "--no-textconv"))
DIFF_OPT_CLR(options, ALLOW_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"); 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); handle_ignore_submodules_arg(options, arg + 20);
else if (!strcmp(arg, "--submodule")) } else if (!strcmp(arg, "--submodule"))
DIFF_OPT_SET(options, SUBMODULE_LOG); DIFF_OPT_SET(options, SUBMODULE_LOG);
else if (!prefixcmp(arg, "--submodule=")) { else if (!prefixcmp(arg, "--submodule=")) {
if (!strcmp(arg + 12, "log")) if (!strcmp(arg + 12, "log"))
@ -4108,6 +4117,24 @@ int diff_result_code(struct diff_options *opt, int status)
return result; 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, void diff_addremove(struct diff_options *options,
int addremove, unsigned mode, int addremove, unsigned mode,
const unsigned char *sha1, const unsigned char *sha1,
@ -4115,7 +4142,7 @@ void diff_addremove(struct diff_options *options,
{ {
struct diff_filespec *one, *two; 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; return;
/* This may look odd, but it is a preparation for /* This may look odd, but it is a preparation for
@ -4162,8 +4189,8 @@ void diff_change(struct diff_options *options,
{ {
struct diff_filespec *one, *two; struct diff_filespec *one, *two;
if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode) if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) &&
&& S_ISGITLINK(new_mode)) is_submodule_ignored(concatpath, options))
return; return;
if (DIFF_OPT_TST(options, REVERSE_DIFF)) { if (DIFF_OPT_TST(options, REVERSE_DIFF)) {

1
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_DIRTY_SUBMODULES (1 << 24)
#define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25) #define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25)
#define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26) #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_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)

Просмотреть файл

@ -6,6 +6,10 @@
#include "revision.h" #include "revision.h"
#include "run-command.h" #include "run-command.h"
#include "diffcore.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) static int add_submodule_odb(const char *path)
{ {
@ -46,16 +50,90 @@ done:
return ret; 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);
}
}
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;
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, void handle_ignore_submodules_arg(struct diff_options *diffopt,
const char *arg) 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")) if (!strcmp(arg, "all"))
DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES); DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
else if (!strcmp(arg, "untracked")) else if (!strcmp(arg, "untracked"))
DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES); DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
else if (!strcmp(arg, "dirty")) else if (!strcmp(arg, "dirty"))
DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES); DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES);
else else if (strcmp(arg, "none"))
die("bad --ignore-submodules argument: %s", arg); die("bad --ignore-submodules argument: %s", arg);
} }

Просмотреть файл

@ -3,6 +3,10 @@
struct diff_options; 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 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,
unsigned char one[20], unsigned char two[20], unsigned char one[20], unsigned char two[20],

Просмотреть файл

@ -114,6 +114,69 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)'
! test -s actual4 ! test -s actual4
' '
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 &&
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 &&
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 &&
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 &&
git config --unset diff.ignoreSubmodules &&
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 &&
@ -146,6 +209,103 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)'
! test -s actual4 ! 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 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 &&
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 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 &&

Просмотреть файл

@ -808,24 +808,38 @@ test_expect_success POSIXPERM 'status succeeds in a read-only repository' '
(exit $status) (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 cat > expect << EOF
# On branch master # On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: sm
#
# Changed but not updated: # Changed but not updated:
# (use "git add <file>..." to update what will be committed) # (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory) # (use "git checkout -- <file>..." to discard changes in working directory)
# #
# modified: dir1/modified # modified: dir1/modified
# #
# Submodule changes to be committed:
#
# * sm $head...$new_head (1):
# > Add bar
#
# Untracked files: # Untracked files:
# (use "git add <file>..." to include in what will be committed) # (use "git add <file>..." to include in what will be committed)
# #
# .gitmodules
# dir1/untracked # dir1/untracked
# dir2/modified # dir2/modified
# dir2/untracked # dir2/untracked
# expect # expect
# output # output
# untracked # untracked
no changes added to commit (use "git add" and/or "git commit -a")
EOF EOF
test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' ' test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' '
@ -834,19 +848,89 @@ 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 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 --unset diff.ignoreSubmodules
'
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 -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' '
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 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 --unset diff.ignoreSubmodules
'
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 -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' '
echo modified > sm/foo && echo modified > sm/foo &&
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 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 -f .gitmodules --remove-section submodule.subname
'
cat > expect << EOF cat > expect << EOF
# On branch master # On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: sm
#
# Changed but not updated: # Changed but not updated:
# (use "git add <file>..." to update what will be committed) # (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory) # (use "git checkout -- <file>..." to discard changes in working directory)
@ -855,16 +939,21 @@ cat > expect << EOF
# modified: dir1/modified # modified: dir1/modified
# modified: sm (modified content) # modified: sm (modified content)
# #
# Submodule changes to be committed:
#
# * sm $head...$new_head (1):
# > Add bar
#
# Untracked files: # Untracked files:
# (use "git add <file>..." to include in what will be committed) # (use "git add <file>..." to include in what will be committed)
# #
# .gitmodules
# dir1/untracked # dir1/untracked
# dir2/modified # dir2/modified
# dir2/untracked # dir2/untracked
# expect # expect
# output # output
# untracked # untracked
no changes added to commit (use "git add" and/or "git commit -a")
EOF EOF
test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" ' test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" '
@ -872,10 +961,34 @@ 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" '
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 -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)
cat > expect << EOF cat > expect << EOF
# On branch master # On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: sm
#
# Changed but not updated: # Changed but not updated:
# (use "git add <file>..." to update what will be committed) # (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory) # (use "git checkout -- <file>..." to discard changes in working directory)
@ -883,21 +996,26 @@ cat > expect << EOF
# modified: dir1/modified # modified: dir1/modified
# modified: sm (new commits) # modified: sm (new commits)
# #
# Submodule changes to be committed:
#
# * sm $head...$new_head (1):
# > Add bar
#
# Submodules changed but not updated: # Submodules changed but not updated:
# #
# * sm $head...$head2 (1): # * sm $new_head...$head2 (1):
# > 2nd commit # > 2nd commit
# #
# Untracked files: # Untracked files:
# (use "git add <file>..." to include in what will be committed) # (use "git add <file>..." to include in what will be committed)
# #
# .gitmodules
# dir1/untracked # dir1/untracked
# dir2/modified # dir2/modified
# dir2/untracked # dir2/untracked
# expect # expect
# output # output
# untracked # untracked
no changes added to commit (use "git add" and/or "git commit -a")
EOF EOF
test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" ' test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" '
@ -905,10 +1023,47 @@ 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" '
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 -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" '
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 -f .gitmodules --remove-section submodule.subname
'
cat > expect << EOF cat > expect << EOF
# On branch master # On branch master
@ -921,6 +1076,7 @@ cat > expect << EOF
# Untracked files: # Untracked files:
# (use "git add <file>..." to include in what will be committed) # (use "git add <file>..." to include in what will be committed)
# #
# .gitmodules
# dir1/untracked # dir1/untracked
# dir2/modified # dir2/modified
# dir2/untracked # dir2/untracked
@ -935,4 +1091,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' '
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 -f .gitmodules --remove-section submodule.subname
'
test_done test_done

Просмотреть файл

@ -313,8 +313,10 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
DIFF_OPT_SET(&rev.diffopt, DIRTY_SUBMODULES); DIFF_OPT_SET(&rev.diffopt, DIRTY_SUBMODULES);
if (!s->show_untracked_files) if (!s->show_untracked_files)
DIFF_OPT_SET(&rev.diffopt, IGNORE_UNTRACKED_IN_SUBMODULES); 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); handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
}
rev.diffopt.format_callback = wt_status_collect_changed_cb; rev.diffopt.format_callback = wt_status_collect_changed_cb;
rev.diffopt.format_callback_data = s; rev.diffopt.format_callback_data = s;
rev.prune_data = s->pathspec; 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; opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;
setup_revisions(0, NULL, &rev, &opt); 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); handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
}
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK; rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = wt_status_collect_updated_cb; rev.diffopt.format_callback = wt_status_collect_updated_cb;