summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--refs.c39
-rw-r--r--refs.h14
-rw-r--r--refs/files-backend.c24
3 files changed, 65 insertions, 12 deletions
diff --git a/refs.c b/refs.c
index 782bf1090a..8b3882cff1 100644
--- a/refs.c
+++ b/refs.c
@@ -1207,14 +1207,14 @@ static int transaction_refname_valid(const char *refname,
return 1;
if (is_pseudo_ref(refname)) {
- strbuf_addf(err, _("refusing to update pseudoref '%s'"),
- refname);
+ const char *what = flags & REF_LOG_ONLY ? "reflog for pseudoref" : "pseudoref";
+ strbuf_addf(err, _("refusing to update %s '%s'"), what, refname);
return 0;
} 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);
+ const char *what = flags & REF_LOG_ONLY ? "reflog with bad name" : "ref with bad name";
+ strbuf_addf(err, _("refusing to update %s '%s'"), what, refname);
return 0;
}
@@ -1257,6 +1257,37 @@ int ref_transaction_update(struct ref_transaction *transaction,
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;
+
+ assert(err);
+
+ flags |= REF_LOG_ONLY | REF_NO_DEREF;
+
+ if (!transaction_refname_valid(refname, new_oid, flags, err))
+ return -1;
+
+ 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;
}
diff --git a/refs.h b/refs.h
index a5bedf48cf..b0dfc65ed2 100644
--- a/refs.h
+++ b/refs.h
@@ -728,6 +728,20 @@ int ref_transaction_update(struct ref_transaction *transaction,
struct strbuf *err);
/*
+ * Similar to`ref_transaction_update`, but this function is only for adding
+ * a reflog update. Supports providing custom committer information. The index
+ * field can be utiltized to order updates as desired. When not used, the
+ * updates default to being ordered by refname.
+ */
+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
* null_oid. It is verified that the reference does not exist
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 255fed8354..c11213f520 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3080,10 +3080,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,11 +3094,17 @@ 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, update->committer_info,
- 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,