/* * Has the work tree entity been removed? * * Return 1 if it was removed from the work tree, 0 if an entity to be * compared with the cache entry ce still exists (the latter includes * the case where a directory that is not a submodule repository * exists for ce that is a submodule -- it is a submodule that is not * checked out). Return negative for an error. */ static int check_removed(const struct cache_entry *ce, struct stat *st) { if (lstat(ce->name, st) < 0) { if (!is_missing_file_error(errno)) return -1; return 1; } if (has_symlink_leading_path(ce->name, ce_namelen(ce))) return 1; if (S_ISDIR(st->st_mode)) { struct object_id sub; /* * If ce is already a gitlink, we can have a plain * directory (i.e. the submodule is not checked out), * or a checked out submodule. Either case this is not * a case where something was removed from the work tree, * so we will return 0. * * Otherwise, if the directory is not a submodule * repository, that means ce which was a blob turned into * a directory --- the blob was removed! */ if (!S_ISGITLINK(ce->ce_mode) && resolve_gitlink_ref(ce->name, "HEAD", &sub)) return 1; } return 0; }
static int process_path(const char *path, struct stat *st, int stat_errno) { int pos, len; const struct cache_entry *ce; len = strlen(path); if (has_symlink_leading_path(path, len)) return error("'%s' is beyond a symbolic link", path); pos = cache_name_pos(path, len); ce = pos < 0 ? NULL : active_cache[pos]; if (ce && ce_skip_worktree(ce)) { /* * working directory version is assumed "good" * so updating it does not make sense. * On the other hand, removing it from index should work */ if (allow_remove && remove_file_from_cache(path)) return error("%s: cannot remove from the index", path); return 0; } /* * First things first: get the stat information, to decide * what to do about the pathname! */ if (stat_errno) return process_lstat_error(path, stat_errno); if (S_ISDIR(st->st_mode)) return process_directory(path, len, st); return add_one_path(ce, path, len, st); }
int read_directory(struct dir_struct *dir, const char *path, int len, const struct pathspec *pathspec) { struct path_simplify *simplify; /* * Check out create_simplify() */ if (pathspec) GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH | PATHSPEC_LITERAL | PATHSPEC_GLOB | PATHSPEC_ICASE); if (has_symlink_leading_path(path, len)) return dir->nr; simplify = create_simplify(pathspec ? pathspec->_raw : NULL); if (!len || treat_leading_path(dir, path, len, simplify)) read_directory_recursive(dir, path, len, 0, simplify); free_simplify(simplify); qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name); qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name); return dir->nr; }
int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec) { struct path_simplify *simplify; if (has_symlink_leading_path(path, strlen(path))) return dir->nr; simplify = create_simplify(pathspec); read_directory_recursive(dir, path, base, baselen, 0, simplify); free_simplify(simplify); qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name); qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name); return dir->nr; }
static int process_path(const char *path) { int len; struct stat st; len = strlen(path); if (has_symlink_leading_path(len, path)) return error("'%s' is beyond a symbolic link", path); /* * First things first: get the stat information, to decide * what to do about the pathname! */ if (lstat(path, &st) < 0) return process_lstat_error(path, errno); if (S_ISDIR(st.st_mode)) return process_directory(path, len, &st); return process_file(path, len, &st); }
/* * Given command line arguments and a prefix, convert the input to * pathspec. die() if any magic in magic_mask is used. */ void parse_pathspec(struct pathspec *pathspec, unsigned magic_mask, unsigned flags, const char *prefix, const char **argv) { struct pathspec_item *item; const char *entry = argv ? *argv : NULL; int i, n, prefixlen; memset(pathspec, 0, sizeof(*pathspec)); if (flags & PATHSPEC_MAXDEPTH_VALID) pathspec->magic |= PATHSPEC_MAXDEPTH; /* No arguments, no prefix -> no pathspec */ if (!entry && !prefix) return; if ((flags & PATHSPEC_PREFER_CWD) && (flags & PATHSPEC_PREFER_FULL)) die("BUG: PATHSPEC_PREFER_CWD and PATHSPEC_PREFER_FULL are incompatible"); /* No arguments with prefix -> prefix pathspec */ if (!entry) { static const char *raw[2]; if (flags & PATHSPEC_PREFER_FULL) return; if (!(flags & PATHSPEC_PREFER_CWD)) die("BUG: PATHSPEC_PREFER_CWD requires arguments"); pathspec->items = item = xmalloc(sizeof(*item)); memset(item, 0, sizeof(*item)); item->match = prefix; item->original = prefix; item->nowildcard_len = item->len = strlen(prefix); item->prefix = item->len; raw[0] = prefix; raw[1] = NULL; pathspec->nr = 1; pathspec->_raw = raw; return; } n = 0; while (argv[n]) n++; pathspec->nr = n; pathspec->items = item = xmalloc(sizeof(*item) * n); pathspec->_raw = argv; prefixlen = prefix ? strlen(prefix) : 0; for (i = 0; i < n; i++) { unsigned short_magic; entry = argv[i]; item[i].magic = prefix_pathspec(item + i, &short_magic, argv + i, flags, prefix, prefixlen, entry); if ((flags & PATHSPEC_LITERAL_PATH) && !(magic_mask & PATHSPEC_LITERAL)) item[i].magic |= PATHSPEC_LITERAL; if (item[i].magic & magic_mask) unsupported_magic(entry, item[i].magic & magic_mask, short_magic); if ((flags & PATHSPEC_SYMLINK_LEADING_PATH) && has_symlink_leading_path(item[i].match, item[i].len)) { die(_("pathspec '%s' is beyond a symbolic link"), entry); } if (item[i].nowildcard_len < item[i].len) pathspec->has_wildcard = 1; pathspec->magic |= item[i].magic; } if (pathspec->magic & PATHSPEC_MAXDEPTH) { if (flags & PATHSPEC_KEEP_ORDER) die("BUG: PATHSPEC_MAXDEPTH_VALID and PATHSPEC_KEEP_ORDER are incompatible"); qsort(pathspec->items, pathspec->nr, sizeof(struct pathspec_item), pathspec_item_cmp); } }