/* * Handle a path that was a directory. Four cases: * * - it's already a gitlink in the index, and we keep it that * way, and update it if we can (if we cannot find the HEAD, * we're going to keep it unchanged in the index!) * * - it's a *file* in the index, in which case it should be * removed as a file if removal is allowed, since it doesn't * exist as such any more. If removal isn't allowed, it's * an error. * * (NOTE! This is old and arguably fairly strange behaviour. * We might want to make this an error unconditionally, and * use "--force-remove" if you actually want to force removal). * * - it used to exist as a subdirectory (ie multiple files with * this particular prefix) in the index, in which case it's wrong * to try to update it as a directory. * * - it doesn't exist at all in the index, but it is a valid * git directory, and it should be *added* as a gitlink. */ static int process_directory(const char *path, int len, struct stat *st) { unsigned char sha1[20]; int pos = cache_name_pos(path, len); /* Exact match: file or existing gitlink */ if (pos >= 0) { const struct cache_entry *ce = active_cache[pos]; if (S_ISGITLINK(ce->ce_mode)) { /* Do nothing to the index if there is no HEAD! */ if (resolve_gitlink_ref(path, "HEAD", sha1) < 0) return 0; return add_one_path(ce, path, len, st); } /* Should this be an unconditional error? */ return remove_one_path(path); } /* Inexact match: is there perhaps a subdirectory match? */ pos = -pos-1; while (pos < active_nr) { const struct cache_entry *ce = active_cache[pos++]; if (strncmp(ce->name, path, len)) break; if (ce->name[len] > '/') break; if (ce->name[len] < '/') continue; /* Subdirectory match - error out */ return error("%s: is a directory - add individual files instead", path); } /* No match - should we add it as a gitlink? */ if (!resolve_gitlink_ref(path, "HEAD", sha1)) return add_one_path(NULL, path, len, st); /* Error out. */ return error("%s: is a directory - add files inside instead", path); }
/* * Handle a path that couldn't be lstat'ed. It's either: * - missing file (ENOENT or ENOTDIR). That's ok if we're * supposed to be removing it and the removal actually * succeeds. * - permission error. That's never ok. */ static int process_lstat_error(const char *path, int err) { if (err == ENOENT || err == ENOTDIR) return remove_one_path(path); return error("lstat(\"%s\"): %s", path, strerror(errno)); }
/* * Handle a path that couldn't be lstat'ed. It's either: * - missing file (ENOENT or ENOTDIR). That's ok if we're * supposed to be removing it and the removal actually * succeeds. * - permission error. That's never ok. */ static int process_lstat_error(const char *path, int err) { if (is_missing_file_error(err)) return remove_one_path(path); return error("lstat(\"%s\"): %s", path, strerror(err)); }