From: Karthik Nayak <karthik.188@gmail.com>
To: git@vger.kernel.org
Cc: Karthik Nayak <karthik.188@gmail.com>, gitster@pobox.com, ps@pks.im
Subject: [PATCH v2 0/9] refs: move some of the generic logic out of the backends
Date: Thu, 23 Apr 2026 10:40:29 +0200 [thread overview]
Message-ID: <20260423-refs-move-to-generic-layer-v2-0-ae5a4f146d7d@gmail.com> (raw)
In-Reply-To: <20260420-refs-move-to-generic-layer-v1-0-513e354f376b@gmail.com>
This series came together while I was working on other reference related
code and realized that some of the individual logic implemented with the
reference backends can be moved to the generic layer.
Moving code to the generic layer, simplifies the responsibility of
individual backends and avoids deviation in logic between the backends.
The biggest changes are related to moving out usage of `parse_object()`
and `peel_object()` from reference transactions. The former is used to
validate that the OID provided points to a commit object. The latter is
an optimization technique where the packed/reftable backend store the
peeled OID whenever available, so reading such references provides the
peeled OID without having to call the ODB.
Moving object parsing to the generic layout involves moving it out of
the prepare stage of the transaction and into `ref_transaction_update()`
where every added update is checked. As such, this also involves
modifying update-ref(1) and receive-pack(1) to follow this paradigm.
---
Changes in v2:
- Split the second commit into two: one introducing
`ref_store_init_options` and the second to use it for reflog config.
- Use opts as the variable name consistently.
- A bunch of grammar fixes.
- Link to v1: https://patch.msgid.link/20260420-refs-move-to-generic-layer-v1-0-513e354f376b@gmail.com
---
builtin/receive-pack.c | 22 +++++---
builtin/update-ref.c | 145 +++++++++++++++++++++++++++++++-----------------
refs.c | 60 +++++++++++++++-----
refs.h | 16 +++---
refs/files-backend.c | 58 +++++++------------
refs/packed-backend.c | 10 ++--
refs/packed-backend.h | 3 +-
refs/refs-internal.h | 35 ++++++++++--
refs/reftable-backend.c | 40 +++----------
9 files changed, 225 insertions(+), 164 deletions(-)
Karthik Nayak (9):
refs: remove unused typedef 'ref_transaction_commit_fn'
refs: introduce `ref_store_init_options`
refs: extract out reflog config to generic layer
refs: return `ref_transaction_error` from `ref_transaction_update()`
update-ref: move `print_rejected_refs()` up
update-ref: handle rejections while adding updates
refs: move object parsing to the generic layer
refs: add peeled object ID to the `ref_update` struct
refs: use peeled tag values in reference backends
Range-diff versus v1:
1: bbcc7bff38 = 1: 807f23ee66 refs: remove unused typedef 'ref_transaction_commit_fn'
2: 57a66ae8d5 ! 2: f63583d8b0 refs: extract out reflog config to generic layer
@@ Metadata
Author: Karthik Nayak <karthik.188@gmail.com>
## Commit message ##
- refs: extract out reflog config to generic layer
+ refs: introduce `ref_store_init_options`
- The reference backends need to know when to create reflog entries, this
- is dictated by the 'core.logallrefupdates' config. Instead of relying on
- the backends to call `repo_settings_get_log_all_ref_updates()` to obtain
- this config value, let's do this in the generic layer and pass down the
- value to the backends.
+ Reference backends are initiated via the `init()` function. When
+ initiating the function, the backend is also provided flags which denote
+ the access levels of the initiator. Create a new structure
+ `ref_store_init_options` to house such options and move the access flags
+ to this structure.
- Instead of passing this in as a new argument, let's create a new
- `ref_init_options` structure which will house information required to
- initialize a reference backend. Move the access flags here as well.
+ This allows easier extension of providing further options to the
+ backends. In the following commit, we'll also provide config around
+ reflog creation to the backends via the same structure.
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
@@ refs.c: static struct ref_store *ref_store_init(struct repository *repo,
{
const struct ref_storage_be *be;
struct ref_store *refs;
-+ struct ref_store_init_options options = {
++ struct ref_store_init_options opts = {
+ .access_flags = flags,
-+ .log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo),
+ };
be = find_ref_storage_backend(format);
@@ refs.c: static struct ref_store *ref_store_init(struct repository *repo,
* allow the backend to handle how it wants to deal with worktrees.
*/
- refs = be->init(repo, repo->ref_storage_payload, gitdir, flags);
-+ refs = be->init(repo, repo->ref_storage_payload, gitdir, &options);
++ refs = be->init(repo, repo->ref_storage_payload, gitdir, &opts);
+
return refs;
}
@@ refs/files-backend.c: static void clear_loose_ref_cache(struct files_ref_store *
const char *payload,
const char *gitdir,
- unsigned int flags)
-+ const struct ref_store_init_options *options)
++ const struct ref_store_init_options *opts)
{
struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
struct ref_store *ref_store = (struct ref_store *)refs;
@@ refs/files-backend.c: static struct ref_store *files_ref_store_init(struct repos
refs->gitcommondir = strbuf_detach(&ref_common_dir, NULL);
refs->packed_ref_store =
- packed_ref_store_init(repo, NULL, refs->gitcommondir, flags);
-- refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
-+ packed_ref_store_init(repo, payload, refs->gitcommondir, options);
-+ refs->store_flags = options->access_flags;
-+ refs->log_all_ref_updates = options->log_all_ref_updates;
++ packed_ref_store_init(repo, payload, refs->gitcommondir, opts);
++ refs->store_flags = opts->access_flags;
+ refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
+
repo_config_get_bool(repo, "core.prefersymlinkrefs", &refs->prefer_symlink_refs);
@@ refs/packed-backend.c: static size_t snapshot_hexsz(const struct snapshot *snaps
const char *payload UNUSED,
const char *gitdir,
- unsigned int store_flags)
-+ const struct ref_store_init_options *options)
++ const struct ref_store_init_options *opts)
{
struct packed_ref_store *refs = xcalloc(1, sizeof(*refs));
struct ref_store *ref_store = (struct ref_store *)refs;
@@ refs/packed-backend.c: static size_t snapshot_hexsz(const struct snapshot *snaps
base_ref_store_init(ref_store, repo, gitdir, &refs_be_packed);
- refs->store_flags = store_flags;
-+ refs->store_flags = options->access_flags;
++ refs->store_flags = opts->access_flags;
strbuf_addf(&sb, "%s/packed-refs", gitdir);
refs->path = strbuf_detach(&sb, NULL);
@@ refs/refs-internal.h: struct ref_store;
+struct ref_store_init_options {
+ /* The kind of operations that the ref_store is allowed to perform. */
+ unsigned int access_flags;
-+
-+ /*
-+ * Denotes under what conditions reflogs should be created when updating
-+ * references.
-+ */
-+ enum log_refs_config log_all_ref_updates;
+};
+
/*
@@ refs/refs-internal.h: struct ref_store;
const char *payload,
const char *gitdir,
- unsigned int flags);
-+ const struct ref_store_init_options *options);
++ const struct ref_store_init_options *opts);
/*
* Release all memory and resources associated with the ref store.
*/
@@ refs/reftable-backend.c: static int reftable_be_config(const char *var, const ch
const char *payload,
const char *gitdir,
- unsigned int store_flags)
-+ const struct ref_store_init_options *options)
++ const struct ref_store_init_options *opts)
{
struct reftable_ref_store *refs = xcalloc(1, sizeof(*refs));
struct strbuf ref_common_dir = STRBUF_INIT;
@@ refs/reftable-backend.c: static struct ref_store *reftable_be_init(struct reposi
base_ref_store_init(&refs->base, repo, refdir.buf, &refs_be_reftable);
strmap_init(&refs->worktree_backends);
- refs->store_flags = store_flags;
-- refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
-+ refs->store_flags = options->access_flags;
-+ refs->log_all_ref_updates = options->log_all_ref_updates;
+ refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
++ refs->store_flags = opts->access_flags;
switch (repo->hash_algo->format_id) {
case GIT_SHA1_FORMAT_ID:
-: ---------- > 3: 15fd026e85 refs: extract out reflog config to generic layer
3: 1c05642914 ! 4: a389011125 refs: return `ref_transaction_error` from `ref_transaction_update()`
@@ Commit message
The `ref_transaction_update()` function is used to add updates to a
given reference transactions. In the following commit, we'll add more
- validation to this function. As such, it would be more beneficial if the
+ validation to this function. As such, it would be beneficial if the
function returns specific error types, so callers can differentiate
between different errors.
4: 6d9544a834 ! 5: 3a203ace83 update-ref: move `print_rejected_refs()` up
@@ Metadata
## Commit message ##
update-ref: move `print_rejected_refs()` up
- The `print_rejected_refs()` is used to print any rejected refs when
- using git-updated-ref(1) with the '--batch-updates' option. In the
- following commit, we'll need to use this function in other places, so
+ The `print_rejected_refs()` function is used to print any rejected refs
+ when using git-updated-ref(1) with the '--batch-updates' option. In the
+ following commit, we'll need to use this function in another place, so
move the function up to avoid a separate forward declaration.
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
5: fd3b66ec45 ! 6: e6b2c7b523 update-ref: handle rejections while adding updates
@@ Commit message
When using git-update-ref(1) with the '--batch-updates' flag, updates
rejected by the reference backend are displayed to the user while other
- updates are applied. This only applies during the committing of the
+ updates are applied. This only applies during the commit phase of the
transaction.
In the following commits, we'll also extend `ref_transaction_update()`
- to reject updates before even a transaction is prepared/committed. In
+ to reject updates before a transaction is prepared/committed. In
preparation, modify the code in update-ref to also handle non-generic
rejections from `ref_transaction_update()`. This involves propagating
information to each of the commands on whether updates are allowed to be
@@ builtin/update-ref.c: static void parse_cmd_update(struct ref_transaction *trans
+ msg, &err);
+
+ if (tx_err && tx_err != REF_TRANSACTION_ERROR_GENERIC &&
-+ opts->allow_update_failures)
++ opts->allow_update_failures) {
+ print_rejected_refs(refname, have_old ? &old_oid : NULL,
+ &new_oid, NULL, NULL, tx_err, err.buf,
+ NULL);
-+ else if (tx_err)
++ } else if (tx_err) {
die("%s", err.buf);
++ }
update_flags = default_flags;
+ free(refname);
@@ builtin/update-ref.c: static void parse_cmd_update(struct ref_transaction *transaction,
}
@@ builtin/update-ref.c: static void parse_cmd_symref_update(struct ref_transaction
+ msg, &err);
+
+ if (tx_err && tx_err != REF_TRANSACTION_ERROR_GENERIC &&
-+ opts->allow_update_failures)
++ opts->allow_update_failures) {
+ print_rejected_refs(refname, have_old_oid ? &old_oid : NULL,
+ NULL, have_old_oid ? NULL : old_target,
+ new_target, tx_err, err.buf, NULL);
-+ else if (tx_err)
++ } else if (tx_err) {
die("%s", err.buf);
++ }
update_flags = default_flags;
+ free(refname);
@@ builtin/update-ref.c: static void parse_cmd_symref_update(struct ref_transaction *transaction,
}
6: 3be9566bf9 ! 7: 36a6284ac1 refs: move object parsing to the generic layer
@@ Commit message
refs: move object parsing to the generic layer
Regular reference updates made via reference transactions validate that
- the provided object ID exists in the object database, this is done by
+ the provided object ID exists in the object database, which is done by
calling 'parse_object()'. This check is done independently by the
- backends.
+ backends which leads to duplicated logic.
Let's move this to the generic layer, ensuring the backends only have to
care about reference storage and not about validation of the object IDs.
7: 5e6a26567a = 8: 32f3bc52f1 refs: add peeled object ID to the `ref_update` struct
8: 27914d0556 = 9: bbcdbd3d18 refs: use peeled tag values in reference backends
base-commit: f65aba1e87db64413b6d1ed5ae5a45b5a84a0997
change-id: 20260417-refs-move-to-generic-layer-f7525c5e8764
Thanks
- Karthik
next prev parent reply other threads:[~2026-04-23 8:40 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-20 10:11 [PATCH 0/8] refs: move some of the generic logic out of the backends Karthik Nayak
2026-04-20 10:11 ` [PATCH 1/8] refs: remove unused typedef 'ref_transaction_commit_fn' Karthik Nayak
2026-04-22 11:15 ` Patrick Steinhardt
2026-04-22 12:20 ` Karthik Nayak
2026-04-20 10:12 ` [PATCH 2/8] refs: extract out reflog config to generic layer Karthik Nayak
2026-04-22 11:15 ` Patrick Steinhardt
2026-04-22 13:13 ` Karthik Nayak
2026-04-20 10:12 ` [PATCH 3/8] refs: return `ref_transaction_error` from `ref_transaction_update()` Karthik Nayak
2026-04-22 11:15 ` Patrick Steinhardt
2026-04-22 13:14 ` Karthik Nayak
2026-04-20 10:12 ` [PATCH 4/8] update-ref: move `print_rejected_refs()` up Karthik Nayak
2026-04-22 11:15 ` Patrick Steinhardt
2026-04-22 13:16 ` Karthik Nayak
2026-04-20 10:12 ` [PATCH 5/8] update-ref: handle rejections while adding updates Karthik Nayak
2026-04-22 11:15 ` Patrick Steinhardt
2026-04-22 14:13 ` Karthik Nayak
2026-04-20 10:12 ` [PATCH 6/8] refs: move object parsing to the generic layer Karthik Nayak
2026-04-22 11:15 ` Patrick Steinhardt
2026-04-22 15:03 ` Karthik Nayak
2026-04-20 10:12 ` [PATCH 7/8] refs: add peeled object ID to the `ref_update` struct Karthik Nayak
2026-04-20 10:12 ` [PATCH 8/8] refs: use peeled tag values in reference backends Karthik Nayak
2026-04-23 8:40 ` Karthik Nayak [this message]
2026-04-23 8:40 ` [PATCH v2 1/9] refs: remove unused typedef 'ref_transaction_commit_fn' Karthik Nayak
2026-04-23 8:40 ` [PATCH v2 2/9] refs: introduce `ref_store_init_options` Karthik Nayak
2026-04-23 8:52 ` Patrick Steinhardt
2026-04-24 9:34 ` Karthik Nayak
2026-04-23 8:40 ` [PATCH v2 3/9] refs: extract out reflog config to generic layer Karthik Nayak
2026-04-23 8:52 ` Patrick Steinhardt
2026-04-23 8:40 ` [PATCH v2 4/9] refs: return `ref_transaction_error` from `ref_transaction_update()` Karthik Nayak
2026-04-24 11:01 ` Toon Claes
2026-04-23 8:40 ` [PATCH v2 5/9] update-ref: move `print_rejected_refs()` up Karthik Nayak
2026-04-23 8:40 ` [PATCH v2 6/9] update-ref: handle rejections while adding updates Karthik Nayak
2026-04-23 8:52 ` Patrick Steinhardt
2026-04-24 9:35 ` Karthik Nayak
2026-04-24 11:22 ` Toon Claes
2026-04-27 8:47 ` Karthik Nayak
2026-04-23 8:40 ` [PATCH v2 7/9] refs: move object parsing to the generic layer Karthik Nayak
2026-04-24 12:06 ` Toon Claes
2026-04-27 9:32 ` Karthik Nayak
2026-04-23 8:40 ` [PATCH v2 8/9] refs: add peeled object ID to the `ref_update` struct Karthik Nayak
2026-04-24 16:44 ` Toon Claes
2026-04-27 9:33 ` Karthik Nayak
2026-04-23 8:40 ` [PATCH v2 9/9] refs: use peeled tag values in reference backends Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 0/9] refs: move some of the generic logic out of the backends Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 1/9] refs: remove unused typedef 'ref_transaction_commit_fn' Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 2/9] refs: introduce `ref_store_init_options` Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 3/9] refs: extract out reflog config to generic layer Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 4/9] refs: return `ref_transaction_error` from `ref_transaction_update()` Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 5/9] update-ref: move `print_rejected_refs()` up Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 6/9] update-ref: handle rejections while adding updates Karthik Nayak
2026-04-29 12:24 ` Toon Claes
2026-04-30 9:52 ` Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 7/9] refs: move object parsing to the generic layer Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 8/9] refs: add peeled object ID to the `ref_update` struct Karthik Nayak
2026-04-27 10:42 ` [PATCH v3 9/9] refs: use peeled tag values in reference backends Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 0/9] refs: move some of the generic logic out of the backends Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 1/9] refs: remove unused typedef 'ref_transaction_commit_fn' Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 2/9] refs: introduce `ref_store_init_options` Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 3/9] refs: extract out reflog config to generic layer Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 4/9] refs: return `ref_transaction_error` from `ref_transaction_update()` Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 5/9] update-ref: move `print_rejected_refs()` up Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 6/9] update-ref: handle rejections while adding updates Karthik Nayak
2026-05-05 5:52 ` Patrick Steinhardt
2026-05-05 8:23 ` Karthik Nayak
2026-05-06 19:44 ` Toon Claes
2026-05-04 17:44 ` [PATCH v4 7/9] refs: move object parsing to the generic layer Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 8/9] refs: add peeled object ID to the `ref_update` struct Karthik Nayak
2026-05-04 17:44 ` [PATCH v4 9/9] refs: use peeled tag values in reference backends Karthik Nayak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260423-refs-move-to-generic-layer-v2-0-ae5a4f146d7d@gmail.com \
--to=karthik.188@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=ps@pks.im \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox