get_loose_ref_cache(): new function
[gitweb.git] / refs / ref-cache.c
index 4274a43a9bb03917c6e08fc98b72de1c3ee7e111..38d4c31985f05b64eea854e948ea8ca9299832af 100644 (file)
@@ -4,9 +4,6 @@
 #include "ref-cache.h"
 #include "../iterator.h"
 
-/* FIXME: This declaration shouldn't be here */
-void read_loose_refs(const char *dirname, struct ref_dir *dir);
-
 void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
 {
        ALLOC_GROW(dir->entries, dir->nr + 1, dir->alloc);
@@ -25,23 +22,10 @@ struct ref_dir *get_ref_dir(struct ref_entry *entry)
        assert(entry->flag & REF_DIR);
        dir = &entry->u.subdir;
        if (entry->flag & REF_INCOMPLETE) {
-               read_loose_refs(entry->name, dir);
+               if (!dir->cache->fill_ref_dir)
+                       die("BUG: incomplete ref_store without fill_ref_dir function");
 
-               /*
-                * Manually add refs/bisect, which, being
-                * per-worktree, might not appear in the directory
-                * listing for refs/ in the main repo.
-                */
-               if (!strcmp(entry->name, "refs/")) {
-                       int pos = search_ref_dir(dir, "refs/bisect/", 12);
-                       if (pos < 0) {
-                               struct ref_entry *child_entry;
-                               child_entry = create_dir_entry(dir->ref_store,
-                                                              "refs/bisect/",
-                                                              12, 1);
-                               add_entry_to_dir(dir, child_entry);
-                       }
-               }
+               dir->cache->fill_ref_dir(dir->cache->ref_store, dir, entry->name);
                entry->flag &= ~REF_INCOMPLETE;
        }
        return dir;
@@ -63,9 +47,20 @@ struct ref_entry *create_ref_entry(const char *refname,
        return ref;
 }
 
+struct ref_cache *create_ref_cache(struct ref_store *refs,
+                                  fill_ref_dir_fn *fill_ref_dir)
+{
+       struct ref_cache *ret = xcalloc(1, sizeof(*ret));
+
+       ret->ref_store = refs;
+       ret->fill_ref_dir = fill_ref_dir;
+       ret->root = create_dir_entry(ret, "", 0, 1);
+       return ret;
+}
+
 static void clear_ref_dir(struct ref_dir *dir);
 
-void free_ref_entry(struct ref_entry *entry)
+static void free_ref_entry(struct ref_entry *entry)
 {
        if (entry->flag & REF_DIR) {
                /*
@@ -77,6 +72,12 @@ void free_ref_entry(struct ref_entry *entry)
        free(entry);
 }
 
+void free_ref_cache(struct ref_cache *cache)
+{
+       free_ref_entry(cache->root);
+       free(cache);
+}
+
 /*
  * Clear and free all entries in dir, recursively.
  */
@@ -90,13 +91,14 @@ static void clear_ref_dir(struct ref_dir *dir)
        dir->entries = NULL;
 }
 
-struct ref_entry *create_dir_entry(struct files_ref_store *ref_store,
+struct ref_entry *create_dir_entry(struct ref_cache *cache,
                                   const char *dirname, size_t len,
                                   int incomplete)
 {
        struct ref_entry *direntry;
+
        FLEX_ALLOC_MEM(direntry, name, dirname, len);
-       direntry->u.subdir.ref_store = ref_store;
+       direntry->u.subdir.cache = cache;
        direntry->flag = REF_DIR | (incomplete ? REF_INCOMPLETE : 0);
        return direntry;
 }
@@ -167,7 +169,7 @@ static struct ref_dir *search_for_subdir(struct ref_dir *dir,
                 * therefore, create an empty record for it but mark
                 * the record complete.
                 */
-               entry = create_dir_entry(dir->ref_store, subdirname, len, 0);
+               entry = create_dir_entry(dir->cache, subdirname, len, 0);
                add_entry_to_dir(dir, entry);
        } else {
                entry = dir->entries[entry_index];
@@ -305,18 +307,18 @@ static void sort_ref_dir(struct ref_dir *dir)
        dir->sorted = dir->nr = i;
 }
 
-int do_for_each_entry_in_dir(struct ref_dir *dir, int offset,
+int do_for_each_entry_in_dir(struct ref_dir *dir,
                             each_ref_entry_fn fn, void *cb_data)
 {
        int i;
        assert(dir->sorted == dir->nr);
-       for (i = offset; i < dir->nr; i++) {
+       for (i = 0; i < dir->nr; i++) {
                struct ref_entry *entry = dir->entries[i];
                int retval;
                if (entry->flag & REF_DIR) {
                        struct ref_dir *subdir = get_ref_dir(entry);
                        sort_ref_dir(subdir);
-                       retval = do_for_each_entry_in_dir(subdir, 0, fn, cb_data);
+                       retval = do_for_each_entry_in_dir(subdir, fn, cb_data);
                } else {
                        retval = fn(entry, cb_data);
                }