From bdab972153a73815e04e9699406433e409ed28ab Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 9 May 2017 12:17:59 -0700 Subject: 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 Signed-off-by: Junio C Hamano --- submodule.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'submodule.c') diff --git a/submodule.c b/submodule.c index d3299e29c0..885663c421 100644 --- a/submodule.c +++ b/submodule.c @@ -282,6 +282,36 @@ int is_submodule_populated_gently(const char *path, int *return_error_code) return ret; } +/* + * Dies if the provided 'prefix' corresponds to an unpopulated submodule + */ +void die_in_unpopulated_submodule(const struct index_state *istate, + const char *prefix) +{ + int i, prefixlen; + + if (!prefix) + return; + + prefixlen = strlen(prefix); + + for (i = 0; i < istate->cache_nr; i++) { + struct cache_entry *ce = istate->cache[i]; + int ce_len = ce_namelen(ce); + + if (!S_ISGITLINK(ce->ce_mode)) + continue; + if (prefixlen <= ce_len) + continue; + if (strncmp(ce->name, prefix, ce_len)) + continue; + if (prefix[ce_len] != '/') + continue; + + die(_("in unpopulated submodule '%s'"), ce->name); + } +} + int parse_submodule_update_strategy(const char *value, struct submodule_update_strategy *dst) { -- cgit v1.2.1 From c08397e3aa46fd0f0da29dfe5b257839b9c5d1c8 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Thu, 11 May 2017 15:04:24 -0700 Subject: pathspec: remove PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE flag Since (ae8d08242 pathspec: pass directory indicator to match_pathspec_item()) the path matching logic has been able to cope with submodules without needing to strip off a trailing slash if a path refers to a submodule. Since the stripping the trailing slash is no longer necessary, remove the PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE flag. In addition, factor out the logic which dies if a path decends into a submodule so that it can still be used as a check after a pathspec struct has been initialized. Signed-off-by: Brandon Williams Signed-off-by: Junio C Hamano --- submodule.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'submodule.c') diff --git a/submodule.c b/submodule.c index 885663c421..80851d0447 100644 --- a/submodule.c +++ b/submodule.c @@ -312,6 +312,39 @@ void die_in_unpopulated_submodule(const struct index_state *istate, } } +/* + * Dies if any paths in the provided pathspec descends into a submodule + */ +void die_path_inside_submodule(const struct index_state *istate, + const struct pathspec *ps) +{ + int i, j; + + for (i = 0; i < istate->cache_nr; i++) { + struct cache_entry *ce = istate->cache[i]; + int ce_len = ce_namelen(ce); + + if (!S_ISGITLINK(ce->ce_mode)) + continue; + + for (j = 0; j < ps->nr ; j++) { + const struct pathspec_item *item = &ps->items[j]; + + if (item->len <= ce_len) + continue; + if (item->match[ce_len] != '/') + continue; + if (strncmp(ce->name, item->match, ce_len)) + continue; + if (item->len == ce_len + 1) + continue; + + die(_("Pathspec '%s' is in submodule '%.*s'"), + item->original, ce_len, ce->name); + } + } +} + int parse_submodule_update_strategy(const char *value, struct submodule_update_strategy *dst) { -- cgit v1.2.1