parse_pathspec: support stripping/checking submodule paths
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Sun, 14 Jul 2013 08:35:34 +0000 (15:35 +0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 15 Jul 2013 17:56:06 +0000 (10:56 -0700)
PATHSPEC_SYMLINK_LEADING_PATH and _STRIP_SUBMODULE_SLASH_EXPENSIVE are
respectively the alternate implementation of
pathspec.c:die_if_path_beyond_symlink() and
pathspec.c:check_path_for_gitlink(). They are intended to replace
those functions when builtin/add.c and builtin/check-ignore.c are
converted to use parse_pathspec.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
pathspec.c
pathspec.h
index 1c07c23fe0e4bb7b9847fca47624b3097a175adf..e2a4f910f9b46f27518a14566c4d8eaaea03c58b 100644 (file)
@@ -214,6 +214,26 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
                match[item->len] = '\0';
        }
 
+       if (flags & PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE)
+               for (i = 0; i < active_nr; i++) {
+                       struct cache_entry *ce = active_cache[i];
+                       int ce_len = ce_namelen(ce);
+
+                       if (!S_ISGITLINK(ce->ce_mode))
+                               continue;
+
+                       if (item->len <= ce_len || match[ce_len] != '/' ||
+                           memcmp(ce->name, match, ce_len))
+                               continue;
+                       if (item->len == ce_len + 1) {
+                               /* strip trailing slash */
+                               item->len--;
+                               match[item->len] = '\0';
+                       } else
+                               die (_("Pathspec '%s' is in submodule '%.*s'"),
+                                    elt, ce_len, ce->name);
+               }
+
        if (limit_pathspec_to_literal())
                item->nowildcard_len = item->len;
        else
@@ -329,6 +349,12 @@ void parse_pathspec(struct pathspec *pathspec,
                        unsupported_magic(entry,
                                          item[i].magic & magic_mask,
                                          short_magic);
+
+               if ((flags & PATHSPEC_SYMLINK_LEADING_PATH) &&
+                   has_symlink_leading_path(item[i].match, item[i].len)) {
+                       die(_("pathspec '%s' is beyond a symbolic link"), entry);
+               }
+
                if (item[i].nowildcard_len < item[i].len)
                        pathspec->has_wildcard = 1;
                pathspec->magic |= item[i].magic;
index 51448513e6a0abf0506afda1401a89a751ce36ba..450fc030349bf90e59a156b19648ef4edc806eb8 100644 (file)
@@ -33,6 +33,16 @@ struct pathspec {
 #define PATHSPEC_MAXDEPTH_VALID (1<<2) /* max_depth field is valid */
 /* strip the trailing slash if the given path is a gitlink */
 #define PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP (1<<3)
+/* die if a symlink is part of the given path's directory */
+#define PATHSPEC_SYMLINK_LEADING_PATH (1<<4)
+/*
+ * This is like a combination of ..LEADING_PATH and .._SLASH_CHEAP
+ * (but not the same): it strips the trailing slash if the given path
+ * is a gitlink but also checks and dies if gitlink is part of the
+ * leading path (i.e. the given path goes beyond a submodule). It's
+ * safer than _SLASH_CHEAP and also more expensive.
+ */
+#define PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE (1<<5)
 
 extern int init_pathspec(struct pathspec *, const char **);
 extern void parse_pathspec(struct pathspec *pathspec,