]> git.ipfire.org Git - thirdparty/git.git/blobdiff - dir.c
Merge branch 'ab/trace2-squelch-gcc-warning'
[thirdparty/git.git] / dir.c
diff --git a/dir.c b/dir.c
index ed68b7e6412cd695db18e16031e8da510da4c3a0..ebe5ec046e050683443507495b3dcfa903c420e4 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -59,6 +59,17 @@ void dir_init(struct dir_struct *dir)
        memset(dir, 0, sizeof(*dir));
 }
 
+struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp)
+{
+       struct dirent *e;
+
+       while ((e = readdir(dirp)) != NULL) {
+               if (!is_dot_or_dotdot(e->d_name))
+                       break;
+       }
+       return e;
+}
+
 int count_slashes(const char *s)
 {
        int cnt = 0;
@@ -306,7 +317,7 @@ static int do_read_blob(const struct object_id *oid, struct oid_stat *oid_stat,
  * [1] Only if DO_MATCH_DIRECTORY is passed; otherwise, this is NOT a match.
  * [2] Only if DO_MATCH_LEADING_PATHSPEC is passed; otherwise, not a match.
  */
-static int match_pathspec_item(const struct index_state *istate,
+static int match_pathspec_item(struct index_state *istate,
                               const struct pathspec_item *item, int prefix,
                               const char *name, int namelen, unsigned flags)
 {
@@ -429,7 +440,7 @@ static int match_pathspec_item(const struct index_state *istate,
  * pathspec did not match any names, which could indicate that the
  * user mistyped the nth pathspec.
  */
-static int do_match_pathspec(const struct index_state *istate,
+static int do_match_pathspec(struct index_state *istate,
                             const struct pathspec *ps,
                             const char *name, int namelen,
                             int prefix, char *seen,
@@ -500,7 +511,7 @@ static int do_match_pathspec(const struct index_state *istate,
        return retval;
 }
 
-static int match_pathspec_with_flags(const struct index_state *istate,
+static int match_pathspec_with_flags(struct index_state *istate,
                                     const struct pathspec *ps,
                                     const char *name, int namelen,
                                     int prefix, char *seen, unsigned flags)
@@ -516,7 +527,7 @@ static int match_pathspec_with_flags(const struct index_state *istate,
        return negative ? 0 : positive;
 }
 
-int match_pathspec(const struct index_state *istate,
+int match_pathspec(struct index_state *istate,
                   const struct pathspec *ps,
                   const char *name, int namelen,
                   int prefix, char *seen, int is_dir)
@@ -529,7 +540,7 @@ int match_pathspec(const struct index_state *istate,
 /**
  * Check if a submodule is a superset of the pathspec
  */
-int submodule_path_match(const struct index_state *istate,
+int submodule_path_match(struct index_state *istate,
                         const struct pathspec *ps,
                         const char *submodule_name,
                         char *seen)
@@ -892,7 +903,7 @@ void add_pattern(const char *string, const char *base,
        add_pattern_to_hashsets(pl, pattern);
 }
 
-static int read_skip_worktree_file_from_index(const struct index_state *istate,
+static int read_skip_worktree_file_from_index(struct index_state *istate,
                                              const char *path,
                                              size_t *size_out, char **data_out,
                                              struct oid_stat *oid_stat)
@@ -1035,6 +1046,9 @@ static int add_patterns_from_buffer(char *buf, size_t size,
                                    const char *base, int baselen,
                                    struct pattern_list *pl);
 
+/* Flags for add_patterns() */
+#define PATTERN_NOFOLLOW (1<<0)
+
 /*
  * Given a file with name "fname", read it (either from disk, or from
  * an index if 'istate' is non-null), parse it and store the
@@ -1046,7 +1060,7 @@ static int add_patterns_from_buffer(char *buf, size_t size,
  */
 static int add_patterns(const char *fname, const char *base, int baselen,
                        struct pattern_list *pl, struct index_state *istate,
-                       struct oid_stat *oid_stat)
+                       unsigned flags, struct oid_stat *oid_stat)
 {
        struct stat st;
        int r;
@@ -1054,7 +1068,11 @@ static int add_patterns(const char *fname, const char *base, int baselen,
        size_t size = 0;
        char *buf;
 
-       fd = open(fname, O_RDONLY);
+       if (flags & PATTERN_NOFOLLOW)
+               fd = open_nofollow(fname, O_RDONLY);
+       else
+               fd = open(fname, O_RDONLY);
+
        if (fd < 0 || fstat(fd, &st) < 0) {
                if (fd < 0)
                        warn_on_fopen_errors(fname);
@@ -1143,9 +1161,10 @@ static int add_patterns_from_buffer(char *buf, size_t size,
 
 int add_patterns_from_file_to_list(const char *fname, const char *base,
                                   int baselen, struct pattern_list *pl,
-                                  struct index_state *istate)
+                                  struct index_state *istate,
+                                  unsigned flags)
 {
-       return add_patterns(fname, base, baselen, pl, istate, NULL);
+       return add_patterns(fname, base, baselen, pl, istate, flags, NULL);
 }
 
 int add_patterns_from_blob_to_list(
@@ -1194,7 +1213,7 @@ static void add_patterns_from_file_1(struct dir_struct *dir, const char *fname,
        if (!dir->untracked)
                dir->unmanaged_exclude_files++;
        pl = add_pattern_list(dir, EXC_FILE, fname);
-       if (add_patterns(fname, "", 0, pl, NULL, oid_stat) < 0)
+       if (add_patterns(fname, "", 0, pl, NULL, 0, oid_stat) < 0)
                die(_("cannot use %s as an exclude file"), fname);
 }
 
@@ -1558,6 +1577,7 @@ static void prep_exclude(struct dir_struct *dir,
                        strbuf_addstr(&sb, dir->exclude_per_dir);
                        pl->src = strbuf_detach(&sb, NULL);
                        add_patterns(pl->src, pl->src, stk->baselen, pl, istate,
+                                    PATTERN_NOFOLLOW,
                                     untracked ? &oid_stat : NULL);
                }
                /*
@@ -1740,13 +1760,13 @@ static enum exist_status directory_exists_in_index(struct index_state *istate,
  * Case 3: if we didn't have it in the index previously, we
  * have a few sub-cases:
  *
- *  (a) if "show_other_directories" is true, we show it as
- *      just a directory, unless "hide_empty_directories" is
+ *  (a) if DIR_SHOW_OTHER_DIRECTORIES flag is set, we show it as
+ *      just a directory, unless DIR_HIDE_EMPTY_DIRECTORIES is
  *      also true, in which case we need to check if it contains any
  *      untracked and / or ignored files.
- *  (b) if it looks like a git directory, and we don't have
- *      'no_gitlinks' set we treat it as a gitlink, and show it
- *      as a directory.
+ *  (b) if it looks like a git directory and we don't have the
+ *      DIR_NO_GITLINKS flag, then we treat it as a gitlink, and
+ *      show it as a directory.
  *  (c) otherwise, we recurse into it.
  */
 static enum path_treatment treat_directory(struct dir_struct *dir,
@@ -1834,7 +1854,6 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
                return path_recurse;
        }
 
-       /* This is the "show_other_directories" case */
        assert(dir->flags & DIR_SHOW_OTHER_DIRECTORIES);
 
        /*
@@ -1849,7 +1868,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
        /* Special cases for where this directory is excluded/ignored */
        if (excluded) {
                /*
-                * In the show_other_directories case, if we're not
+                * If DIR_SHOW_OTHER_DIRECTORIES is set and we're not
                 * hiding empty directories, there is no need to
                 * recurse into an ignored directory.
                 */
@@ -2333,7 +2352,7 @@ static int read_cached_dir(struct cached_dir *cdir)
        struct dirent *de;
 
        if (cdir->fdir) {
-               de = readdir(cdir->fdir);
+               de = readdir_skip_dot_and_dotdot(cdir->fdir);
                if (!de) {
                        cdir->d_name = NULL;
                        cdir->d_type = DT_UNKNOWN;
@@ -2932,11 +2951,9 @@ int is_empty_dir(const char *path)
        if (!dir)
                return 0;
 
-       while ((e = readdir(dir)) != NULL)
-               if (!is_dot_or_dotdot(e->d_name)) {
-                       ret = 0;
-                       break;
-               }
+       e = readdir_skip_dot_and_dotdot(dir);
+       if (e)
+               ret = 0;
 
        closedir(dir);
        return ret;
@@ -2976,10 +2993,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
        strbuf_complete(path, '/');
 
        len = path->len;
-       while ((e = readdir(dir)) != NULL) {
+       while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
                struct stat st;
-               if (is_dot_or_dotdot(e->d_name))
-                       continue;
 
                strbuf_setlen(path, len);
                strbuf_addstr(path, e->d_name);
@@ -3055,7 +3070,7 @@ int get_sparse_checkout_patterns(struct pattern_list *pl)
        char *sparse_filename = get_sparse_checkout_filename();
 
        pl->use_cone_patterns = core_sparse_checkout_cone;
-       res = add_patterns_from_file_to_list(sparse_filename, "", 0, pl, NULL);
+       res = add_patterns_from_file_to_list(sparse_filename, "", 0, pl, NULL, 0);
 
        free(sparse_filename);
        return res;
@@ -3384,7 +3399,7 @@ static void read_oid(size_t pos, void *cb)
                rd->data = rd->end + 1;
                return;
        }
-       hashcpy(ud->exclude_oid.hash, rd->data);
+       oidread(&ud->exclude_oid, rd->data);
        rd->data += the_hash_algo->rawsz;
 }
 
@@ -3392,7 +3407,7 @@ static void load_oid_stat(struct oid_stat *oid_stat, const unsigned char *data,
                          const unsigned char *sha1)
 {
        stat_data_from_disk(&oid_stat->stat, data);
-       hashcpy(oid_stat->oid.hash, sha1);
+       oidread(&oid_stat->oid, sha1);
        oid_stat->valid = 1;
 }
 
@@ -3582,6 +3597,8 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,
        if (repo_read_index(&subrepo) < 0)
                die(_("index file corrupt in repo %s"), subrepo.gitdir);
 
+       /* TODO: audit for interaction with sparse-index. */
+       ensure_full_index(subrepo.index);
        for (i = 0; i < subrepo.index->cache_nr; i++) {
                const struct cache_entry *ce = subrepo.index->cache[i];
 
@@ -3596,7 +3613,7 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,
                         */
                        i++;
 
-               sub = submodule_from_path(&subrepo, &null_oid, ce->name);
+               sub = submodule_from_path(&subrepo, null_oid(), ce->name);
                if (!sub || !is_submodule_active(&subrepo, ce->name))
                        /* .gitmodules broken or inactive sub */
                        continue;