summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-07-03 03:23:36 (GMT)
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-03 03:23:36 (GMT)
commit8a65ff7666db1299449a397bab3d39d74b82aa54 (patch)
treeb0f9407b07ab00a4de734f39affaf3805c54c27e /refs.c
parentad8c80a58f7bf8f7d5d34794355e5540cd7b3218 (diff)
downloadgit-8a65ff7666db1299449a397bab3d39d74b82aa54.zip
git-8a65ff7666db1299449a397bab3d39d74b82aa54.tar.gz
git-8a65ff7666db1299449a397bab3d39d74b82aa54.tar.bz2
Generalize the "show each ref" code in receice-pack
This turns it into a generic "do xyz for each ref" library function.
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/refs.c b/refs.c
index 9973d1f..0a99dd1 100644
--- a/refs.c
+++ b/refs.c
@@ -3,6 +3,71 @@
#include <errno.h>
+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, unsigned char *sha1))
+{
+ int retval = 0;
+ DIR *dir = opendir(base);
+
+ if (dir) {
+ struct dirent *de;
+ int baselen = strlen(base);
+ char *path = xmalloc(baselen + 257);
+ memcpy(path, base, 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)) {
+ path[baselen + namelen] = '/';
+ path[baselen + namelen + 1] = 0;
+ 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 for_each_ref(int (*fn)(const char *path, unsigned char *sha1))
+{
+ return do_for_each_ref("refs/", fn);
+}
+
static char *ref_file_name(const char *ref)
{
char *base = get_refs_directory();