pathspec.con commit fetch-pack: do not filter out one-level refs (4c22408)
   1#include "cache.h"
   2#include "dir.h"
   3#include "pathspec.h"
   4
   5/*
   6 * Finds which of the given pathspecs match items in the index.
   7 *
   8 * For each pathspec, sets the corresponding entry in the seen[] array
   9 * (which should be specs items long, i.e. the same size as pathspec)
  10 * to the nature of the "closest" (i.e. most specific) match found for
  11 * that pathspec in the index, if it was a closer type of match than
  12 * the existing entry.  As an optimization, matching is skipped
  13 * altogether if seen[] already only contains non-zero entries.
  14 *
  15 * If seen[] has not already been written to, it may make sense
  16 * to use find_pathspecs_matching_against_index() instead.
  17 */
  18void add_pathspec_matches_against_index(const char **pathspec,
  19                                        char *seen, int specs)
  20{
  21        int num_unmatched = 0, i;
  22
  23        /*
  24         * Since we are walking the index as if we were walking the directory,
  25         * we have to mark the matched pathspec as seen; otherwise we will
  26         * mistakenly think that the user gave a pathspec that did not match
  27         * anything.
  28         */
  29        for (i = 0; i < specs; i++)
  30                if (!seen[i])
  31                        num_unmatched++;
  32        if (!num_unmatched)
  33                return;
  34        for (i = 0; i < active_nr; i++) {
  35                const struct cache_entry *ce = active_cache[i];
  36                match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen);
  37        }
  38}
  39
  40/*
  41 * Finds which of the given pathspecs match items in the index.
  42 *
  43 * This is a one-shot wrapper around add_pathspec_matches_against_index()
  44 * which allocates, populates, and returns a seen[] array indicating the
  45 * nature of the "closest" (i.e. most specific) matches which each of the
  46 * given pathspecs achieves against all items in the index.
  47 */
  48char *find_pathspecs_matching_against_index(const char **pathspec)
  49{
  50        char *seen;
  51        int i;
  52
  53        for (i = 0; pathspec[i];  i++)
  54                ; /* just counting */
  55        seen = xcalloc(i, 1);
  56        add_pathspec_matches_against_index(pathspec, seen, i);
  57        return seen;
  58}
  59
  60/*
  61 * Check the index to see whether path refers to a submodule, or
  62 * something inside a submodule.  If the former, returns the path with
  63 * any trailing slash stripped.  If the latter, dies with an error
  64 * message.
  65 */
  66const char *check_path_for_gitlink(const char *path)
  67{
  68        int i, path_len = strlen(path);
  69        for (i = 0; i < active_nr; i++) {
  70                const struct cache_entry *ce = active_cache[i];
  71                if (S_ISGITLINK(ce->ce_mode)) {
  72                        int ce_len = ce_namelen(ce);
  73                        if (path_len <= ce_len || path[ce_len] != '/' ||
  74                            memcmp(ce->name, path, ce_len))
  75                                /* path does not refer to this
  76                                 * submodule or anything inside it */
  77                                continue;
  78                        if (path_len == ce_len + 1) {
  79                                /* path refers to submodule;
  80                                 * strip trailing slash */
  81                                return xstrndup(ce->name, ce_len);
  82                        } else {
  83                                die (_("Path '%s' is in submodule '%.*s'"),
  84                                     path, ce_len, ce->name);
  85                        }
  86                }
  87        }
  88        return path;
  89}
  90
  91/*
  92 * Dies if the given path refers to a file inside a symlinked
  93 * directory in the index.
  94 */
  95void die_if_path_beyond_symlink(const char *path, const char *prefix)
  96{
  97        if (has_symlink_leading_path(path, strlen(path))) {
  98                int len = prefix ? strlen(prefix) : 0;
  99                die(_("'%s' is beyond a symbolic link"), path + len);
 100        }
 101}