Skip to content

Commit 1b8d93b

Browse files
committed
Add required explicit pathspec in order to add
1 parent 79598c6 commit 1b8d93b

File tree

3 files changed

+79
-22
lines changed

3 files changed

+79
-22
lines changed

Documentation/git-add.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ in linkgit:gitglossary[7].
7878
`-f`::
7979
`--force`::
8080
Allow adding otherwise ignored files. The option is also used
81-
when you update to submodules and `submodule.<name>.ignore=all`
82-
is set.
81+
when updating submodules and `submodule.<name>.ignore=all`
82+
is set. The `path` to the submodule must be explicitly specified.
8383

8484
`--sparse`::
8585
Allow updating index entries outside of the sparse-checkout cone.

read-cache.c

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,6 +3887,7 @@ struct update_callback_data {
38873887
int flags;
38883888
int ignored_too;
38893889
int add_errors;
3890+
struct pathspec *pathspec;
38903891
};
38913892

38923893
static int fix_unmerged_status(struct diff_filepair *p,
@@ -3920,26 +3921,51 @@ static void update_callback(struct diff_queue_struct *q,
39203921
struct diff_filepair *p = q->queue[i];
39213922
const char *path = p->one->path;
39223923

3923-
trace_printf("File '%s'\n", path);
3924-
39253924
if (!data->include_sparse &&
39263925
!path_in_sparse_checkout(path, data->index))
39273926
continue;
39283927

39293928
switch (fix_unmerged_status(p, data)) {
39303929
default:
39313930
die(_("unexpected diff status %c"), p->status);
3932-
case DIFF_STATUS_MODIFIED:
3933-
trace_printf("diff modified '%s'\n", path);
3931+
case DIFF_STATUS_MODIFIED: {
39343932
const struct submodule *sub = submodule_from_path(data->repo, null_oid(the_hash_algo), path);
3935-
if ( sub && sub->name && sub->ignore && strcmp(sub->ignore, "all") == 0 ) {
3936-
trace_printf("ignore=all %s\n" , path );
3937-
if ( data->ignored_too && data->ignored_too > 0 ) {
3938-
trace_printf("Adding submodule even ignore=all is due to --force|-f: %s\n", path);
3933+
if (sub && sub->name && sub->ignore && !strcmp(sub->ignore, "all")) {
3934+
int pathspec_matches = 0;
3935+
char *norm_pathspec = NULL;
3936+
int ps_i;
3937+
trace_printf("ignore=all %s\n", path);
3938+
trace_printf("pathspec %s\n",
3939+
(data->pathspec && data->pathspec->nr) ? "has pathspec" : "no pathspec");
3940+
/* Safely scan all pathspec items (q->nr may exceed pathspec->nr). */
3941+
if (data->pathspec) {
3942+
for (ps_i = 0; ps_i < data->pathspec->nr; ps_i++) {
3943+
const char *m = data->pathspec->items[ps_i].match;
3944+
if (!m)
3945+
continue;
3946+
norm_pathspec = xstrdup(m);
3947+
strip_dir_trailing_slashes(norm_pathspec);
3948+
if (!strcmp(path, norm_pathspec)) {
3949+
pathspec_matches = 1;
3950+
free(norm_pathspec);
3951+
norm_pathspec = NULL;
3952+
break;
3953+
}
3954+
free(norm_pathspec);
3955+
norm_pathspec = NULL;
3956+
}
3957+
}
3958+
if (pathspec_matches) {
3959+
if (data->ignored_too && data->ignored_too > 0) {
3960+
trace_printf("Forcing add of submodule ignored=all due to --force: %s\n", path);
3961+
} else {
3962+
printf("Skipping submodule due to ignore=all: %s\n", path);
3963+
printf(" Use -f|--force if you really want to add the update to the index.\n");
3964+
continue;
3965+
}
39393966
} else {
3940-
trace_printf("Skipping submodule with ignore=all: %s\n", path);
3941-
trace_printf(" Use -f if you really want to add them.");
3942-
/* Skip this path (submodule ignored) and move on to next diff pair */
3967+
/* No explicit pathspec match -> skip silently (or with trace). */
3968+
trace_printf("pathspec does not match %s\n", path);
39433969
continue;
39443970
}
39453971
}
@@ -3949,6 +3975,7 @@ static void update_callback(struct diff_queue_struct *q,
39493975
data->add_errors++;
39503976
}
39513977
break;
3978+
}
39523979
case DIFF_STATUS_DELETED:
39533980
if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
39543981
break;
@@ -3972,8 +3999,9 @@ int add_files_to_cache(struct repository *repo, const char *prefix,
39723999
data.index = repo->index;
39734000
data.include_sparse = include_sparse;
39744001
data.flags = flags;
3975-
trace_printf("DEBUG ignored_too=%d\n", ignored_too);
39764002
data.ignored_too = ignored_too;
4003+
data.pathspec = (struct pathspec *)pathspec;
4004+
39774005

39784006
repo_init_revisions(repo, &rev, prefix);
39794007
setup_revisions(0, NULL, &rev, NULL);

t/t2206-add-submodule-ignored.sh

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,13 @@ test_expect_success 'main: add submodule with default config' '
4747
git status --porcelain | grep "^ M sub$" &&
4848
echo
4949
'
50-
5150
#3
5251
# change the submodule config to ignore=all and check that status and log do not show changes
5352
test_expect_success 'main: submodule config ignore=all' '
5453
cd "${base_path}" &&
5554
cd main &&
5655
git config -f .gitmodules submodule.sub.ignore all &&
57-
git add . &&
56+
GIT_TRACE=1 git add . &&
5857
git commit -m "update submodule config sub.ignore all" &&
5958
! git status --porcelain | grep "^.*$" &&
6059
! git log --oneline --name-only | grep "^sub$" &&
@@ -77,26 +76,56 @@ test_expect_success 'sub: change to different sha1 and check status in main' '
7776
test_expect_success 'main: check normal add and status' '
7877
cd "${base_path}" &&
7978
cd main &&
80-
git add . &&
79+
GIT_TRACE=1 git add . &&
8180
! git status --porcelain | grep "^ M sub$" &&
8281
echo
8382
'
8483

8584
#6
86-
# check that 'git add --force' does stage the change in the submodule
87-
# and that 'git status' does show it as modified
85+
# check that 'git add --force .' does not stage the change in the submodule
86+
# and that 'git status' does not show it as modified
87+
test_expect_success 'main: check --force add . and status' '
88+
cd "${base_path}" &&
89+
cd main &&
90+
GIT_TRACE=1 git add --force . &&
91+
! git status --porcelain | grep "^M sub$" &&
92+
echo
93+
'
94+
95+
#7
96+
# check that 'git add .' does not stage the change in the submodule
97+
# and that 'git status' does not show it as modified
98+
test_expect_success 'main: check _add sub_ and status' '
99+
cd "${base_path}" &&
100+
cd main &&
101+
GIT_TRACE=1 git add sub | grep "Skipping submodule due to ignore=all: sub" &&
102+
! git status --porcelain | grep "^M sub$" &&
103+
echo
104+
'
105+
106+
#8
107+
# check that 'git add --force sub' does stage the change in the submodule
108+
# check that 'git add --force ./sub/' does stage the change in the submodule
109+
# and that 'git status --porcelain' does show it as modified
110+
# commit it..
88111
# check that 'git log --ignore-submodules=none' shows the submodule change
89112
# in the log
90-
test_expect_success 'main: check force add and status' '
113+
test_expect_success 'main: check force add sub and ./sub/ and status' '
91114
cd "${base_path}" &&
92115
cd main &&
93-
git add --force . &&
116+
echo "Adding with --force should work: git add --force sub" &&
117+
GIT_TRACE=1 git add --force sub &&
118+
git status --porcelain | grep "^M sub$" &&
119+
git restore --staged sub &&
120+
! git status --porcelain | grep "^M sub$" &&
121+
echo "Adding with --force should work: git add --force ./sub/" &&
122+
GIT_TRACE=1 git add --force ./sub/ &&
94123
git status --porcelain | grep "^M sub$" &&
95124
git commit -m "update submodule pointer" &&
96125
! git status --porcelain | grep "^ M sub$" &&
97126
git log --ignore-submodules=none --name-only --oneline | grep "^sub$" &&
98127
echo
99128
'
129+
100130
test_done
101131
exit 0
102-

0 commit comments

Comments
 (0)