files-backend at this point is still aware of the per-repo/worktree
separation in refs, so it can handle a linked worktree.

Some refs operations are known not working when current files-backend is
used in a linked worktree (e.g. reflog). Tests will be written when
refs_* functions start to be called with worktree backend to verify that
they work as expected.

Note: accessing a worktree of a submodule remains unaddressed. Perhaps
after get_worktrees() can access submodule (or rather a new function
get_submodule_worktrees(), that lists worktrees of a submodule), we can
update this function to work with submodules as well.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 refs.c | 31 +++++++++++++++++++++++++++++++
 refs.h |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/refs.c b/refs.c
index 875e30a0b8..a4083caf6a 100644
--- a/refs.c
+++ b/refs.c
@@ -10,6 +10,7 @@
 #include "object.h"
 #include "tag.h"
 #include "submodule.h"
+#include "worktree.h"
 
 /*
  * List of all available backends
@@ -1486,6 +1487,9 @@ static struct ref_store *main_ref_store;
 /* A hashmap of ref_stores, stored by submodule name: */
 static struct hashmap submodule_ref_stores;
 
+/* A hashmap of ref_stores, stored by worktree id: */
+static struct hashmap worktree_ref_stores;
+
 /*
  * Look up a ref store by name. If that ref_store hasn't been
  * registered yet, return NULL.
@@ -1590,6 +1594,33 @@ struct ref_store *get_submodule_ref_store(const char 
*submodule)
        return refs;
 }
 
+struct ref_store *get_worktree_ref_store(const struct worktree *wt)
+{
+       struct ref_store *refs;
+       unsigned int refs_all_capabilities =
+               REF_STORE_READ | REF_STORE_WRITE |
+               REF_STORE_ODB | REF_STORE_MAIN;
+
+       if (wt->is_current)
+               return get_main_ref_store();
+
+       refs = lookup_ref_store_map(&worktree_ref_stores, wt->id);
+       if (refs)
+               return refs;
+
+       if (wt->id)
+               refs = ref_store_init(git_common_path("worktrees/%s", wt->id),
+                                     refs_all_capabilities);
+       else
+               refs = ref_store_init(get_git_common_dir(),
+                                     refs_all_capabilities);
+
+       if (refs)
+               register_ref_store_map(&worktree_ref_stores, "worktree",
+                                      refs, wt->id);
+       return refs;
+}
+
 void base_ref_store_init(struct ref_store *refs,
                         const struct ref_storage_be *be)
 {
diff --git a/refs.h b/refs.h
index 49e97d7d5f..6df69a2adb 100644
--- a/refs.h
+++ b/refs.h
@@ -5,6 +5,7 @@ struct object_id;
 struct ref_store;
 struct strbuf;
 struct string_list;
+struct worktree;
 
 /*
  * Resolve a reference, recursively following symbolic refererences.
@@ -655,5 +656,6 @@ struct ref_store *get_main_ref_store(void);
  * submodule==NULL.
  */
 struct ref_store *get_submodule_ref_store(const char *submodule);
+struct ref_store *get_worktree_ref_store(const struct worktree *wt);
 
 #endif /* REFS_H */
-- 
2.11.0.157.gd943d85

Reply via email to