X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=refs.c;h=6ca04d3b0fb4b9c40e816820309fd879ffc1d40b;hb=f03f2ba0a558c6fbfcf40ca24da55a8e9d602e46;hp=9973d1fc21e9d14f4cf1d30cb59f55cdfd7fc1e7;hpb=85c1f337be49eaa9a22e42a1c9958deef5ab57c3;p=git.git diff --git a/refs.c b/refs.c index 9973d1fc..6ca04d3b 100644 --- a/refs.c +++ b/refs.c @@ -3,6 +3,85 @@ #include +static int read_ref(const char *path, unsigned char *sha1) +{ + int ret = -1; + int fd = open(path, 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(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 (lstat(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]; + const char *headpath = git_path("HEAD"); + if (!read_ref(headpath, sha1)) + fn(headpath, sha1); + return do_for_each_ref(get_refs_directory(), fn); +} + +int for_each_ref(int (*fn)(const char *path, const unsigned char *sha1)) +{ + return do_for_each_ref(get_refs_directory(), fn); +} + static char *ref_file_name(const char *ref) { char *base = get_refs_directory();