From: Linus Torvalds Date: Sun, 3 Jul 2005 17:01:38 +0000 (-0700) Subject: Fix up "for_each_ref()" to be more usable, and use it in git-fsck-cache X-Git-Tag: v0.99~97 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=944d858969e4e14adefdd8f21fac5c8ab45f83f7;p=git.git Fix up "for_each_ref()" to be more usable, and use it in git-fsck-cache It needed to take the GIT_DIR information into account, something that the original receive-pack usage just never cared about. --- diff --git a/fsck-cache.c b/fsck-cache.c index 44ad5f16..9867fa65 100644 --- a/fsck-cache.c +++ b/fsck-cache.c @@ -6,6 +6,7 @@ #include "tree.h" #include "blob.h" #include "tag.h" +#include "refs.h" #include "pack.h" #define REACHABLE 0x0001 @@ -303,76 +304,30 @@ static int fsck_dir(int i, char *path) return 0; } -static int read_sha1_reference(const char *path) +static int default_refs = 0; + +static int fsck_handle_ref(const char *refname, const unsigned char *sha1) { - char hexname[60]; - unsigned char sha1[20]; - int fd = open(path, O_RDONLY), len; struct object *obj; - if (fd < 0) - return -1; - - len = read(fd, hexname, sizeof(hexname)); - close(fd); - if (len < 40) - return -1; - - if (get_sha1_hex(hexname, sha1) < 0) - return -1; - obj = lookup_object(sha1); if (!obj) { if (!standalone && has_sha1_file(sha1)) - return 0; /* it is in pack */ - return error("%s: invalid sha1 pointer %.40s", path, hexname); + return 0; /* it is in a pack */ + error("%s: invalid sha1 pointer %s", refname, sha1_to_hex(sha1)); + /* We'll continue with the rest despite the error.. */ + return 0; } - + default_refs++; obj->used = 1; mark_reachable(obj, REACHABLE); return 0; } -static int find_file_objects(const char *base, const char *name) -{ - int baselen = strlen(base); - int namelen = strlen(name); - char *path = xmalloc(baselen + namelen + 2); - struct stat st; - - memcpy(path, base, baselen); - path[baselen] = '/'; - memcpy(path + baselen + 1, name, namelen+1); - if (stat(path, &st) < 0) - return 0; - - /* - * Recurse into directories - */ - if (S_ISDIR(st.st_mode)) { - int count = 0; - DIR *dir = opendir(path); - if (dir) { - struct dirent *de; - while ((de = readdir(dir)) != NULL) { - if (de->d_name[0] == '.') - continue; - count += find_file_objects(path, de->d_name); - } - closedir(dir); - } - return count; - } - if (S_ISREG(st.st_mode)) - return read_sha1_reference(path) == 0; - return 0; -} - static void get_default_heads(void) { - char *git_dir = gitenv(GIT_DIR_ENVIRONMENT) ? : DEFAULT_GIT_DIR_ENVIRONMENT; - int count = find_file_objects(git_dir, "refs"); - if (!count) + for_each_ref(fsck_handle_ref); + if (!default_refs) die("No default references"); } diff --git a/receive-pack.c b/receive-pack.c index 53d00a5e..d05f7d5e 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -7,7 +7,7 @@ static const char receive_pack_usage[] = "git-receive-pack "; static const char *unpacker = "git-unpack-objects"; -static int show_ref(const char *path, unsigned char *sha1) +static int show_ref(const char *path, const unsigned char *sha1) { packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); return 0; diff --git a/refs.c b/refs.c index 0a99dd14..447080ed 100644 --- a/refs.c +++ b/refs.c @@ -17,7 +17,7 @@ static int read_ref(const char *path, unsigned char *sha1) return ret; } -static int do_for_each_ref(const char *base, int (*fn)(const char *path, unsigned char *sha1)) +static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1)) { int retval = 0; DIR *dir = opendir(base); @@ -27,6 +27,8 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, unsigne int baselen = strlen(base); char *path = xmalloc(baselen + 257); memcpy(path, base, baselen); + if (baselen && base[baselen-1] != '/') + path[baselen++] = '/'; while ((de = readdir(dir)) != NULL) { unsigned char sha1[20]; @@ -42,8 +44,6 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, unsigne if (lstat(path, &st) < 0) continue; if (S_ISDIR(st.st_mode)) { - path[baselen + namelen] = '/'; - path[baselen + namelen + 1] = 0; retval = do_for_each_ref(path, fn); if (retval) break; @@ -63,9 +63,9 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, unsigne return retval; } -int for_each_ref(int (*fn)(const char *path, unsigned char *sha1)) +int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1)) { - return do_for_each_ref("refs/", fn); + return do_for_each_ref(get_refs_directory(), fn); } static char *ref_file_name(const char *ref) diff --git a/refs.h b/refs.h index 7565decb..a79cb13c 100644 --- a/refs.h +++ b/refs.h @@ -5,7 +5,7 @@ * Calls the specified function for each ref file until it returns nonzero, * and returns the value */ -extern int for_each_ref(int (*fn)(const char *path, unsigned char *sha1)); +extern int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1)); /** Reads the refs file specified into sha1 **/ extern int get_ref_sha1(const char *ref, unsigned char *sha1);