Merge branch 'jc/fake-ancestor-with-non-blobs'
[gitweb.git] / pathspec.c
index 1472af89ce262ec0e59aba0d46c10d3f588a15e1..284f3970a31eb86a121712267e36ff162452590d 100644 (file)
  * altogether if seen[] already only contains non-zero entries.
  *
  * If seen[] has not already been written to, it may make sense
- * to use find_used_pathspec() instead.
+ * to use find_pathspecs_matching_against_index() instead.
  */
-void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
+void add_pathspec_matches_against_index(const char **pathspec,
+                                       char *seen, int specs)
 {
        int num_unmatched = 0, i;
 
@@ -39,12 +40,12 @@ void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
 /*
  * Finds which of the given pathspecs match items in the index.
  *
- * This is a one-shot wrapper around fill_pathspec_matches() which
- * allocates, populates, and returns a seen[] array indicating the
- * nature of the "closest" (i.e. most specific) matches which each of
- * the given pathspecs achieves against all items in the index.
+ * This is a one-shot wrapper around add_pathspec_matches_against_index()
+ * which allocates, populates, and returns a seen[] array indicating the
+ * nature of the "closest" (i.e. most specific) matches which each of the
+ * given pathspecs achieves against all items in the index.
  */
-char *find_used_pathspec(const char **pathspec)
+char *find_pathspecs_matching_against_index(const char **pathspec)
 {
        char *seen;
        int i;
@@ -52,6 +53,49 @@ char *find_used_pathspec(const char **pathspec)
        for (i = 0; pathspec[i];  i++)
                ; /* just counting */
        seen = xcalloc(i, 1);
-       fill_pathspec_matches(pathspec, seen, i);
+       add_pathspec_matches_against_index(pathspec, seen, i);
        return seen;
 }
+
+/*
+ * Check the index to see whether path refers to a submodule, or
+ * something inside a submodule.  If the former, returns the path with
+ * any trailing slash stripped.  If the latter, dies with an error
+ * message.
+ */
+const char *check_path_for_gitlink(const char *path)
+{
+       int i, path_len = strlen(path);
+       for (i = 0; i < active_nr; i++) {
+               struct cache_entry *ce = active_cache[i];
+               if (S_ISGITLINK(ce->ce_mode)) {
+                       int ce_len = ce_namelen(ce);
+                       if (path_len <= ce_len || path[ce_len] != '/' ||
+                           memcmp(ce->name, path, ce_len))
+                               /* path does not refer to this
+                                * submodule or anything inside it */
+                               continue;
+                       if (path_len == ce_len + 1) {
+                               /* path refers to submodule;
+                                * strip trailing slash */
+                               return xstrndup(ce->name, ce_len);
+                       } else {
+                               die (_("Path '%s' is in submodule '%.*s'"),
+                                    path, ce_len, ce->name);
+                       }
+               }
+       }
+       return path;
+}
+
+/*
+ * Dies if the given path refers to a file inside a symlinked
+ * directory in the index.
+ */
+void die_if_path_beyond_symlink(const char *path, const char *prefix)
+{
+       if (has_symlink_leading_path(path, strlen(path))) {
+               int len = prefix ? strlen(prefix) : 0;
+               die(_("'%s' is beyond a symbolic link"), path + len);
+       }
+}