]> git.ipfire.org Git - thirdparty/git.git/blobdiff - dir.c
dir: convert to strbuf
[thirdparty/git.git] / dir.c
diff --git a/dir.c b/dir.c
index 532bcb65b523223b66efd3f4e458f62fcbe0d6a5..6d0ea9e70b26b46a244e8aac857880b4d0d3a8f5 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -230,7 +230,7 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
                        return MATCHED_RECURSIVELY;
        }
 
-       if (item->has_wildcard && !fnmatch(match, name, 0))
+       if (item->use_wildcard && !fnmatch(match, name, 0))
                return MATCHED_FNMATCH;
 
        return 0;
@@ -866,14 +866,14 @@ enum path_treatment {
 };
 
 static enum path_treatment treat_one_path(struct dir_struct *dir,
-                                         char *path, int *len,
+                                         struct strbuf *path,
                                          const struct path_simplify *simplify,
                                          int dtype, struct dirent *de)
 {
-       int exclude = excluded(dir, path, &dtype);
+       int exclude = excluded(dir, path->buf, &dtype);
        if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
-           && exclude_matches_pathspec(path, *len, simplify))
-               dir_add_ignored(dir, path, *len);
+           && exclude_matches_pathspec(path->buf, path->len, simplify))
+               dir_add_ignored(dir, path->buf, path->len);
 
        /*
         * Excluded? If we don't explicitly want to show
@@ -883,7 +883,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
                return path_ignored;
 
        if (dtype == DT_UNKNOWN)
-               dtype = get_dtype(de, path, *len);
+               dtype = get_dtype(de, path->buf, path->len);
 
        /*
         * Do we want to see just the ignored files?
@@ -900,9 +900,8 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
        default:
                return path_ignored;
        case DT_DIR:
-               memcpy(path + *len, "/", 2);
-               (*len)++;
-               switch (treat_directory(dir, path, *len, simplify)) {
+               strbuf_addch(path, '/');
+               switch (treat_directory(dir, path->buf, path->len, simplify)) {
                case show_directory:
                        if (exclude != !!(dir->flags
                                          & DIR_SHOW_IGNORED))
@@ -923,26 +922,21 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
 
 static enum path_treatment treat_path(struct dir_struct *dir,
                                      struct dirent *de,
-                                     char *path, int path_max,
+                                     struct strbuf *path,
                                      int baselen,
-                                     const struct path_simplify *simplify,
-                                     int *len)
+                                     const struct path_simplify *simplify)
 {
        int dtype;
 
        if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git"))
                return path_ignored;
-       *len = strlen(de->d_name);
-       /* Ignore overly long pathnames! */
-       if (*len + baselen + 8 > path_max)
-               return path_ignored;
-       memcpy(path + baselen, de->d_name, *len + 1);
-       *len += baselen;
-       if (simplify_away(path, *len, simplify))
+       strbuf_setlen(path, baselen);
+       strbuf_addstr(path, de->d_name);
+       if (simplify_away(path->buf, path->len, simplify))
                return path_ignored;
 
        dtype = DTYPE(de);
-       return treat_one_path(dir, path, len, simplify, dtype, de);
+       return treat_one_path(dir, path, simplify, dtype, de);
 }
 
 /*
@@ -964,16 +958,15 @@ static int read_directory_recursive(struct dir_struct *dir,
 
        if (fdir) {
                struct dirent *de;
-               char path[PATH_MAX + 1];
-               memcpy(path, base, baselen);
+               struct strbuf path = STRBUF_INIT;
+
+               strbuf_add(&path, base, baselen);
 
                while ((de = readdir(fdir)) != NULL) {
-                       int len;
-                       switch (treat_path(dir, de, path, sizeof(path),
-                                          baselen, simplify, &len)) {
+                       switch (treat_path(dir, de, &path, baselen, simplify)) {
                        case path_recurse:
                                contents += read_directory_recursive
-                                       (dir, pathlen, 0, simplify);
+                                       (dir, path.buf, path.len, 0, simplify);
                                continue;
                        case path_ignored:
                                continue;
@@ -984,10 +977,11 @@ static int read_directory_recursive(struct dir_struct *dir,
                        if (check_only)
                                goto exit_early;
                        else
-                               dir_add_name(dir, pathlen);
+                               dir_add_name(dir, path.buf, path.len);
                }
 exit_early:
                closedir(fdir);
+               strbuf_release(&path);
        }
 
        return contents;
@@ -1051,8 +1045,8 @@ static int treat_leading_path(struct dir_struct *dir,
                              const char *path, int len,
                              const struct path_simplify *simplify)
 {
-       char pathbuf[PATH_MAX];
-       int baselen, blen;
+       struct strbuf sb = STRBUF_INIT;
+       int baselen, rc = 0;
        const char *cp;
 
        while (len && path[len - 1] == '/')
@@ -1067,19 +1061,22 @@ static int treat_leading_path(struct dir_struct *dir,
                        baselen = len;
                else
                        baselen = cp - path;
-               memcpy(pathbuf, path, baselen);
-               pathbuf[baselen] = '\0';
-               if (!is_directory(pathbuf))
-                       return 0;
-               if (simplify_away(pathbuf, baselen, simplify))
-                       return 0;
-               blen = baselen;
-               if (treat_one_path(dir, pathbuf, &blen, simplify,
+               strbuf_setlen(&sb, 0);
+               strbuf_add(&sb, path, baselen);
+               if (!is_directory(sb.buf))
+                       break;
+               if (simplify_away(sb.buf, sb.len, simplify))
+                       break;
+               if (treat_one_path(dir, &sb, simplify,
                                   DT_DIR, NULL) == path_ignored)
-                       return 0; /* do not recurse into it */
-               if (len <= baselen)
-                       return 1; /* finished checking */
+                       break; /* do not recurse into it */
+               if (len <= baselen) {
+                       rc = 1;
+                       break; /* finished checking */
+               }
        }
+       strbuf_release(&sb);
+       return rc;
 }
 
 int read_directory(struct dir_struct *dir, const char *path, int len, const char **pathspec)
@@ -1105,57 +1102,45 @@ int file_exists(const char *f)
 }
 
 /*
- * get_relative_cwd() gets the prefix of the current working directory
- * relative to 'dir'.  If we are not inside 'dir', it returns NULL.
- *
- * As a convenience, it also returns NULL if 'dir' is already NULL.  The
- * reason for this behaviour is that it is natural for functions returning
- * directory names to return NULL to say "this directory does not exist"
- * or "this directory is invalid".  These cases are usually handled the
- * same as if the cwd is not inside 'dir' at all, so get_relative_cwd()
- * returns NULL for both of them.
- *
- * Most notably, get_relative_cwd(buffer, size, get_git_work_tree())
- * unifies the handling of "outside work tree" with "no work tree at all".
+ * Given two normalized paths (a trailing slash is ok), if subdir is
+ * outside dir, return -1.  Otherwise return the offset in subdir that
+ * can be used as relative path to dir.
  */
-char *get_relative_cwd(char *buffer, int size, const char *dir)
+int dir_inside_of(const char *subdir, const char *dir)
 {
-       char *cwd = buffer;
-
-       if (!dir)
-               return NULL;
-       if (!getcwd(buffer, size))
-               die_errno("can't find the current directory");
+       int offset = 0;
 
-       if (!is_absolute_path(dir))
-               dir = real_path(dir);
+       assert(dir && subdir && *dir && *subdir);
 
-       while (*dir && *dir == *cwd) {
+       while (*dir && *subdir && *dir == *subdir) {
                dir++;
-               cwd++;
-       }
-       if (*dir)
-               return NULL;
-       switch (*cwd) {
-       case '\0':
-               return cwd;
-       case '/':
-               return cwd + 1;
-       default:
-               /*
-                * dir can end with a path separator when it's root
-                * directory. Return proper prefix in that case.
-                */
-               if (dir[-1] == '/')
-                       return cwd;
-               return NULL;
+               subdir++;
+               offset++;
        }
+
+       /* hel[p]/me vs hel[l]/yeah */
+       if (*dir && *subdir)
+               return -1;
+
+       if (!*subdir)
+               return !*dir ? offset : -1; /* same dir */
+
+       /* foo/[b]ar vs foo/[] */
+       if (is_dir_sep(dir[-1]))
+               return is_dir_sep(subdir[-1]) ? offset : -1;
+
+       /* foo[/]bar vs foo[] */
+       return is_dir_sep(*subdir) ? offset + 1 : -1;
 }
 
 int is_inside_dir(const char *dir)
 {
-       char buffer[PATH_MAX];
-       return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
+       char cwd[PATH_MAX];
+       if (!dir)
+               return 0;
+       if (!getcwd(cwd, sizeof(cwd)))
+               die_errno("can't find the current directory");
+       return dir_inside_of(cwd, dir) >= 0;
 }
 
 int is_empty_dir(const char *path)
@@ -1286,8 +1271,8 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
 
                item->match = path;
                item->len = strlen(path);
-               item->has_wildcard = !no_wildcard(path);
-               if (item->has_wildcard)
+               item->use_wildcard = !no_wildcard(path);
+               if (item->use_wildcard)
                        pathspec->has_wildcard = 1;
        }