Skip to content

Commit d74aacd

Browse files
KarthikNayakgitster
authored andcommitted
refs: receive and use the reference storage payload
An upcoming commit will add support for providing an URI via the 'extensions.refStorage' config. The URI will contain the reference backend and a corresponding payload. The payload can be then used for providing an alternate locations for the reference backend. To prepare for this, modify the existing backends to accept such an argument when initializing via the 'init()' function. Both the files and reftable backends will parse the information to be filesystem paths to store references. Given that no callers pass any payload yet this is essentially a no-op change for now. To enable this, provide a 'refs_compute_filesystem_location()' function which will parse the current 'gitdir' and the 'payload' to provide the final reference directory and common reference directory (if working in a linked worktree). The documentation and tests will be added alongside the extension of the config variable. Helped-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 2a32ac4 commit d74aacd

6 files changed

Lines changed: 85 additions & 16 deletions

File tree

refs.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define USE_THE_REPOSITORY_VARIABLE
66

77
#include "git-compat-util.h"
8+
#include "abspath.h"
89
#include "advice.h"
910
#include "config.h"
1011
#include "environment.h"
@@ -2290,7 +2291,7 @@ static struct ref_store *ref_store_init(struct repository *repo,
22902291
if (!be)
22912292
BUG("reference backend is unknown");
22922293

2293-
refs = be->init(repo, gitdir, flags);
2294+
refs = be->init(repo, NULL, gitdir, flags);
22942295
return refs;
22952296
}
22962297

@@ -3468,3 +3469,40 @@ const char *ref_transaction_error_msg(enum ref_transaction_error err)
34683469
return "unknown failure";
34693470
}
34703471
}
3472+
3473+
void refs_compute_filesystem_location(const char *gitdir, const char *payload,
3474+
bool *is_worktree, struct strbuf *refdir,
3475+
struct strbuf *ref_common_dir)
3476+
{
3477+
struct strbuf sb = STRBUF_INIT;
3478+
3479+
*is_worktree = get_common_dir_noenv(ref_common_dir, gitdir);
3480+
3481+
if (!payload) {
3482+
/*
3483+
* We can use the 'gitdir' as the 'refdir' without appending the
3484+
* worktree path, as the 'gitdir' here is already the worktree
3485+
* path and is different from 'commondir' denoted by 'ref_common_dir'.
3486+
*/
3487+
strbuf_addstr(refdir, gitdir);
3488+
return;
3489+
}
3490+
3491+
if (!is_absolute_path(payload)) {
3492+
strbuf_addf(&sb, "%s/%s", ref_common_dir->buf, payload);
3493+
strbuf_realpath(ref_common_dir, sb.buf, 1);
3494+
} else {
3495+
strbuf_realpath(ref_common_dir, payload, 1);
3496+
}
3497+
3498+
strbuf_addbuf(refdir, ref_common_dir);
3499+
3500+
if (*is_worktree) {
3501+
const char *wt_id = strrchr(gitdir, '/');
3502+
if (!wt_id)
3503+
BUG("worktree path does not contain slash");
3504+
strbuf_addf(refdir, "/worktrees/%s", wt_id + 1);
3505+
}
3506+
3507+
strbuf_release(&sb);
3508+
}

refs/files-backend.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,26 +106,33 @@ static void clear_loose_ref_cache(struct files_ref_store *refs)
106106
* set of caches.
107107
*/
108108
static struct ref_store *files_ref_store_init(struct repository *repo,
109+
const char *payload,
109110
const char *gitdir,
110111
unsigned int flags)
111112
{
112113
struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
113114
struct ref_store *ref_store = (struct ref_store *)refs;
114-
struct strbuf sb = STRBUF_INIT;
115+
struct strbuf ref_common_dir = STRBUF_INIT;
116+
struct strbuf refdir = STRBUF_INIT;
117+
bool is_worktree;
118+
119+
refs_compute_filesystem_location(gitdir, payload, &is_worktree, &refdir,
120+
&ref_common_dir);
115121

116-
base_ref_store_init(ref_store, repo, gitdir, &refs_be_files);
122+
base_ref_store_init(ref_store, repo, refdir.buf, &refs_be_files);
117123
refs->store_flags = flags;
118-
get_common_dir_noenv(&sb, gitdir);
119-
refs->gitcommondir = strbuf_detach(&sb, NULL);
124+
refs->gitcommondir = strbuf_detach(&ref_common_dir, NULL);
120125
refs->packed_ref_store =
121-
packed_ref_store_init(repo, refs->gitcommondir, flags);
126+
packed_ref_store_init(repo, NULL, refs->gitcommondir, flags);
122127
refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
123128
repo_config_get_bool(repo, "core.prefersymlinkrefs", &refs->prefer_symlink_refs);
124129

125130
chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
126131
chdir_notify_reparent("files-backend $GIT_COMMONDIR",
127132
&refs->gitcommondir);
128133

134+
strbuf_release(&refdir);
135+
129136
return ref_store;
130137
}
131138

refs/packed-backend.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,12 @@ static size_t snapshot_hexsz(const struct snapshot *snapshot)
211211
return snapshot->refs->base.repo->hash_algo->hexsz;
212212
}
213213

214+
/*
215+
* Since packed-refs is only stored in the common dir, don't parse the
216+
* payload and rely on the files-backend to set 'gitdir' correctly.
217+
*/
214218
struct ref_store *packed_ref_store_init(struct repository *repo,
219+
const char *payload UNUSED,
215220
const char *gitdir,
216221
unsigned int store_flags)
217222
{

refs/packed-backend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct ref_transaction;
1414
*/
1515

1616
struct ref_store *packed_ref_store_init(struct repository *repo,
17+
const char *payload,
1718
const char *gitdir,
1819
unsigned int store_flags);
1920

refs/refs-internal.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ struct ref_store;
389389
* the ref_store and to record the ref_store for later lookup.
390390
*/
391391
typedef struct ref_store *ref_store_init_fn(struct repository *repo,
392+
const char *payload,
392393
const char *gitdir,
393394
unsigned int flags);
394395
/*
@@ -666,4 +667,17 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
666667
unsigned int initial_transaction,
667668
struct strbuf *err);
668669

670+
/*
671+
* Given a gitdir and the reference storage payload provided, retrieve the
672+
* 'refdir' and 'ref_common_dir'. The former is where references should be
673+
* stored for the current worktree, the latter is the common reference
674+
* directory if working with a linked worktree. If working with the main
675+
* worktree, both values will be the same.
676+
*
677+
* This is used by backends that store references in the repository directly.
678+
*/
679+
void refs_compute_filesystem_location(const char *gitdir, const char *payload,
680+
bool *is_worktree, struct strbuf *refdir,
681+
struct strbuf *ref_common_dir);
682+
669683
#endif /* REFS_REFS_INTERNAL_H */

refs/reftable-backend.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -372,18 +372,24 @@ static int reftable_be_fsync(int fd)
372372
}
373373

374374
static struct ref_store *reftable_be_init(struct repository *repo,
375+
const char *payload,
375376
const char *gitdir,
376377
unsigned int store_flags)
377378
{
378379
struct reftable_ref_store *refs = xcalloc(1, sizeof(*refs));
380+
struct strbuf ref_common_dir = STRBUF_INIT;
381+
struct strbuf refdir = STRBUF_INIT;
379382
struct strbuf path = STRBUF_INIT;
380-
int is_worktree;
383+
bool is_worktree;
381384
mode_t mask;
382385

383386
mask = umask(0);
384387
umask(mask);
385388

386-
base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);
389+
refs_compute_filesystem_location(gitdir, payload, &is_worktree, &refdir,
390+
&ref_common_dir);
391+
392+
base_ref_store_init(&refs->base, repo, refdir.buf, &refs_be_reftable);
387393
strmap_init(&refs->worktree_backends);
388394
refs->store_flags = store_flags;
389395
refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
@@ -419,14 +425,11 @@ static struct ref_store *reftable_be_init(struct repository *repo,
419425
/*
420426
* Set up the main reftable stack that is hosted in GIT_COMMON_DIR.
421427
* This stack contains both the shared and the main worktree refs.
422-
*
423-
* Note that we don't try to resolve the path in case we have a
424-
* worktree because `get_common_dir_noenv()` already does it for us.
425428
*/
426-
is_worktree = get_common_dir_noenv(&path, gitdir);
429+
strbuf_addbuf(&path, &ref_common_dir);
427430
if (!is_worktree) {
428431
strbuf_reset(&path);
429-
strbuf_realpath(&path, gitdir, 0);
432+
strbuf_realpath(&path, ref_common_dir.buf, 0);
430433
}
431434
strbuf_addstr(&path, "/reftable");
432435
refs->err = reftable_backend_init(&refs->main_backend, path.buf,
@@ -443,10 +446,9 @@ static struct ref_store *reftable_be_init(struct repository *repo,
443446
* do it efficiently.
444447
*/
445448
if (is_worktree) {
446-
strbuf_reset(&path);
447-
strbuf_addf(&path, "%s/reftable", gitdir);
449+
strbuf_addstr(&refdir, "/reftable");
448450

449-
refs->err = reftable_backend_init(&refs->worktree_backend, path.buf,
451+
refs->err = reftable_backend_init(&refs->worktree_backend, refdir.buf,
450452
&refs->write_options);
451453
if (refs->err)
452454
goto done;
@@ -456,6 +458,8 @@ static struct ref_store *reftable_be_init(struct repository *repo,
456458

457459
done:
458460
assert(refs->err != REFTABLE_API_ERROR);
461+
strbuf_release(&ref_common_dir);
462+
strbuf_release(&refdir);
459463
strbuf_release(&path);
460464
return &refs->base;
461465
}

0 commit comments

Comments
 (0)