From: Karthik Nayak <karthik.188@gmail.com>
To: git@vger.kernel.org
Cc: Karthik Nayak <karthik.188@gmail.com>,
ps@pks.im, jltobler@gmail.com, phillip.wood123@gmail.com
Subject: [PATCH v4 5/8] refs: introduce enum-based transaction error types
Date: Thu, 20 Mar 2025 12:44:00 +0100 [thread overview]
Message-ID: <20250320-245-partially-atomic-ref-updates-v4-5-3dcc1b311dc9@gmail.com> (raw)
In-Reply-To: <20250320-245-partially-atomic-ref-updates-v4-0-3dcc1b311dc9@gmail.com>
Replace preprocessor-defined transaction errors with a strongly-typed
enum `ref_transaction_error`. This change:
- Improves type safety and function signature clarity.
- Makes error handling more explicit and discoverable.
- Maintains existing error cases, while adding new error cases for
common scenarios.
This refactoring paves the way for more comprehensive error handling
which we will utilize in the upcoming commits to add batch reference
update support.
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
---
builtin/fetch.c | 2 +-
refs.c | 49 ++++++------
refs.h | 54 ++++++++-----
refs/files-backend.c | 202 ++++++++++++++++++++++++------------------------
refs/packed-backend.c | 23 +++---
refs/refs-internal.h | 5 +-
refs/reftable-backend.c | 64 +++++++--------
7 files changed, 213 insertions(+), 186 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 95fd0018b9..7615c17faf 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -687,7 +687,7 @@ static int s_update_ref(const char *action,
switch (ref_transaction_commit(our_transaction, &err)) {
case 0:
break;
- case TRANSACTION_NAME_CONFLICT:
+ case REF_TRANSACTION_ERROR_NAME_CONFLICT:
ret = STORE_REF_ERROR_DF_CONFLICT;
goto out;
default:
diff --git a/refs.c b/refs.c
index 61bed9672a..3d0b53d56e 100644
--- a/refs.c
+++ b/refs.c
@@ -2271,7 +2271,7 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref,
REF_NO_DEREF, logmsg, &err))
goto error_return;
prepret = ref_transaction_prepare(transaction, &err);
- if (prepret && prepret != TRANSACTION_CREATE_EXISTS)
+ if (prepret && prepret != REF_TRANSACTION_ERROR_CREATE_EXISTS)
goto error_return;
} else {
if (ref_transaction_update(transaction, ref, NULL, NULL,
@@ -2289,7 +2289,7 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref,
}
}
- if (prepret == TRANSACTION_CREATE_EXISTS)
+ if (prepret == REF_TRANSACTION_ERROR_CREATE_EXISTS)
goto cleanup;
if (ref_transaction_commit(transaction, &err))
@@ -2425,7 +2425,7 @@ int ref_transaction_prepare(struct ref_transaction *transaction,
string_list_sort(&transaction->refnames);
if (ref_update_reject_duplicates(&transaction->refnames, err))
- return TRANSACTION_GENERIC_ERROR;
+ return REF_TRANSACTION_ERROR_GENERIC;
ret = refs->be->transaction_prepare(refs, transaction, err);
if (ret)
@@ -2497,19 +2497,19 @@ int ref_transaction_commit(struct ref_transaction *transaction,
return ret;
}
-int refs_verify_refnames_available(struct ref_store *refs,
- const struct string_list *refnames,
- const struct string_list *extras,
- const struct string_list *skip,
- unsigned int initial_transaction,
- struct strbuf *err)
+enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs,
+ const struct string_list *refnames,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ unsigned int initial_transaction,
+ struct strbuf *err)
{
struct strbuf dirname = STRBUF_INIT;
struct strbuf referent = STRBUF_INIT;
struct string_list_item *item;
struct ref_iterator *iter = NULL;
struct strset dirnames;
- int ret = -1;
+ int ret = REF_TRANSACTION_ERROR_NAME_CONFLICT;
/*
* For the sake of comments in this function, suppose that
@@ -2625,12 +2625,13 @@ int refs_verify_refnames_available(struct ref_store *refs,
return ret;
}
-int refs_verify_refname_available(struct ref_store *refs,
- const char *refname,
- const struct string_list *extras,
- const struct string_list *skip,
- unsigned int initial_transaction,
- struct strbuf *err)
+enum ref_transaction_error refs_verify_refname_available(
+ struct ref_store *refs,
+ const char *refname,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ unsigned int initial_transaction,
+ struct strbuf *err)
{
struct string_list_item item = { .string = (char *) refname };
struct string_list refnames = {
@@ -2818,8 +2819,9 @@ int ref_update_has_null_new_value(struct ref_update *update)
return !update->new_target && is_null_oid(&update->new_oid);
}
-int ref_update_check_old_target(const char *referent, struct ref_update *update,
- struct strbuf *err)
+enum ref_transaction_error ref_update_check_old_target(const char *referent,
+ struct ref_update *update,
+ struct strbuf *err)
{
if (!update->old_target)
BUG("called without old_target set");
@@ -2827,17 +2829,18 @@ int ref_update_check_old_target(const char *referent, struct ref_update *update,
if (!strcmp(referent, update->old_target))
return 0;
- if (!strcmp(referent, ""))
+ if (!strcmp(referent, "")) {
strbuf_addf(err, "verifying symref target: '%s': "
"reference is missing but expected %s",
ref_update_original_update_refname(update),
update->old_target);
- else
- strbuf_addf(err, "verifying symref target: '%s': "
- "is at %s but expected %s",
+ return REF_TRANSACTION_ERROR_NONEXISTENT_REF;
+ }
+
+ strbuf_addf(err, "verifying symref target: '%s': is at %s but expected %s",
ref_update_original_update_refname(update),
referent, update->old_target);
- return -1;
+ return REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE;
}
struct migration_data {
diff --git a/refs.h b/refs.h
index 240e2d8537..dcd83e81e2 100644
--- a/refs.h
+++ b/refs.h
@@ -16,6 +16,29 @@ struct worktree;
enum ref_storage_format ref_storage_format_by_name(const char *name);
const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format);
+/*
+ * enum ref_transaction_error represents the following return codes:
+ * REF_TRANSACTION_ERROR_GENERIC error_code: default error code.
+ * REF_TRANSACTION_ERROR_NAME_CONFLICT error_code: ref name conflict like A vs A/B.
+ * REF_TRANSACTION_ERROR_CREATE_EXISTS error_code: ref to be created already exists.
+ * REF_TRANSACTION_ERROR_NONEXISTENT_REF error_code: ref expected but doesn't exist.
+ * REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE error_code: provided old_oid or old_target of
+ * reference doesn't match actual.
+ * REF_TRANSACTION_ERROR_INVALID_NEW_VALUE error_code: provided new_oid or new_target is
+ * invalid.
+ * REF_TRANSACTION_ERROR_EXPECTED_SYMREF error_code: expected ref to be symref, but is a
+ * regular ref.
+ */
+enum ref_transaction_error {
+ REF_TRANSACTION_ERROR_GENERIC = -1,
+ REF_TRANSACTION_ERROR_NAME_CONFLICT = -2,
+ REF_TRANSACTION_ERROR_CREATE_EXISTS = -3,
+ REF_TRANSACTION_ERROR_NONEXISTENT_REF = -4,
+ REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE = -5,
+ REF_TRANSACTION_ERROR_INVALID_NEW_VALUE = -6,
+ REF_TRANSACTION_ERROR_EXPECTED_SYMREF = -7,
+};
+
/*
* Resolve a reference, recursively following symbolic references.
*
@@ -117,24 +140,24 @@ int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
*
* extras and skip must be sorted.
*/
-int refs_verify_refname_available(struct ref_store *refs,
- const char *refname,
- const struct string_list *extras,
- const struct string_list *skip,
- unsigned int initial_transaction,
- struct strbuf *err);
+enum ref_transaction_error refs_verify_refname_available(struct ref_store *refs,
+ const char *refname,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ unsigned int initial_transaction,
+ struct strbuf *err);
/*
* Same as `refs_verify_refname_available()`, but checking for a list of
* refnames instead of only a single item. This is more efficient in the case
* where one needs to check multiple refnames.
*/
-int refs_verify_refnames_available(struct ref_store *refs,
- const struct string_list *refnames,
- const struct string_list *extras,
- const struct string_list *skip,
- unsigned int initial_transaction,
- struct strbuf *err);
+enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs,
+ const struct string_list *refnames,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ unsigned int initial_transaction,
+ struct strbuf *err);
int refs_ref_exists(struct ref_store *refs, const char *refname);
@@ -830,13 +853,6 @@ int ref_transaction_verify(struct ref_transaction *transaction,
unsigned int flags,
struct strbuf *err);
-/* Naming conflict (for example, the ref names A and A/B conflict). */
-#define TRANSACTION_NAME_CONFLICT -1
-/* When only creation was requested, but the ref already exists. */
-#define TRANSACTION_CREATE_EXISTS -2
-/* All other errors. */
-#define TRANSACTION_GENERIC_ERROR -3
-
/*
* Perform the preparatory stages of committing `transaction`. Acquire
* any needed locks, check preconditions, etc.; basically, do as much
diff --git a/refs/files-backend.c b/refs/files-backend.c
index ea023a59fc..4f27f7652c 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -663,7 +663,7 @@ static void unlock_ref(struct ref_lock *lock)
* broken, lock the reference anyway but clear old_oid.
*
* Return 0 on success. On failure, write an error message to err and
- * return TRANSACTION_NAME_CONFLICT or TRANSACTION_GENERIC_ERROR.
+ * return REF_TRANSACTION_ERROR_NAME_CONFLICT or REF_TRANSACTION_ERROR_GENERIC.
*
* Implementation note: This function is basically
*
@@ -676,19 +676,20 @@ static void unlock_ref(struct ref_lock *lock)
* avoided, namely if we were successfully able to read the ref
* - Generate informative error messages in the case of failure
*/
-static int lock_raw_ref(struct files_ref_store *refs,
- const char *refname, int mustexist,
- struct string_list *refnames_to_check,
- const struct string_list *extras,
- struct ref_lock **lock_p,
- struct strbuf *referent,
- unsigned int *type,
- struct strbuf *err)
-{
+static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
+ const char *refname,
+ int mustexist,
+ struct string_list *refnames_to_check,
+ const struct string_list *extras,
+ struct ref_lock **lock_p,
+ struct strbuf *referent,
+ unsigned int *type,
+ struct strbuf *err)
+{
+ enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC;
struct ref_lock *lock;
struct strbuf ref_file = STRBUF_INIT;
int attempts_remaining = 3;
- int ret = TRANSACTION_GENERIC_ERROR;
int failure_errno;
assert(err);
@@ -728,13 +729,14 @@ static int lock_raw_ref(struct files_ref_store *refs,
strbuf_reset(err);
strbuf_addf(err, "unable to resolve reference '%s'",
refname);
+ ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF;
} else {
/*
* The error message set by
* refs_verify_refname_available() is
* OK.
*/
- ret = TRANSACTION_NAME_CONFLICT;
+ ret = REF_TRANSACTION_ERROR_NAME_CONFLICT;
}
} else {
/*
@@ -788,6 +790,7 @@ static int lock_raw_ref(struct files_ref_store *refs,
/* Garden variety missing reference. */
strbuf_addf(err, "unable to resolve reference '%s'",
refname);
+ ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF;
goto error_return;
} else {
/*
@@ -820,6 +823,7 @@ static int lock_raw_ref(struct files_ref_store *refs,
/* Garden variety missing reference. */
strbuf_addf(err, "unable to resolve reference '%s'",
refname);
+ ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF;
goto error_return;
} else if (remove_dir_recursively(&ref_file,
REMOVE_DIR_EMPTY_ONLY)) {
@@ -830,7 +834,7 @@ static int lock_raw_ref(struct files_ref_store *refs,
* The error message set by
* verify_refname_available() is OK.
*/
- ret = TRANSACTION_NAME_CONFLICT;
+ ret = REF_TRANSACTION_ERROR_NAME_CONFLICT;
goto error_return;
} else {
/*
@@ -1517,10 +1521,11 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
return ret;
}
-static int write_ref_to_lockfile(struct files_ref_store *refs,
- struct ref_lock *lock,
- const struct object_id *oid,
- int skip_oid_verification, struct strbuf *err);
+static enum ref_transaction_error write_ref_to_lockfile(struct files_ref_store *refs,
+ struct ref_lock *lock,
+ const struct object_id *oid,
+ int skip_oid_verification,
+ struct strbuf *err);
static int commit_ref_update(struct files_ref_store *refs,
struct ref_lock *lock,
const struct object_id *oid, const char *logmsg,
@@ -1926,10 +1931,11 @@ static int files_log_ref_write(struct files_ref_store *refs,
* Write oid into the open lockfile, then close the lockfile. On
* errors, rollback the lockfile, fill in *err and return -1.
*/
-static int write_ref_to_lockfile(struct files_ref_store *refs,
- struct ref_lock *lock,
- const struct object_id *oid,
- int skip_oid_verification, struct strbuf *err)
+static enum ref_transaction_error write_ref_to_lockfile(struct files_ref_store *refs,
+ struct ref_lock *lock,
+ const struct object_id *oid,
+ int skip_oid_verification,
+ struct strbuf *err)
{
static char term = '\n';
struct object *o;
@@ -1943,7 +1949,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,
"trying to write ref '%s' with nonexistent object %s",
lock->ref_name, oid_to_hex(oid));
unlock_ref(lock);
- return -1;
+ return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE;
}
if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
strbuf_addf(
@@ -1951,7 +1957,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,
"trying to write non-commit object %s to branch '%s'",
oid_to_hex(oid), lock->ref_name);
unlock_ref(lock);
- return -1;
+ return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE;
}
}
fd = get_lock_file_fd(&lock->lk);
@@ -1962,7 +1968,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,
strbuf_addf(err,
"couldn't write '%s'", get_lock_file_path(&lock->lk));
unlock_ref(lock);
- return -1;
+ return REF_TRANSACTION_ERROR_GENERIC;
}
return 0;
}
@@ -2376,9 +2382,10 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st
* If update is a direct update of head_ref (the reference pointed to
* by HEAD), then add an extra REF_LOG_ONLY update for HEAD.
*/
-static int split_head_update(struct ref_update *update,
- struct ref_transaction *transaction,
- const char *head_ref, struct strbuf *err)
+static enum ref_transaction_error split_head_update(struct ref_update *update,
+ struct ref_transaction *transaction,
+ const char *head_ref,
+ struct strbuf *err)
{
struct ref_update *new_update;
@@ -2402,7 +2409,7 @@ static int split_head_update(struct ref_update *update,
"multiple updates for 'HEAD' (including one "
"via its referent '%s') are not allowed",
update->refname);
- return TRANSACTION_NAME_CONFLICT;
+ return REF_TRANSACTION_ERROR_NAME_CONFLICT;
}
new_update = ref_transaction_add_update(
@@ -2430,10 +2437,10 @@ static int split_head_update(struct ref_update *update,
* Note that the new update will itself be subject to splitting when
* the iteration gets to it.
*/
-static int split_symref_update(struct ref_update *update,
- const char *referent,
- struct ref_transaction *transaction,
- struct strbuf *err)
+static enum ref_transaction_error split_symref_update(struct ref_update *update,
+ const char *referent,
+ struct ref_transaction *transaction,
+ struct strbuf *err)
{
struct ref_update *new_update;
unsigned int new_flags;
@@ -2450,7 +2457,7 @@ static int split_symref_update(struct ref_update *update,
"multiple updates for '%s' (including one "
"via symref '%s') are not allowed",
referent, update->refname);
- return TRANSACTION_NAME_CONFLICT;
+ return REF_TRANSACTION_ERROR_NAME_CONFLICT;
}
new_flags = update->flags;
@@ -2491,11 +2498,10 @@ static int split_symref_update(struct ref_update *update,
* everything is OK, return 0; otherwise, write an error message to
* err and return -1.
*/
-static int check_old_oid(struct ref_update *update, struct object_id *oid,
- struct strbuf *err)
+static enum ref_transaction_error check_old_oid(struct ref_update *update,
+ struct object_id *oid,
+ struct strbuf *err)
{
- int ret = TRANSACTION_GENERIC_ERROR;
-
if (!(update->flags & REF_HAVE_OLD) ||
oideq(oid, &update->old_oid))
return 0;
@@ -2504,21 +2510,20 @@ static int check_old_oid(struct ref_update *update, struct object_id *oid,
strbuf_addf(err, "cannot lock ref '%s': "
"reference already exists",
ref_update_original_update_refname(update));
- ret = TRANSACTION_CREATE_EXISTS;
- }
- else if (is_null_oid(oid))
+ return REF_TRANSACTION_ERROR_CREATE_EXISTS;
+ } else if (is_null_oid(oid)) {
strbuf_addf(err, "cannot lock ref '%s': "
"reference is missing but expected %s",
ref_update_original_update_refname(update),
oid_to_hex(&update->old_oid));
- else
- strbuf_addf(err, "cannot lock ref '%s': "
- "is at %s but expected %s",
- ref_update_original_update_refname(update),
- oid_to_hex(oid),
- oid_to_hex(&update->old_oid));
+ return REF_TRANSACTION_ERROR_NONEXISTENT_REF;
+ }
- return ret;
+ strbuf_addf(err, "cannot lock ref '%s': is at %s but expected %s",
+ ref_update_original_update_refname(update), oid_to_hex(oid),
+ oid_to_hex(&update->old_oid));
+
+ return REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE;
}
struct files_transaction_backend_data {
@@ -2540,17 +2545,17 @@ struct files_transaction_backend_data {
* - If it is an update of head_ref, add a corresponding REF_LOG_ONLY
* update of HEAD.
*/
-static int lock_ref_for_update(struct files_ref_store *refs,
- struct ref_update *update,
- struct ref_transaction *transaction,
- const char *head_ref,
- struct string_list *refnames_to_check,
- struct strbuf *err)
+static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *refs,
+ struct ref_update *update,
+ struct ref_transaction *transaction,
+ const char *head_ref,
+ struct string_list *refnames_to_check,
+ struct strbuf *err)
{
struct strbuf referent = STRBUF_INIT;
int mustexist = ref_update_expects_existing_old_ref(update);
struct files_transaction_backend_data *backend_data;
- int ret = 0;
+ enum ref_transaction_error ret = 0;
struct ref_lock *lock;
files_assert_main_repository(refs, "lock_ref_for_update");
@@ -2602,22 +2607,17 @@ static int lock_ref_for_update(struct files_ref_store *refs,
strbuf_addf(err, "cannot lock ref '%s': "
"error reading reference",
ref_update_original_update_refname(update));
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto out;
}
}
- if (update->old_target) {
- if (ref_update_check_old_target(referent.buf, update, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
- goto out;
- }
- } else {
+ if (update->old_target)
+ ret = ref_update_check_old_target(referent.buf, update, err);
+ else
ret = check_old_oid(update, &lock->old_oid, err);
- if (ret) {
- goto out;
- }
- }
+ if (ret)
+ goto out;
} else {
/*
* Create a new update for the reference this
@@ -2644,7 +2644,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
"but is a regular ref"),
ref_update_original_update_refname(update),
update->old_target);
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_EXPECTED_SYMREF;
goto out;
} else {
ret = check_old_oid(update, &lock->old_oid, err);
@@ -2668,14 +2668,14 @@ static int lock_ref_for_update(struct files_ref_store *refs,
if (update->new_target && !(update->flags & REF_LOG_ONLY)) {
if (create_symref_lock(lock, update->new_target, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto out;
}
if (close_ref_gently(lock)) {
strbuf_addf(err, "couldn't close '%s.lock'",
update->refname);
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto out;
}
@@ -2693,25 +2693,27 @@ static int lock_ref_for_update(struct files_ref_store *refs,
* The reference already has the desired
* value, so we don't need to write it.
*/
- } else if (write_ref_to_lockfile(
- refs, lock, &update->new_oid,
- update->flags & REF_SKIP_OID_VERIFICATION,
- err)) {
- char *write_err = strbuf_detach(err, NULL);
-
- /*
- * The lock was freed upon failure of
- * write_ref_to_lockfile():
- */
- update->backend_data = NULL;
- strbuf_addf(err,
- "cannot update ref '%s': %s",
- update->refname, write_err);
- free(write_err);
- ret = TRANSACTION_GENERIC_ERROR;
- goto out;
} else {
- update->flags |= REF_NEEDS_COMMIT;
+ ret = write_ref_to_lockfile(
+ refs, lock, &update->new_oid,
+ update->flags & REF_SKIP_OID_VERIFICATION,
+ err);
+ if (ret) {
+ char *write_err = strbuf_detach(err, NULL);
+
+ /*
+ * The lock was freed upon failure of
+ * write_ref_to_lockfile():
+ */
+ update->backend_data = NULL;
+ strbuf_addf(err,
+ "cannot update ref '%s': %s",
+ update->refname, write_err);
+ free(write_err);
+ goto out;
+ } else {
+ update->flags |= REF_NEEDS_COMMIT;
+ }
}
}
if (!(update->flags & REF_NEEDS_COMMIT)) {
@@ -2723,7 +2725,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
if (close_ref_gently(lock)) {
strbuf_addf(err, "couldn't close '%s.lock'",
update->refname);
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto out;
}
}
@@ -2865,7 +2867,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
refs->packed_ref_store,
transaction->flags, err);
if (!packed_transaction) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
@@ -2897,13 +2899,13 @@ static int files_transaction_prepare(struct ref_store *ref_store,
*/
if (refs_verify_refnames_available(refs->packed_ref_store, &refnames_to_check,
&transaction->refnames, NULL, 0, err)) {
- ret = TRANSACTION_NAME_CONFLICT;
+ ret = REF_TRANSACTION_ERROR_NAME_CONFLICT;
goto cleanup;
}
if (packed_transaction) {
if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
backend_data->packed_refs_locked = 1;
@@ -2934,7 +2936,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
*/
backend_data->packed_transaction = NULL;
if (ref_transaction_abort(packed_transaction, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
}
@@ -3035,7 +3037,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
packed_transaction = ref_store_transaction_begin(refs->packed_ref_store,
transaction->flags, err);
if (!packed_transaction) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
@@ -3058,7 +3060,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
if (!loose_transaction) {
loose_transaction = ref_store_transaction_begin(&refs->base, 0, err);
if (!loose_transaction) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
}
@@ -3083,19 +3085,19 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
}
if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
if (refs_verify_refnames_available(&refs->base, &refnames_to_check,
&affected_refnames, NULL, 1, err)) {
packed_refs_unlock(refs->packed_ref_store);
- ret = TRANSACTION_NAME_CONFLICT;
+ ret = REF_TRANSACTION_ERROR_NAME_CONFLICT;
goto cleanup;
}
if (ref_transaction_commit(packed_transaction, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
packed_refs_unlock(refs->packed_ref_store);
@@ -3103,7 +3105,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
if (loose_transaction) {
if (ref_transaction_prepare(loose_transaction, err) ||
ref_transaction_commit(loose_transaction, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
}
@@ -3152,7 +3154,7 @@ static int files_transaction_finish(struct ref_store *ref_store,
if (update->flags & REF_NEEDS_COMMIT ||
update->flags & REF_LOG_ONLY) {
if (parse_and_write_reflog(refs, update, lock, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
}
@@ -3171,7 +3173,7 @@ static int files_transaction_finish(struct ref_store *ref_store,
strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
unlock_ref(lock);
update->backend_data = NULL;
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
}
@@ -3227,7 +3229,7 @@ static int files_transaction_finish(struct ref_store *ref_store,
strbuf_reset(&sb);
files_ref_path(refs, &sb, lock->ref_name);
if (unlink_or_msg(sb.buf, err)) {
- ret = TRANSACTION_GENERIC_ERROR;
+ ret = REF_TRANSACTION_ERROR_GENERIC;
goto cleanup;
}
}
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 19220d2e99..d90bd815a3 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1326,10 +1326,11 @@ static int packed_ref_store_remove_on_disk(struct ref_store *ref_store,
* The packfile must be locked before calling this function and will
* remain locked when it is done.
*/
-static int write_with_updates(struct packed_ref_store *refs,
- struct string_list *updates,
- struct strbuf *err)
+static enum ref_transaction_error write_with_updates(struct packed_ref_store *refs,
+ struct string_list *updates,
+ struct strbuf *err)
{
+ enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC;
struct ref_iterator *iter = NULL;
size_t i;
int ok;
@@ -1353,7 +1354,7 @@ static int write_with_updates(struct packed_ref_store *refs,
strbuf_addf(err, "unable to create file %s: %s",
sb.buf, strerror(errno));
strbuf_release(&sb);
- return -1;
+ return REF_TRANSACTION_ERROR_GENERIC;
}
strbuf_release(&sb);
@@ -1409,6 +1410,7 @@ static int write_with_updates(struct packed_ref_store *refs,
strbuf_addf(err, "cannot update ref '%s': "
"reference already exists",
update->refname);
+ ret = REF_TRANSACTION_ERROR_CREATE_EXISTS;
goto error;
} else if (!oideq(&update->old_oid, iter->oid)) {
strbuf_addf(err, "cannot update ref '%s': "
@@ -1416,6 +1418,7 @@ static int write_with_updates(struct packed_ref_store *refs,
update->refname,
oid_to_hex(iter->oid),
oid_to_hex(&update->old_oid));
+ ret = REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE;
goto error;
}
}
@@ -1452,6 +1455,7 @@ static int write_with_updates(struct packed_ref_store *refs,
"reference is missing but expected %s",
update->refname,
oid_to_hex(&update->old_oid));
+ ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF;
goto error;
}
}
@@ -1509,7 +1513,7 @@ static int write_with_updates(struct packed_ref_store *refs,
strerror(errno));
strbuf_release(&sb);
delete_tempfile(&refs->tempfile);
- return -1;
+ return REF_TRANSACTION_ERROR_GENERIC;
}
return 0;
@@ -1521,7 +1525,7 @@ static int write_with_updates(struct packed_ref_store *refs,
error:
ref_iterator_free(iter);
delete_tempfile(&refs->tempfile);
- return -1;
+ return ret;
}
int is_packed_transaction_needed(struct ref_store *ref_store,
@@ -1654,7 +1658,7 @@ static int packed_transaction_prepare(struct ref_store *ref_store,
REF_STORE_READ | REF_STORE_WRITE | REF_STORE_ODB,
"ref_transaction_prepare");
struct packed_transaction_backend_data *data;
- int ret = TRANSACTION_GENERIC_ERROR;
+ enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC;
/*
* Note that we *don't* skip transactions with zero updates,
@@ -1675,7 +1679,8 @@ static int packed_transaction_prepare(struct ref_store *ref_store,
data->own_lock = 1;
}
- if (write_with_updates(refs, &transaction->refnames, err))
+ ret = write_with_updates(refs, &transaction->refnames, err);
+ if (ret)
goto failure;
transaction->state = REF_TRANSACTION_PREPARED;
@@ -1707,7 +1712,7 @@ static int packed_transaction_finish(struct ref_store *ref_store,
ref_store,
REF_STORE_READ | REF_STORE_WRITE | REF_STORE_ODB,
"ref_transaction_finish");
- int ret = TRANSACTION_GENERIC_ERROR;
+ int ret = REF_TRANSACTION_ERROR_GENERIC;
char *packed_refs_path;
clear_snapshot(refs);
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 6d3770d0cc..3f1d19abd9 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -770,8 +770,9 @@ int ref_update_has_null_new_value(struct ref_update *update);
* If everything is OK, return 0; otherwise, write an error message to
* err and return -1.
*/
-int ref_update_check_old_target(const char *referent, struct ref_update *update,
- struct strbuf *err);
+enum ref_transaction_error ref_update_check_old_target(const char *referent,
+ struct ref_update *update,
+ struct strbuf *err);
/*
* Check if the ref must exist, this means that the old_oid or
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 786df11a03..bd6b042103 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1069,20 +1069,20 @@ static int queue_transaction_update(struct reftable_ref_store *refs,
return 0;
}
-static int prepare_single_update(struct reftable_ref_store *refs,
- struct reftable_transaction_data *tx_data,
- struct ref_transaction *transaction,
- struct reftable_backend *be,
- struct ref_update *u,
- struct string_list *refnames_to_check,
- unsigned int head_type,
- struct strbuf *head_referent,
- struct strbuf *referent,
- struct strbuf *err)
+static enum ref_transaction_error prepare_single_update(struct reftable_ref_store *refs,
+ struct reftable_transaction_data *tx_data,
+ struct ref_transaction *transaction,
+ struct reftable_backend *be,
+ struct ref_update *u,
+ struct string_list *refnames_to_check,
+ unsigned int head_type,
+ struct strbuf *head_referent,
+ struct strbuf *referent,
+ struct strbuf *err)
{
+ enum ref_transaction_error ret = 0;
struct object_id current_oid = {0};
const char *rewritten_ref;
- int ret = 0;
/*
* There is no need to reload the respective backends here as
@@ -1093,7 +1093,7 @@ static int prepare_single_update(struct reftable_ref_store *refs,
*/
ret = backend_for(&be, refs, u->refname, &rewritten_ref, 0);
if (ret)
- return ret;
+ return REF_TRANSACTION_ERROR_GENERIC;
/* Verify that the new object ID is valid. */
if ((u->flags & REF_HAVE_NEW) && !is_null_oid(&u->new_oid) &&
@@ -1104,13 +1104,13 @@ static int prepare_single_update(struct reftable_ref_store *refs,
strbuf_addf(err,
_("trying to write ref '%s' with nonexistent object %s"),
u->refname, oid_to_hex(&u->new_oid));
- return -1;
+ return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE;
}
if (o->type != OBJ_COMMIT && is_branch(u->refname)) {
strbuf_addf(err, _("trying to write non-commit object %s to branch '%s'"),
oid_to_hex(&u->new_oid), u->refname);
- return -1;
+ return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE;
}
}
@@ -1134,7 +1134,7 @@ static int prepare_single_update(struct reftable_ref_store *refs,
_("multiple updates for 'HEAD' (including one "
"via its referent '%s') are not allowed"),
u->refname);
- return TRANSACTION_NAME_CONFLICT;
+ return REF_TRANSACTION_ERROR_NAME_CONFLICT;
}
ref_transaction_add_update(
@@ -1147,7 +1147,7 @@ static int prepare_single_update(struct reftable_ref_store *refs,
ret = reftable_backend_read_ref(be, rewritten_ref,
¤t_oid, referent, &u->type);
if (ret < 0)
- return ret;
+ return REF_TRANSACTION_ERROR_GENERIC;
if (ret > 0 && !ref_update_expects_existing_old_ref(u)) {
/*
* The reference does not exist, and we either have no
@@ -1168,7 +1168,7 @@ static int prepare_single_update(struct reftable_ref_store *refs,
ret = queue_transaction_update(refs, tx_data, u,
¤t_oid, err);
if (ret)
- return ret;
+ return REF_TRANSACTION_ERROR_GENERIC;
}
return 0;
@@ -1180,7 +1180,7 @@ static int prepare_single_update(struct reftable_ref_store *refs,
"unable to resolve reference '%s'"),
ref_update_original_update_refname(u), u->refname);
- return -1;
+ return REF_TRANSACTION_ERROR_NONEXISTENT_REF;
}
if (u->type & REF_ISSYMREF) {
@@ -1196,7 +1196,7 @@ static int prepare_single_update(struct reftable_ref_store *refs,
if (u->flags & REF_HAVE_OLD && !resolved) {
strbuf_addf(err, _("cannot lock ref '%s': "
"error reading reference"), u->refname);
- return -1;
+ return REF_TRANSACTION_ERROR_GENERIC;
}
} else {
struct ref_update *new_update;
@@ -1211,7 +1211,7 @@ static int prepare_single_update(struct reftable_ref_store *refs,
_("multiple updates for '%s' (including one "
"via symref '%s') are not allowed"),
referent->buf, u->refname);
- return TRANSACTION_NAME_CONFLICT;
+ return REF_TRANSACTION_ERROR_NAME_CONFLICT;
}
/*
@@ -1255,31 +1255,32 @@ static int prepare_single_update(struct reftable_ref_store *refs,
"but is a regular ref"),
ref_update_original_update_refname(u),
u->old_target);
- return -1;
+ return REF_TRANSACTION_ERROR_EXPECTED_SYMREF;
}
- if (ref_update_check_old_target(referent->buf, u, err)) {
- return -1;
- }
+ ret = ref_update_check_old_target(referent->buf, u, err);
+ if (ret)
+ return ret;
} else if ((u->flags & REF_HAVE_OLD) && !oideq(¤t_oid, &u->old_oid)) {
if (is_null_oid(&u->old_oid)) {
strbuf_addf(err, _("cannot lock ref '%s': "
"reference already exists"),
ref_update_original_update_refname(u));
- return TRANSACTION_CREATE_EXISTS;
- }
- else if (is_null_oid(¤t_oid))
+ return REF_TRANSACTION_ERROR_CREATE_EXISTS;
+ } else if (is_null_oid(¤t_oid)) {
strbuf_addf(err, _("cannot lock ref '%s': "
"reference is missing but expected %s"),
ref_update_original_update_refname(u),
oid_to_hex(&u->old_oid));
- else
+ return REF_TRANSACTION_ERROR_NONEXISTENT_REF;
+ } else {
strbuf_addf(err, _("cannot lock ref '%s': "
"is at %s but expected %s"),
ref_update_original_update_refname(u),
oid_to_hex(¤t_oid),
oid_to_hex(&u->old_oid));
- return TRANSACTION_NAME_CONFLICT;
+ return REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE;
+ }
}
/*
@@ -1296,8 +1297,8 @@ static int prepare_single_update(struct reftable_ref_store *refs,
if ((u->type & REF_ISSYMREF) ||
(u->flags & REF_LOG_ONLY) ||
(u->flags & REF_HAVE_NEW && !oideq(¤t_oid, &u->new_oid)))
- return queue_transaction_update(refs, tx_data, u,
- ¤t_oid, err);
+ if (queue_transaction_update(refs, tx_data, u, ¤t_oid, err))
+ return REF_TRANSACTION_ERROR_GENERIC;
return 0;
}
@@ -1385,7 +1386,6 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
transaction->state = REF_TRANSACTION_PREPARED;
done:
- assert(ret != REFTABLE_API_ERROR);
if (ret < 0) {
free_transaction_data(tx_data);
transaction->state = REF_TRANSACTION_CLOSED;
--
2.48.1
next prev parent reply other threads:[~2025-03-20 11:44 UTC|newest]
Thread overview: 147+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-07 7:34 [PATCH 0/6] refs: introduce support for partial reference transactions Karthik Nayak
2025-02-07 7:34 ` [PATCH 1/6] refs/files: remove duplicate check in `split_symref_update()` Karthik Nayak
2025-02-07 16:12 ` Patrick Steinhardt
2025-02-11 6:35 ` Karthik Nayak
2025-02-07 7:34 ` [PATCH 2/6] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-02-07 16:12 ` Patrick Steinhardt
2025-02-11 10:33 ` Karthik Nayak
2025-02-07 7:34 ` [PATCH 3/6] refs/files: remove duplicate duplicates check Karthik Nayak
2025-02-07 16:12 ` Patrick Steinhardt
2025-02-07 7:34 ` [PATCH 4/6] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-02-07 7:34 ` [PATCH 5/6] refs: implement partial reference transaction support Karthik Nayak
2025-02-07 16:12 ` Patrick Steinhardt
2025-02-21 10:33 ` Karthik Nayak
2025-02-07 7:34 ` [PATCH 6/6] update-ref: add --allow-partial flag for stdin mode Karthik Nayak
2025-02-07 16:12 ` Patrick Steinhardt
2025-02-21 11:45 ` Karthik Nayak
2025-02-11 17:03 ` [PATCH 0/6] refs: introduce support for partial reference transactions Phillip Wood
2025-02-11 17:40 ` Phillip Wood
2025-02-12 12:36 ` Karthik Nayak
2025-02-12 12:34 ` Karthik Nayak
2025-02-19 14:34 ` Phillip Wood
2025-02-19 15:10 ` Patrick Steinhardt
2025-02-21 11:50 ` Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 0/7] " Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 1/7] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 2/7] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 3/7] refs/files: remove duplicate duplicates check Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 4/7] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 5/7] refs: introduce enum-based transaction error types Karthik Nayak
2025-02-25 11:08 ` Patrick Steinhardt
2025-03-03 20:12 ` Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 6/7] refs: implement partial reference transaction support Karthik Nayak
2025-02-25 11:07 ` Patrick Steinhardt
2025-03-03 20:17 ` Karthik Nayak
2025-02-25 14:57 ` Phillip Wood
2025-03-03 20:21 ` Karthik Nayak
2025-03-04 10:31 ` Phillip Wood
2025-03-05 14:20 ` Karthik Nayak
2025-02-25 9:29 ` [PATCH v2 7/7] update-ref: add --allow-partial flag for stdin mode Karthik Nayak
2025-02-25 11:08 ` Patrick Steinhardt
2025-03-03 20:22 ` Karthik Nayak
2025-02-25 14:59 ` Phillip Wood
2025-03-03 20:34 ` Karthik Nayak
2025-03-05 17:38 ` [PATCH v3 0/8] refs: introduce support for partial reference transactions Karthik Nayak
2025-03-05 17:38 ` [PATCH v3 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-03-05 21:20 ` Junio C Hamano
2025-03-06 9:13 ` Karthik Nayak
2025-03-05 17:38 ` [PATCH v3 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-03-05 21:56 ` Junio C Hamano
2025-03-06 9:46 ` Karthik Nayak
2025-03-05 17:38 ` [PATCH v3 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-03-05 17:38 ` [PATCH v3 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-03-05 17:39 ` [PATCH v3 5/8] refs: introduce enum-based transaction error types Karthik Nayak
2025-03-05 17:39 ` [PATCH v3 6/8] refs: implement partial reference transaction support Karthik Nayak
2025-03-07 19:50 ` Jeff King
2025-03-07 20:46 ` Junio C Hamano
2025-03-07 20:48 ` Junio C Hamano
2025-03-07 21:05 ` Karthik Nayak
2025-03-07 22:54 ` [PATCH] config.mak.dev: enable -Wunreachable-code Jeff King
2025-03-07 23:28 ` Junio C Hamano
2025-03-08 3:23 ` Jeff King
2025-03-10 15:40 ` Junio C Hamano
2025-03-10 16:04 ` Jeff King
2025-03-10 18:50 ` Junio C Hamano
2025-03-14 16:10 ` Jeff King
2025-03-14 16:13 ` Jeff King
2025-03-14 17:27 ` Junio C Hamano
2025-03-14 17:40 ` Junio C Hamano
2025-03-14 17:43 ` Patrick Steinhardt
2025-03-14 18:53 ` Jeff King
2025-03-14 19:50 ` Junio C Hamano
2025-03-14 17:15 ` Junio C Hamano
2025-06-03 21:29 ` Mike Hommey
2025-06-03 22:07 ` Junio C Hamano
2025-06-03 22:37 ` Mike Hommey
2025-06-03 23:08 ` Mike Hommey
2025-03-14 21:09 ` [PATCH v2 0/3] -Wunreachable-code Junio C Hamano
2025-03-14 21:09 ` [PATCH v2 1/3] config.mak.dev: enable -Wunreachable-code Junio C Hamano
2025-03-14 21:09 ` [PATCH v2 2/3] run-command: use errno to check for sigfillset() error Junio C Hamano
2025-03-17 21:30 ` Taylor Blau
2025-03-17 23:12 ` Junio C Hamano
2025-03-18 0:36 ` Junio C Hamano
2025-03-14 21:09 ` [PATCH v2 3/3] git-compat-util: add NOT_A_CONST macro and use it in atfork_prepare() Junio C Hamano
2025-03-14 22:29 ` Junio C Hamano
2025-03-17 18:00 ` Jeff King
2025-03-17 23:53 ` [PATCH v3 0/3] -Wunreachable-code Junio C Hamano
2025-03-17 23:53 ` [PATCH v3 1/3] run-command: use errno to check for sigfillset() error Junio C Hamano
2025-03-17 23:53 ` [PATCH v3 2/3] git-compat-util: add NOT_CONSTANT macro and use it in atfork_prepare() Junio C Hamano
2025-03-18 0:20 ` Jeff King
2025-03-18 0:28 ` Junio C Hamano
2025-03-18 22:04 ` Calvin Wan
2025-03-18 22:26 ` Calvin Wan
2025-03-18 23:55 ` Junio C Hamano
2025-03-17 23:53 ` [PATCH v3 3/3] config.mak.dev: enable -Wunreachable-code Junio C Hamano
2025-03-18 0:18 ` [PATCH v3 0/3] -Wunreachable-code Jeff King
2025-03-07 21:02 ` [PATCH v3 6/8] refs: implement partial reference transaction support Karthik Nayak
2025-03-07 19:57 ` Jeff King
2025-03-07 21:07 ` Karthik Nayak
2025-03-05 17:39 ` [PATCH v3 7/8] refs: support partial update rejections during F/D checks Karthik Nayak
2025-03-05 17:39 ` [PATCH v3 8/8] update-ref: add --allow-partial flag for stdin mode Karthik Nayak
2025-03-05 19:28 ` [PATCH v3 0/8] refs: introduce support for partial reference transactions Junio C Hamano
2025-03-06 9:06 ` Karthik Nayak
2025-03-20 11:43 ` [PATCH v4 0/8] refs: introduce support for batched reference updates Karthik Nayak
2025-03-20 11:43 ` [PATCH v4 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-03-20 11:43 ` [PATCH v4 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-03-20 11:43 ` [PATCH v4 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-03-20 11:43 ` [PATCH v4 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-03-20 11:44 ` Karthik Nayak [this message]
2025-03-20 20:26 ` [PATCH v4 5/8] refs: introduce enum-based transaction error types Patrick Steinhardt
2025-03-24 14:50 ` Karthik Nayak
2025-03-25 12:31 ` Patrick Steinhardt
2025-03-20 11:44 ` [PATCH v4 6/8] refs: implement batch reference update support Karthik Nayak
2025-03-20 20:26 ` Patrick Steinhardt
2025-03-24 14:54 ` Karthik Nayak
2025-03-20 11:44 ` [PATCH v4 7/8] refs: support rejection in batch updates during F/D checks Karthik Nayak
2025-03-24 13:08 ` Patrick Steinhardt
2025-03-24 17:48 ` Karthik Nayak
2025-03-25 12:31 ` Patrick Steinhardt
2025-03-20 11:44 ` [PATCH v4 8/8] update-ref: add --batch-updates flag for stdin mode Karthik Nayak
2025-03-24 13:08 ` Patrick Steinhardt
2025-03-24 17:51 ` Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 0/8] refs: introduce support for batched reference updates Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 5/8] refs: introduce enum-based transaction error types Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 6/8] refs: implement batch reference update support Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 7/8] refs: support rejection in batch updates during F/D checks Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 8/8] update-ref: add --batch-updates flag for stdin mode Karthik Nayak
2025-03-28 13:00 ` Jean-Noël AVILA
2025-03-29 16:36 ` Junio C Hamano
2025-03-29 18:18 ` Karthik Nayak
2025-03-28 9:24 ` [PATCH v5 0/8] refs: introduce support for batched reference updates Patrick Steinhardt
2025-04-08 8:51 ` [PATCH v6 " Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 5/8] refs: introduce enum-based transaction error types Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 6/8] refs: implement batch reference update support Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 7/8] refs: support rejection in batch updates during F/D checks Karthik Nayak
2025-04-08 8:51 ` [PATCH v6 8/8] update-ref: add --batch-updates flag for stdin mode Karthik Nayak
2025-04-08 15:02 ` Junio C Hamano
2025-04-08 15:26 ` Karthik Nayak
2025-04-08 17:37 ` Junio C Hamano
2025-04-10 11:23 ` 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=20250320-245-partially-atomic-ref-updates-v4-5-3dcc1b311dc9@gmail.com \
--to=karthik.188@gmail.com \
--cc=git@vger.kernel.org \
--cc=jltobler@gmail.com \
--cc=phillip.wood123@gmail.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;
as well as URLs for NNTP newsgroup(s).