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 <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed May 11, 2017 at 15:04 UTC c08397e3aa46fd0f0da29dfe5b257839b9c5d1c8
6 files changed +44 -43
builtin/add.c
+3 -2
@@ -388,10 +388,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
388 */
389 parse_pathspec(&pathspec, 0,
390 PATHSPEC_PREFER_FULL |
391 - PATHSPEC_SYMLINK_LEADING_PATH |
392 - PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,
391 + PATHSPEC_SYMLINK_LEADING_PATH,
392 prefix, argv);
393
394 + die_path_inside_submodule(&the_index, &pathspec);
395 +
396 if (add_new_files) {
397 int baselen;
398
builtin/check-ignore.c
+3 -1
@@ -4,6 +4,7 @@
4 #include "quote.h"
5 #include "pathspec.h"
6 #include "parse-options.h"
7 +#include "submodule.h"
8
9 static int quiet, verbose, stdin_paths, show_non_matching, no_index;
10 static const char * const check_ignore_usage[] = {
@@ -87,10 +88,11 @@ static int check_ignore(struct dir_struct *dir,
88 parse_pathspec(&pathspec,
89 PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
90 PATHSPEC_SYMLINK_LEADING_PATH |
90 - PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE |
91 PATHSPEC_KEEP_ORDER,
92 prefix, argv);
93
94 + die_path_inside_submodule(&the_index, &pathspec);
95 +
96 /*
97 * look for pathspecs matching entries in the index, since these
98 * should not be ignored, in order to be consistent with
pathspec.c
-29
@@ -398,32 +398,6 @@ static void strip_submodule_slash_cheap(struct pathspec_item *item)
398 }
399 }
400
401 -static void strip_submodule_slash_expensive(struct pathspec_item *item)
402 -{
403 - int i;
404 -
405 - for (i = 0; i < active_nr; i++) {
406 - struct cache_entry *ce = active_cache[i];
407 - int ce_len = ce_namelen(ce);
408 -
409 - if (!S_ISGITLINK(ce->ce_mode))
410 - continue;
411 -
412 - if (item->len <= ce_len || item->match[ce_len] != '/' ||
413 - memcmp(ce->name, item->match, ce_len))
414 - continue;
415 -
416 - if (item->len == ce_len + 1) {
417 - /* strip trailing slash */
418 - item->len--;
419 - item->match[item->len] = '\0';
420 - } else {
421 - die(_("Pathspec '%s' is in submodule '%.*s'"),
422 - item->original, ce_len, ce->name);
423 - }
424 - }
425 -}
426 -
401 /*
402 * Perform the initialization of a pathspec_item based on a pathspec element.
403 */
@@ -499,9 +473,6 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
473 if (flags & PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP)
474 strip_submodule_slash_cheap(item);
475
502 - if (flags & PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE)
503 - strip_submodule_slash_expensive(item);
504 -
476 if (magic & PATHSPEC_LITERAL) {
477 item->nowildcard_len = item->len;
478 } else {
pathspec.h
+3 -11
@@ -62,23 +62,15 @@ struct pathspec {
62 #define PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP (1<<3)
63 /* die if a symlink is part of the given path's directory */
64 #define PATHSPEC_SYMLINK_LEADING_PATH (1<<4)
65 -/*
66 - * This is like a combination of ..LEADING_PATH and .._SLASH_CHEAP
67 - * (but not the same): it strips the trailing slash if the given path
68 - * is a gitlink but also checks and dies if gitlink is part of the
69 - * leading path (i.e. the given path goes beyond a submodule). It's
70 - * safer than _SLASH_CHEAP and also more expensive.
71 - */
72 -#define PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE (1<<5)
73 -#define PATHSPEC_PREFIX_ORIGIN (1<<6)
74 -#define PATHSPEC_KEEP_ORDER (1<<7)
65 +#define PATHSPEC_PREFIX_ORIGIN (1<<5)
66 +#define PATHSPEC_KEEP_ORDER (1<<6)
67 /*
68 * For the callers that just need pure paths from somewhere else, not
69 * from command line. Global --*-pathspecs options are ignored. No
70 * magic is parsed in each pathspec either. If PATHSPEC_LITERAL is
71 * allowed, then it will automatically set for every pathspec.
72 */
81 -#define PATHSPEC_LITERAL_PATH (1<<8)
73 +#define PATHSPEC_LITERAL_PATH (1<<7)
74
75 extern void parse_pathspec(struct pathspec *pathspec,
76 unsigned magic_mask,
submodule.c
+33
@@ -312,6 +312,39 @@ void die_in_unpopulated_submodule(const struct index_state *istate,
312 }
313 }
314
315 +/*
316 + * Dies if any paths in the provided pathspec descends into a submodule
317 + */
318 +void die_path_inside_submodule(const struct index_state *istate,
319 + const struct pathspec *ps)
320 +{
321 + int i, j;
322 +
323 + for (i = 0; i < istate->cache_nr; i++) {
324 + struct cache_entry *ce = istate->cache[i];
325 + int ce_len = ce_namelen(ce);
326 +
327 + if (!S_ISGITLINK(ce->ce_mode))
328 + continue;
329 +
330 + for (j = 0; j < ps->nr ; j++) {
331 + const struct pathspec_item *item = &ps->items[j];
332 +
333 + if (item->len <= ce_len)
334 + continue;
335 + if (item->match[ce_len] != '/')
336 + continue;
337 + if (strncmp(ce->name, item->match, ce_len))
338 + continue;
339 + if (item->len == ce_len + 1)
340 + continue;
341 +
342 + die(_("Pathspec '%s' is in submodule '%.*s'"),
343 + item->original, ce_len, ce->name);
344 + }
345 + }
346 +}
347 +
348 int parse_submodule_update_strategy(const char *value,
349 struct submodule_update_strategy *dst)
350 {
submodule.h
+2
@@ -51,6 +51,8 @@ extern int is_submodule_initialized(const char *path);
51 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);
54 +extern void die_path_inside_submodule(const struct index_state *istate,
55 + const struct pathspec *ps);
56 extern int parse_submodule_update_strategy(const char *value,
57 struct submodule_update_strategy *dst);
58 extern const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);