resolve_packed_ref(): rename function from resolve_missing_loose_ref()
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 256fef5da0fde1e3d9ab2dc81d22cad6d9db86cc..abccd7ebd775314280087789c65e6fb6eaa90878 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -9,6 +9,25 @@
 #include "object.h"
 #include "tag.h"
 
+/*
+ * List of all available backends
+ */
+static struct ref_storage_be *refs_backends = &refs_be_files;
+
+static struct ref_storage_be *find_ref_storage_backend(const char *name)
+{
+       struct ref_storage_be *be;
+       for (be = refs_backends; be; be = be->next)
+               if (!strcmp(be->name, name))
+                       return be;
+       return NULL;
+}
+
+int ref_storage_backend_exists(const char *name)
+{
+       return find_ref_storage_backend(name) != NULL;
+}
+
 /*
  * How to handle various characters in refnames:
  * 0: An acceptable character for refs
@@ -1132,8 +1151,12 @@ int head_ref(each_ref_fn fn, void *cb_data)
 static int do_for_each_ref(const char *submodule, const char *prefix,
                           each_ref_fn fn, int trim, int flags, void *cb_data)
 {
+       struct ref_store *refs = get_ref_store(submodule);
        struct ref_iterator *iter;
 
+       if (!refs)
+               return 0;
+
        iter = files_ref_iterator_begin(submodule, prefix, flags);
        iter = prefix_ref_iterator_begin(iter, prefix, trim);
 
@@ -1265,3 +1288,101 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
        errno = ELOOP;
        return NULL;
 }
+
+/* A pointer to the ref_store for the main repository: */
+static struct ref_store *main_ref_store;
+
+/* A linked list of ref_stores for submodules: */
+static struct ref_store *submodule_ref_stores;
+
+void base_ref_store_init(struct ref_store *refs,
+                        const struct ref_storage_be *be,
+                        const char *submodule)
+{
+       refs->be = be;
+       if (!submodule) {
+               if (main_ref_store)
+                       die("BUG: main_ref_store initialized twice");
+
+               refs->submodule = "";
+               refs->next = NULL;
+               main_ref_store = refs;
+       } else {
+               if (lookup_ref_store(submodule))
+                       die("BUG: ref_store for submodule '%s' initialized twice",
+                           submodule);
+
+               refs->submodule = xstrdup(submodule);
+               refs->next = submodule_ref_stores;
+               submodule_ref_stores = refs;
+       }
+}
+
+struct ref_store *ref_store_init(const char *submodule)
+{
+       const char *be_name = "files";
+       struct ref_storage_be *be = find_ref_storage_backend(be_name);
+
+       if (!be)
+               die("BUG: reference backend %s is unknown", be_name);
+
+       if (!submodule || !*submodule)
+               return be->init(NULL);
+       else
+               return be->init(submodule);
+}
+
+struct ref_store *lookup_ref_store(const char *submodule)
+{
+       struct ref_store *refs;
+
+       if (!submodule || !*submodule)
+               return main_ref_store;
+
+       for (refs = submodule_ref_stores; refs; refs = refs->next) {
+               if (!strcmp(submodule, refs->submodule))
+                       return refs;
+       }
+
+       return NULL;
+}
+
+struct ref_store *get_ref_store(const char *submodule)
+{
+       struct ref_store *refs;
+
+       if (!submodule || !*submodule) {
+               refs = lookup_ref_store(NULL);
+
+               if (!refs)
+                       refs = ref_store_init(NULL);
+       } else {
+               refs = lookup_ref_store(submodule);
+
+               if (!refs) {
+                       struct strbuf submodule_sb = STRBUF_INIT;
+
+                       strbuf_addstr(&submodule_sb, submodule);
+                       if (is_nonbare_repository_dir(&submodule_sb))
+                               refs = ref_store_init(submodule);
+                       strbuf_release(&submodule_sb);
+               }
+       }
+
+       return refs;
+}
+
+void assert_main_repository(struct ref_store *refs, const char *caller)
+{
+       if (*refs->submodule)
+               die("BUG: %s called for a submodule", caller);
+}
+
+/* backend functions */
+int ref_transaction_commit(struct ref_transaction *transaction,
+                          struct strbuf *err)
+{
+       struct ref_store *refs = get_ref_store(NULL);
+
+       return refs->be->transaction_commit(refs, transaction, err);
+}