get_ref_dir(): change signature
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 197579205bf8dcc2dc2c1950ef27c7385a50697a..91ec3954b78d59000cad99fdeea2761d1f0831b4 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -53,6 +53,7 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
        return line;
 }
 
+/* Add a ref_entry to the end of the ref_array (unsorted). */
 static void add_ref(const char *refname, const unsigned char *sha1,
                    int flag, int check_name, struct ref_array *refs,
                    struct ref_entry **new_entry)
@@ -83,9 +84,28 @@ static int ref_entry_cmp(const void *a, const void *b)
        return strcmp(one->name, two->name);
 }
 
+/*
+ * Emit a warning and return true iff ref1 and ref2 have the same name
+ * and the same sha1.  Die if they have the same name but different
+ * sha1s.
+ */
+static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2)
+{
+       if (!strcmp(ref1->name, ref2->name)) {
+               /* Duplicate name; make sure that the SHA1s match: */
+               if (hashcmp(ref1->sha1, ref2->sha1))
+                       die("Duplicated ref, and SHA1s don't match: %s",
+                           ref1->name);
+               warning("Duplicated ref: %s", ref1->name);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 static void sort_ref_array(struct ref_array *array)
 {
-       int i = 0, j = 1;
+       int i, j;
 
        /* Nothing to sort unless there are at least two entries */
        if (array->nr < 2)
@@ -94,19 +114,13 @@ static void sort_ref_array(struct ref_array *array)
        qsort(array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
 
        /* Remove any duplicates from the ref_array */
-       for (; j < array->nr; j++) {
-               struct ref_entry *a = array->refs[i];
-               struct ref_entry *b = array->refs[j];
-               if (!strcmp(a->name, b->name)) {
-                       if (hashcmp(a->sha1, b->sha1))
-                               die("Duplicated ref, and SHA1s don't match: %s",
-                                   a->name);
-                       warning("Duplicated ref: %s", a->name);
-                       free(b);
+       i = 0;
+       for (j = 1; j < array->nr; j++) {
+               if (is_dup_ref(array->refs[i], array->refs[j])) {
+                       free(array->refs[j]);
                        continue;
                }
-               i++;
-               array->refs[i] = array->refs[j];
+               array->refs[++i] = array->refs[j];
        }
        array->nr = i + 1;
 }
@@ -264,16 +278,14 @@ void clear_extra_refs(void)
        clear_ref_array(&extra_refs);
 }
 
-static struct ref_array *get_packed_refs(const char *submodule)
+static struct ref_array *get_packed_refs(struct ref_cache *refs)
 {
-       struct ref_cache *refs = get_ref_cache(submodule);
-
        if (!refs->did_packed) {
                const char *packed_refs_file;
                FILE *f;
 
-               if (submodule)
-                       packed_refs_file = git_path_submodule(submodule, "packed-refs");
+               if (*refs->name)
+                       packed_refs_file = git_path_submodule(refs->name, "packed-refs");
                else
                        packed_refs_file = git_path("packed-refs");
                f = fopen(packed_refs_file, "r");
@@ -286,14 +298,14 @@ static struct ref_array *get_packed_refs(const char *submodule)
        return &refs->packed;
 }
 
-static void get_ref_dir(const char *submodule, const char *base,
+static void get_ref_dir(struct ref_cache *refs, const char *base,
                        struct ref_array *array)
 {
        DIR *dir;
        const char *path;
 
-       if (submodule)
-               path = git_path_submodule(submodule, "%s", base);
+       if (*refs->name)
+               path = git_path_submodule(refs->name, "%s", base);
        else
                path = git_path("%s", base);
 
@@ -324,19 +336,19 @@ static void get_ref_dir(const char *submodule, const char *base,
                        if (has_extension(de->d_name, ".lock"))
                                continue;
                        memcpy(refname + baselen, de->d_name, namelen+1);
-                       refdir = submodule
-                               ? git_path_submodule(submodule, "%s", refname)
+                       refdir = *refs->name
+                               ? git_path_submodule(refs->name, "%s", refname)
                                : git_path("%s", refname);
                        if (stat(refdir, &st) < 0)
                                continue;
                        if (S_ISDIR(st.st_mode)) {
-                               get_ref_dir(submodule, refname, array);
+                               get_ref_dir(refs, refname, array);
                                continue;
                        }
-                       if (submodule) {
+                       if (*refs->name) {
                                hashclr(sha1);
                                flag = 0;
-                               if (resolve_gitlink_ref(submodule, refname, sha1) < 0) {
+                               if (resolve_gitlink_ref(refs->name, refname, sha1) < 0) {
                                        hashclr(sha1);
                                        flag |= REF_ISBROKEN;
                                }
@@ -385,12 +397,10 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
        for_each_rawref(warn_if_dangling_symref, &data);
 }
 
-static struct ref_array *get_loose_refs(const char *submodule)
+static struct ref_array *get_loose_refs(struct ref_cache *refs)
 {
-       struct ref_cache *refs = get_ref_cache(submodule);
-
        if (!refs->did_loose) {
-               get_ref_dir(submodule, "refs", &refs->loose);
+               get_ref_dir(refs, "refs", &refs->loose);
                sort_ref_array(&refs->loose);
                refs->did_loose = 1;
        }
@@ -417,7 +427,7 @@ static int resolve_gitlink_packed_ref(char *name, int pathlen,
        if (pathlen < 6 || memcmp(name + pathlen - 6, "/.git/", 6))
                die("Oops");
        name[pathlen - 6] = '\0'; /* make it path to the submodule */
-       array = get_packed_refs(name);
+       array = get_packed_refs(get_ref_cache(name));
        ref = search_ref_array(array, refname);
        if (ref != NULL) {
                memcpy(sha1, ref->sha1, 20);
@@ -497,7 +507,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
  */
 static int get_packed_ref(const char *refname, unsigned char *sha1)
 {
-       struct ref_array *packed = get_packed_refs(NULL);
+       struct ref_array *packed = get_packed_refs(get_ref_cache(NULL));
        struct ref_entry *entry = search_ref_array(packed, refname);
        if (entry) {
                hashcpy(sha1, entry->sha1);
@@ -681,7 +691,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
                return -1;
 
        if ((flag & REF_ISPACKED)) {
-               struct ref_array *array = get_packed_refs(NULL);
+               struct ref_array *array = get_packed_refs(get_ref_cache(NULL));
                struct ref_entry *r = search_ref_array(array, refname);
 
                if (r != NULL && r->flag & REF_KNOWS_PEELED) {
@@ -706,8 +716,9 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
                           int trim, int flags, void *cb_data)
 {
        int retval = 0, i, p = 0, l = 0;
-       struct ref_array *packed = get_packed_refs(submodule);
-       struct ref_array *loose = get_loose_refs(submodule);
+       struct ref_cache *refs = get_ref_cache(submodule);
+       struct ref_array *packed = get_packed_refs(refs);
+       struct ref_array *loose = get_loose_refs(refs);
 
        struct ref_array *extra = &extra_refs;
 
@@ -1224,7 +1235,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
         * name is a proper prefix of our refname.
         */
        if (missing &&
-            !is_refname_available(refname, NULL, get_packed_refs(NULL))) {
+            !is_refname_available(refname, NULL, get_packed_refs(get_ref_cache(NULL)))) {
                last_errno = ENOTDIR;
                goto error_return;
        }
@@ -1284,7 +1295,7 @@ static int repack_without_ref(const char *refname)
        struct ref_entry *ref;
        int fd, i;
 
-       packed = get_packed_refs(NULL);
+       packed = get_packed_refs(get_ref_cache(NULL));
        ref = search_ref_array(packed, refname);
        if (ref == NULL)
                return 0;
@@ -1367,6 +1378,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
        struct stat loginfo;
        int log = !lstat(git_path("logs/%s", oldrefname), &loginfo);
        const char *symref = NULL;
+       struct ref_cache *refs = get_ref_cache(NULL);
 
        if (log && S_ISLNK(loginfo.st_mode))
                return error("reflog for %s is a symlink", oldrefname);
@@ -1378,10 +1390,10 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
        if (!symref)
                return error("refname %s not found", oldrefname);
 
-       if (!is_refname_available(newrefname, oldrefname, get_packed_refs(NULL)))
+       if (!is_refname_available(newrefname, oldrefname, get_packed_refs(refs)))
                return 1;
 
-       if (!is_refname_available(newrefname, oldrefname, get_loose_refs(NULL)))
+       if (!is_refname_available(newrefname, oldrefname, get_loose_refs(refs)))
                return 1;
 
        if (log && rename(git_path("logs/%s", oldrefname), git_path(TMP_RENAMED_LOG)))