Show changes to 5 files +122 −49
refs.c, refs.h, refs/files-backend.c, refs/refs-internal.h, refs/reftable-backend.c
diff --git a/refs.c b/refs.c
index 732c236a3fd0cf324cc172b48d3d54f6dbadf4a4..602a65873181a90751def525608a7fa7bea59562 100644
--- a/refs.c
+++ b/refs.c
@@ -1160,13 +1160,15 @@ void ref_transaction_free(struct ref_transaction *transaction)
free(transaction);
}
-struct ref_update *ref_transaction_add_update(
- struct ref_transaction *transaction,
- const char *refname, unsigned int flags,
- const struct object_id *new_oid,
- const struct object_id *old_oid,
- const char *new_target, const char *old_target,
- const char *msg)
+struct ref_update *ref_transaction_add_update(struct ref_transaction *transaction,
+ const char *refname,
+ unsigned int flags,
+ const struct object_id *new_oid,
+ const struct object_id *old_oid,
+ const char *new_target,
+ const char *old_target,
+ const char *committer_info,
+ const char *msg)
{
struct ref_update *update;
@@ -1190,8 +1192,15 @@ struct ref_update *ref_transaction_add_update(
oidcpy(&update->new_oid, new_oid);
if ((flags & REF_HAVE_OLD) && old_oid)
oidcpy(&update->old_oid, old_oid);
- if (!(flags & REF_SKIP_CREATE_REFLOG))
+ if (!(flags & REF_SKIP_CREATE_REFLOG)) {
+ if (committer_info) {
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_addstr(&sb, committer_info);
+ update->committer_info = strbuf_detach(&sb, NULL);
+ }
+
update->msg = normalize_reflog_message(msg);
+ }
return update;
}
@@ -1199,20 +1208,29 @@ struct ref_update *ref_transaction_add_update(
static int transaction_refname_verification(const char *refname,
const struct object_id *new_oid,
unsigned int flags,
+ unsigned int reflog,
struct strbuf *err)
{
if (flags & REF_SKIP_REFNAME_VERIFICATION)
return 0;
if (is_pseudo_ref(refname)) {
- strbuf_addf(err, _("refusing to update pseudoref '%s'"),
- refname);
+ if (reflog)
+ strbuf_addf(err, _("refusing to update reflog for pseudoref '%s'"),
+ refname);
+ else
+ strbuf_addf(err, _("refusing to update pseudoref '%s'"),
+ refname);
return -1;
} else if ((new_oid && !is_null_oid(new_oid)) ?
check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
!refname_is_safe(refname)) {
- strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
- refname);
+ if (reflog)
+ strbuf_addf(err, _("refusing to update reflog with bad name '%s'"),
+ refname);
+ else
+ strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
+ refname);
return -1;
}
@@ -1238,7 +1256,7 @@ int ref_transaction_update(struct ref_transaction *transaction,
return -1;
}
- ret = transaction_refname_verification(refname, new_oid, flags, err);
+ ret = transaction_refname_verification(refname, new_oid, flags, 0, err);
if (ret)
return ret;
@@ -1255,18 +1273,47 @@ int ref_transaction_update(struct ref_transaction *transaction,
flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
flags |= (new_target ? REF_HAVE_NEW : 0) | (old_target ? REF_HAVE_OLD : 0);
- ref_transaction_add_update(transaction, refname, flags,
- new_oid, old_oid, new_target,
- old_target, msg);
+ ref_transaction_add_update(transaction, refname, flags, new_oid,
+ old_oid, new_target, old_target, NULL, msg);
+ return 0;
+}
+
+int ref_transaction_update_reflog(struct ref_transaction *transaction,
+ const char *refname,
+ const struct object_id *new_oid,
+ const struct object_id *old_oid,
+ const char *committer_info, unsigned int flags,
+ const char *msg, unsigned int index,
+ struct strbuf *err)
+{
+ struct ref_update *update;
+ int ret;
+
+ assert(err);
+
+ ret = transaction_refname_verification(refname, new_oid, flags, 1, err);
+ if (ret)
+ return ret;
+
+ flags |= REF_LOG_ONLY | REF_NO_DEREF;
+
+ update = ref_transaction_add_update(transaction, refname, flags,
+ new_oid, old_oid, NULL, NULL,
+ committer_info, msg);
+ /*
+ * While we do set the old_oid value, we unset the flag to skip
+ * old_oid verification which only makes sense for refs.
+ */
+ update->flags &= ~REF_HAVE_OLD;
+ update->index = index;
+
return 0;
}
int ref_transaction_create(struct ref_transaction *transaction,
- const char *refname,
- const struct object_id *new_oid,
- const char *new_target,
- unsigned int flags, const char *msg,
- struct strbuf *err)
+ const char *refname, const struct object_id *new_oid,
+ const char *new_target, unsigned int flags,
+ const char *msg, struct strbuf *err)
{
if (new_oid && new_target)
BUG("create called with both new_oid and new_target set");
diff --git a/refs.h b/refs.h
index a5bedf48cf6de91005a7e8d0bf58ca98350397a6..b86d2cd87be33f7bb1b31fce711d6c7c8d9491c9 100644
--- a/refs.h
+++ b/refs.h
@@ -727,6 +727,18 @@ int ref_transaction_update(struct ref_transaction *transaction,
unsigned int flags, const char *msg,
struct strbuf *err);
+/*
+ * Similar to `ref_transaction_update`, but this function is only for adding
+ * a reflog updates. Supports providing custom committer information.
+ */
+int ref_transaction_update_reflog(struct ref_transaction *transaction,
+ const char *refname,
+ const struct object_id *new_oid,
+ const struct object_id *old_oid,
+ const char *committer_info, unsigned int flags,
+ const char *msg, unsigned int index,
+ struct strbuf *err);
+
/*
* Add a reference creation to transaction. new_oid is the value that
* the reference should have after the update; it must not be
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 9c929c1ac33bc62a75620e684a809d46b574f1c6..32975e0fd7a03ab8ddf99c0a68af99921d3f5090 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1268,10 +1268,10 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
transaction = ref_store_transaction_begin(&refs->base, 0, &err);
if (!transaction)
goto cleanup;
- ref_transaction_add_update(
- transaction, r->name,
- REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,
- null_oid(), &r->oid, NULL, NULL, NULL);
+ ref_transaction_add_update(transaction, r->name,
+ REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD |
+ REF_IS_PRUNING, null_oid(), &r->oid, NULL,
+ NULL, NULL, NULL);
if (ref_transaction_commit(transaction, &err))
goto cleanup;
@@ -2418,7 +2418,7 @@ static int split_head_update(struct ref_update *update,
transaction, "HEAD",
update->flags | REF_LOG_ONLY | REF_NO_DEREF,
&update->new_oid, &update->old_oid,
- NULL, NULL, update->msg);
+ NULL, NULL, update->committer_info, update->msg);
/*
* Add "HEAD". This insertion is O(N) in the transaction
@@ -2482,7 +2482,8 @@ static int split_symref_update(struct ref_update *update,
transaction, referent, new_flags,
update->new_target ? NULL : &update->new_oid,
update->old_target ? NULL : &update->old_oid,
- update->new_target, update->old_target, update->msg);
+ update->new_target, update->old_target, NULL,
+ update->msg);
new_update->parent_update = update;
@@ -2911,11 +2912,11 @@ static int files_transaction_prepare(struct ref_store *ref_store,
packed_transaction;
}
- ref_transaction_add_update(
- packed_transaction, update->refname,
- REF_HAVE_NEW | REF_NO_DEREF,
- &update->new_oid, NULL,
- NULL, NULL, NULL);
+ ref_transaction_add_update(packed_transaction,
+ update->refname,
+ REF_HAVE_NEW | REF_NO_DEREF,
+ &update->new_oid, NULL, NULL,
+ NULL, NULL, NULL);
}
}
@@ -3080,10 +3081,12 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
}
/*
- * packed-refs don't support symbolic refs and root refs, so we
- * have to queue these references via the loose transaction.
+ * packed-refs don't support symbolic refs, root refs and reflogs,
+ * so we have to queue these references via the loose transaction.
*/
- if (update->new_target || is_root_ref(update->refname)) {
+ if (update->new_target ||
+ is_root_ref(update->refname) ||
+ (update->flags & REF_LOG_ONLY)) {
if (!loose_transaction) {
loose_transaction = ref_store_transaction_begin(&refs->base, 0, err);
if (!loose_transaction) {
@@ -3092,15 +3095,22 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
}
}
- ref_transaction_add_update(loose_transaction, update->refname,
- update->flags & ~REF_HAVE_OLD,
- update->new_target ? NULL : &update->new_oid, NULL,
- update->new_target, NULL, NULL);
+ if (update->flags & REF_LOG_ONLY)
+ ref_transaction_add_update(loose_transaction, update->refname,
+ update->flags, &update->new_oid,
+ &update->old_oid, NULL, NULL,
+ update->committer_info, update->msg);
+ else
+ ref_transaction_add_update(loose_transaction, update->refname,
+ update->flags & ~REF_HAVE_OLD,
+ update->new_target ? NULL : &update->new_oid, NULL,
+ update->new_target, NULL, update->committer_info,
+ NULL);
} else {
ref_transaction_add_update(packed_transaction, update->refname,
update->flags & ~REF_HAVE_OLD,
&update->new_oid, &update->old_oid,
- NULL, NULL, NULL);
+ NULL, NULL, update->committer_info, NULL);
}
}
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index f5c733d099f0c6f1076a25f4f77d9d5eb345ec87..82c1387d1e6ab3658b31fe99c95f98645ff1ebf1 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -156,13 +156,15 @@ int ref_update_reject_duplicates(struct string_list *refnames,
* dereferenced if the REF_HAVE_NEW and REF_HAVE_OLD bits,
* respectively, are set in flags.
*/
-struct ref_update *ref_transaction_add_update(
- struct ref_transaction *transaction,
- const char *refname, unsigned int flags,
- const struct object_id *new_oid,
- const struct object_id *old_oid,
- const char *new_target, const char *old_target,
- const char *msg);
+struct ref_update *ref_transaction_add_update(struct ref_transaction *transaction,
+ const char *refname,
+ unsigned int flags,
+ const struct object_id *new_oid,
+ const struct object_id *old_oid,
+ const char *new_target,
+ const char *old_target,
+ const char *committer_info,
+ const char *msg);
/*
* Transaction states.
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index c008f20be719fec3af6a8f81c821cb9c263764d7..b2e3ba877de9e59fea5a4d066eb13e60ef22a32b 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1078,7 +1078,8 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
new_update = ref_transaction_add_update(
transaction, "HEAD",
u->flags | REF_LOG_ONLY | REF_NO_DEREF,
- &u->new_oid, &u->old_oid, NULL, NULL, u->msg);
+ &u->new_oid, &u->old_oid, NULL, NULL, NULL,
+ u->msg);
string_list_insert(&affected_refnames, new_update->refname);
}
@@ -1161,7 +1162,8 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
transaction, referent.buf, new_flags,
u->new_target ? NULL : &u->new_oid,
u->old_target ? NULL : &u->old_oid,
- u->new_target, u->old_target, u->msg);
+ u->new_target, u->old_target,
+ u->committer_info, u->msg);
new_update->parent_update = u;