X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=refs.c;h=161018097def05f717ae20e59e3df6cc1b01ab77;hb=b893f09104ee5f1d8710dfe17cdf1cbac995f17a;hp=9973d1fc21e9d14f4cf1d30cb59f55cdfd7fc1e7;hpb=95fc75129acf14d980bdd56b9b2ee74190f81d91;p=git.git diff --git a/refs.c b/refs.c index 9973d1fc..16101809 100644 --- a/refs.c +++ b/refs.c @@ -3,6 +3,84 @@ #include +static int read_ref(const char *refname, unsigned char *sha1) +{ + int ret = -1; + int fd = open(git_path("%s", refname), O_RDONLY); + + if (fd >= 0) { + char buffer[60]; + if (read(fd, buffer, sizeof(buffer)) >= 40) + ret = get_sha1_hex(buffer, sha1); + close(fd); + } + return ret; +} + +static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1)) +{ + int retval = 0; + DIR *dir = opendir(git_path("%s", base)); + + if (dir) { + struct dirent *de; + int baselen = strlen(base); + char *path = xmalloc(baselen + 257); + + if (!strncmp(base, "./", 2)) { + base += 2; + baselen -= 2; + } + memcpy(path, base, baselen); + if (baselen && base[baselen-1] != '/') + path[baselen++] = '/'; + + while ((de = readdir(dir)) != NULL) { + unsigned char sha1[20]; + struct stat st; + int namelen; + + if (de->d_name[0] == '.') + continue; + namelen = strlen(de->d_name); + if (namelen > 255) + continue; + memcpy(path + baselen, de->d_name, namelen+1); + if (stat(git_path("%s", path), &st) < 0) + continue; + if (S_ISDIR(st.st_mode)) { + retval = do_for_each_ref(path, fn); + if (retval) + break; + continue; + } + if (read_ref(path, sha1) < 0) + continue; + if (!has_sha1_file(sha1)) + continue; + retval = fn(path, sha1); + if (retval) + break; + } + free(path); + closedir(dir); + } + return retval; +} + +int head_ref(int (*fn)(const char *path, const unsigned char *sha1)) +{ + unsigned char sha1[20]; + if (!read_ref("HEAD", sha1)) + return fn("HEAD", sha1); + return 0; +} + +int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1)) +{ + return do_for_each_ref("refs", fn); +} + static char *ref_file_name(const char *ref) { char *base = get_refs_directory();