diff mbox series

[v4,6/8] refs: introduce the `ref_transaction_update_reflog` function

Message ID 20241216-320-git-refs-migrate-reflogs-v4-6-d7cd3f197453@gmail.com (mailing list archive)
State Accepted
Commit 84675fa2717e08b39bf810eb9a439068ac915dfb
Headers show
Series refs: add reflog support to `git refs migrate` | expand

Commit Message

Karthik Nayak Dec. 16, 2024, 4:44 p.m. UTC
Introduce a new function `ref_transaction_update_reflog`, for clients to
add a reflog update to a transaction. While the existing function
`ref_transaction_update` also allows clients to add a reflog entry, this
function does a few things more, It:
  - Enforces that only a reflog entry is added and does not update the
  ref itself.
  - Allows the users to also provide the committer information. This
  means clients can add reflog entries with custom committer
  information.

The `transaction_refname_valid()` function also modifies the error
message selectively based on the type of the update. This change also
affects reflog updates which go through `ref_transaction_update()`.

A follow up commit will utilize this function to add reflog support to
`git refs migrate`.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
---
 refs.c               | 39 +++++++++++++++++++++++++++++++++++----
 refs.h               | 14 ++++++++++++++
 refs/files-backend.c | 24 ++++++++++++++++--------
 3 files changed, 65 insertions(+), 12 deletions(-)

Comments

Toon Claes Dec. 19, 2024, 7:32 p.m. UTC | #1
Karthik Nayak <karthik.188@gmail.com> writes:

> Introduce a new function `ref_transaction_update_reflog`, for clients to
> add a reflog update to a transaction. While the existing function
> `ref_transaction_update` also allows clients to add a reflog entry, this
> function does a few things more, It:
>   - Enforces that only a reflog entry is added and does not update the
>   ref itself.
>   - Allows the users to also provide the committer information. This
>   means clients can add reflog entries with custom committer
>   information.
>
> The `transaction_refname_valid()` function also modifies the error
> message selectively based on the type of the update. This change also
> affects reflog updates which go through `ref_transaction_update()`.
>
> A follow up commit will utilize this function to add reflog support to
> `git refs migrate`.
>
> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
> ---
>  refs.c               | 39 +++++++++++++++++++++++++++++++++++----
>  refs.h               | 14 ++++++++++++++
>  refs/files-backend.c | 24 ++++++++++++++++--------
>  3 files changed, 65 insertions(+), 12 deletions(-)
>
> diff --git a/refs.c b/refs.c
> index 782bf1090af65196263a3c35ed18d878bb4f2967..8b3882cff17e5e3b0376f75654e32f81a23e5cb2 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";

These strings are not localized.

> +		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";

Also these strings are not localized.
Junio C Hamano Dec. 19, 2024, 8:25 p.m. UTC | #2
Toon Claes <toon@iotcl.com> writes:

>> +		const char *what = flags & REF_LOG_ONLY ? "reflog for pseudoref" : "pseudoref";
>
> These strings are not localized.
>
>> +		strbuf_addf(err, _("refusing to update %s '%s'"), what, refname);
>>  		return 0;

And the structure forces sentence logo.  If "reflog for pseudoref"
were masculine and "pseudoref" were feminine in a language where the
verb "update" conjugates differently based on its object, the
resulting construction cannot be translated.  Rather, we'd need to
do something uglier like this:

	const char *refusal_msg;
	if (flag & REF_LOG_ONLY)
		refusal_msg = _("refusing to update reflog for pseudoref '%s'");
	else
		refusal_msg = _("refusing to update pseudoref '%s'");
	...
	strbuf_addf(err, refusal_msg, refname);
Karthik Nayak Dec. 20, 2024, 10:55 a.m. UTC | #3
Junio C Hamano <gitster@pobox.com> writes:

> Toon Claes <toon@iotcl.com> writes:
>
>>> +		const char *what = flags & REF_LOG_ONLY ? "reflog for pseudoref" : "pseudoref";
>>
>> These strings are not localized.
>>
>>> +		strbuf_addf(err, _("refusing to update %s '%s'"), what, refname);
>>>  		return 0;
>
> And the structure forces sentence logo.  If "reflog for pseudoref"
> were masculine and "pseudoref" were feminine in a language where the
> verb "update" conjugates differently based on its object, the
> resulting construction cannot be translated.  Rather, we'd need to
> do something uglier like this:
>
> 	const char *refusal_msg;
> 	if (flag & REF_LOG_ONLY)
> 		refusal_msg = _("refusing to update reflog for pseudoref '%s'");
> 	else
> 		refusal_msg = _("refusing to update pseudoref '%s'");
> 	...
> 	strbuf_addf(err, refusal_msg, refname);

Indeed. Will add this in. I think its better to prioritize good
translation here.
diff mbox series

Patch

diff --git a/refs.c b/refs.c
index 782bf1090af65196263a3c35ed18d878bb4f2967..8b3882cff17e5e3b0376f75654e32f81a23e5cb2 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 a5bedf48cf6de91005a7e8d0bf58ca98350397a6..b0dfc65ed2e59c4b66967840339f81e7746a96d3 100644
--- a/refs.h
+++ b/refs.h
@@ -727,6 +727,20 @@  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 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
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 255fed8354cae982f785b1b85340e2a1eeecf2a6..c11213f52065bcf2fa7612df8f9500692ee2d02c 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,