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; const char *cp; while (len && path[len - 1] == '/') len--; if (!len) return 1; baselen = 0; while (1) { cp = path + baselen + !!baselen; cp = memchr(cp, '/', path + len - cp); if (!cp) 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, DT_DIR, NULL) == path_ignored) return 0; /* do not recurse into it */ if (len <= baselen) return 1; /* finished checking */ } }
static enum path_treatment treat_path(struct dir_struct *dir, struct dirent *de, struct strbuf *path, int baselen, const struct path_simplify *simplify) { int dtype; if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git")) return path_none; strbuf_setlen(path, baselen); strbuf_addstr(path, de->d_name); if (simplify_away(path->buf, path->len, simplify)) return path_none; dtype = DTYPE(de); return treat_one_path(dir, path, simplify, dtype, de); }
static int treat_leading_path(struct dir_struct *dir, const char *path, int len, const struct path_simplify *simplify) { struct strbuf sb = STRBUF_INIT; int baselen, rc = 0; const char *cp; int old_flags = dir->flags; while (len && path[len - 1] == '/') len--; if (!len) return 1; baselen = 0; dir->flags &= ~DIR_SHOW_OTHER_DIRECTORIES; while (1) { cp = path + baselen + !!baselen; cp = memchr(cp, '/', path + len - cp); if (!cp) baselen = len; else baselen = cp - path; 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_none) break; /* do not recurse into it */ if (len <= baselen) { rc = 1; break; /* finished checking */ } } strbuf_release(&sb); dir->flags = old_flags; return rc; }
static enum path_treatment treat_path(struct dir_struct *dir, struct dirent *de, char *path, int path_max, int baselen, const struct path_simplify *simplify, int *len) { 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)) return path_ignored; dtype = DTYPE(de); return treat_one_path(dir, path, len, simplify, dtype, de); }
/* * Read a directory tree. We currently ignore anything but * directories, regular files and symlinks. That's because git * doesn't handle them at all yet. Maybe that will change some * day. * * Also, we ignore the name ".git" (even if it is not a directory). * That likely will not change. */ static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify) { DIR *fdir = opendir(path); int contents = 0; if (fdir) { struct dirent *de; char fullname[PATH_MAX + 1]; memcpy(fullname, base, baselen); while ((de = readdir(fdir)) != NULL) { int len, dtype; int exclude; if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git")) continue; len = strlen(de->d_name); /* Ignore overly long pathnames! */ if (len + baselen + 8 > sizeof(fullname)) continue; memcpy(fullname + baselen, de->d_name, len+1); if (simplify_away(fullname, baselen + len, simplify)) continue; dtype = DTYPE(de); exclude = excluded(dir, fullname, &dtype); if (exclude && (dir->flags & DIR_COLLECT_IGNORED) && in_pathspec(fullname, baselen + len, simplify)) dir_add_ignored(dir, fullname, baselen + len); /* * Excluded? If we don't explicitly want to show * ignored files, ignore it */ if (exclude && !(dir->flags & DIR_SHOW_IGNORED)) continue; if (dtype == DT_UNKNOWN) dtype = get_dtype(de, fullname); /* * Do we want to see just the ignored files? * We still need to recurse into directories, * even if we don't ignore them, since the * directory may contain files that we do.. */ if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) { if (dtype != DT_DIR) continue; } switch (dtype) { default: continue; case DT_DIR: memcpy(fullname + baselen + len, "/", 2); len++; switch (treat_directory(dir, fullname, baselen + len, simplify)) { case show_directory: if (exclude != !!(dir->flags & DIR_SHOW_IGNORED)) continue; break; case recurse_into_directory: contents += read_directory_recursive(dir, fullname, fullname, baselen + len, 0, simplify); continue; case ignore_directory: continue; } break; case DT_REG: case DT_LNK: break; } contents++; if (check_only) goto exit_early; else dir_add_name(dir, fullname, baselen + len); } exit_early: closedir(fdir); } return contents; }