Skip to content

Commit bdab972

Browse files
bmwillgitster
authored andcommitted
submodule: add die_in_unpopulated_submodule function
Currently 'git add' is the only command which dies when launched from an unpopulated submodule (the place-holder directory for a submodule which hasn't been checked out). This is triggered implicitly by passing the PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE flag to 'parse_pathspec()'. Instead make this desire more explicit by creating a function 'die_in_unpopulated_submodule()' which dies if the provided 'prefix' has a leading path component which matches a submodule in the the index. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 2c3b407 commit bdab972

5 files changed

Lines changed: 36 additions & 34 deletions

File tree

builtin/add.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "revision.h"
1818
#include "bulk-checkin.h"
1919
#include "argv-array.h"
20+
#include "submodule.h"
2021

2122
static const char * const builtin_add_usage[] = {
2223
N_("git add [<options>] [--] <pathspec>..."),
@@ -379,6 +380,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
379380
if (read_cache() < 0)
380381
die(_("index file corrupt"));
381382

383+
die_in_unpopulated_submodule(&the_index, prefix);
384+
382385
/*
383386
* Check the "pathspec '%s' did not match any files" block
384387
* below before enabling new magic.

pathspec.c

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -424,27 +424,6 @@ static void strip_submodule_slash_expensive(struct pathspec_item *item)
424424
}
425425
}
426426

427-
static void die_inside_submodule_path(struct pathspec_item *item)
428-
{
429-
int i;
430-
431-
for (i = 0; i < active_nr; i++) {
432-
struct cache_entry *ce = active_cache[i];
433-
int ce_len = ce_namelen(ce);
434-
435-
if (!S_ISGITLINK(ce->ce_mode))
436-
continue;
437-
438-
if (item->len < ce_len ||
439-
!(item->match[ce_len] == '/' || item->match[ce_len] == '\0') ||
440-
memcmp(ce->name, item->match, ce_len))
441-
continue;
442-
443-
die(_("Pathspec '%s' is in submodule '%.*s'"),
444-
item->original, ce_len, ce->name);
445-
}
446-
}
447-
448427
/*
449428
* Perform the initialization of a pathspec_item based on a pathspec element.
450429
*/
@@ -547,14 +526,6 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
547526
/* sanity checks, pathspec matchers assume these are sane */
548527
if (item->nowildcard_len > item->len ||
549528
item->prefix > item->len) {
550-
/*
551-
* This case can be triggered by the user pointing us to a
552-
* pathspec inside a submodule, which is an input error.
553-
* Detect that here and complain, but fallback in the
554-
* non-submodule case to a BUG, as we have no idea what
555-
* would trigger that.
556-
*/
557-
die_inside_submodule_path(item);
558529
die ("BUG: error initializing pathspec_item");
559530
}
560531
}

submodule.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,36 @@ int is_submodule_populated_gently(const char *path, int *return_error_code)
282282
return ret;
283283
}
284284

285+
/*
286+
* Dies if the provided 'prefix' corresponds to an unpopulated submodule
287+
*/
288+
void die_in_unpopulated_submodule(const struct index_state *istate,
289+
const char *prefix)
290+
{
291+
int i, prefixlen;
292+
293+
if (!prefix)
294+
return;
295+
296+
prefixlen = strlen(prefix);
297+
298+
for (i = 0; i < istate->cache_nr; i++) {
299+
struct cache_entry *ce = istate->cache[i];
300+
int ce_len = ce_namelen(ce);
301+
302+
if (!S_ISGITLINK(ce->ce_mode))
303+
continue;
304+
if (prefixlen <= ce_len)
305+
continue;
306+
if (strncmp(ce->name, prefix, ce_len))
307+
continue;
308+
if (prefix[ce_len] != '/')
309+
continue;
310+
311+
die(_("in unpopulated submodule '%s'"), ce->name);
312+
}
313+
}
314+
285315
int parse_submodule_update_strategy(const char *value,
286316
struct submodule_update_strategy *dst)
287317
{

submodule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ extern int is_submodule_initialized(const char *path);
4949
* Otherwise the return error code is the same as of resolve_gitdir_gently.
5050
*/
5151
extern int is_submodule_populated_gently(const char *path, int *return_error_code);
52+
extern void die_in_unpopulated_submodule(const struct index_state *istate,
53+
const char *prefix);
5254
extern int parse_submodule_update_strategy(const char *value,
5355
struct submodule_update_strategy *dst);
5456
extern const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);

t/t6134-pathspec-in-submodule.sh

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,9 @@ test_expect_success 'error message for path inside submodule' '
2424
test_cmp expect actual
2525
'
2626

27-
cat <<EOF >expect
28-
fatal: Pathspec '.' is in submodule 'sub'
29-
EOF
30-
3127
test_expect_success 'error message for path inside submodule from within submodule' '
3228
test_must_fail git -C sub add . 2>actual &&
33-
test_cmp expect actual
29+
test_i18ngrep "in unpopulated submodule" actual
3430
'
3531

3632
test_done

0 commit comments

Comments
 (0)