parse packed refs in a single pass over packed-refs file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
diff --git a/lib/reference.c b/lib/reference.c
index 3a4f6f0..e9c070c 100644
--- a/lib/reference.c
+++ b/lib/reference.c
@@ -198,36 +198,40 @@ parse_packed_ref_line(struct got_reference **ref, const char *abs_refname,
}
static const struct got_error *
-open_packed_ref(struct got_reference **ref, FILE *f, const char *subdir,
- const char *refname)
+open_packed_ref(struct got_reference **ref, FILE *f, const char **subdirs,
+ int nsubdirs, const char *refname)
{
const struct got_error *err = NULL;
char *abs_refname;
char *line;
size_t len;
const char delim[3] = {'\0', '\0', '\0'};
+ int i, ref_is_absolute = (strncmp(refname, "refs/", 5) == 0);
- if (strncmp(refname, "refs/", 5) == 0) {
- abs_refname = strdup(refname);
- if (abs_refname == NULL)
- return got_error_from_errno();
- } else if (asprintf(&abs_refname, "refs/%s/%s", subdir, refname) == -1)
- return got_error_from_errno();
-
+ if (ref_is_absolute)
+ abs_refname = (char *)refname;
do {
line = fparseln(f, &len, NULL, delim, 0);
if (line == NULL) {
err = got_error(GOT_ERR_NOT_REF);
break;
}
-
- err = parse_packed_ref_line(ref, abs_refname, line);
+ for (i = 0; i < nsubdirs; i++) {
+ if (!ref_is_absolute &&
+ asprintf(&abs_refname, "refs/%s/%s", subdirs[i],
+ refname) == -1)
+ return got_error_from_errno();
+ err = parse_packed_ref_line(ref, abs_refname, line);
+ if (!ref_is_absolute)
+ free(abs_refname);
+ if (err)
+ break;
+ }
free(line);
if (err)
break;
} while (*ref == NULL);
- free(abs_refname);
return err;
}
@@ -277,16 +281,11 @@ got_ref_open(struct got_reference **ref, struct got_repository *repo,
f = fopen(packed_refs_path, "rb");
free(packed_refs_path);
if (f != NULL) {
- for (i = 0; i < nitems(subdirs); i++) {
- err = open_packed_ref(ref, f, subdirs[i],
- refname);
- if (err == NULL) {
- fclose(f);
- goto done;
- }
- rewind(f);
- }
+ err = open_packed_ref(ref, f, subdirs, nitems(subdirs),
+ refname);
fclose(f);
+ if (err == NULL)
+ goto done;
}
}