Message ID | 20241213-320-git-refs-migrate-reflogs-v2-6-f28312cdb6c0@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | refs: add reflog support to `git refs migrate` | expand |
On Fri, Dec 13, 2024 at 11:36 AM Karthik Nayak <karthik.188@gmail.com> wrote: > +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); > + > + if (!transaction_refname_valid(refname, new_oid, flags, 1, err)) > + return -1; > + > + flags |= REF_LOG_ONLY | REF_NO_DEREF; If we could switch the above lines like this: flags |= REF_LOG_ONLY | REF_NO_DEREF; if (!transaction_refname_valid(refname, new_oid, flags, 1, err)) return -1; maybe we wouldn't need transaction_refname_valid() to take an 'unsigned int reflog' argument and we could instead use 'flags & REF_LOG_ONLY' inside that function? > + 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; > }
On Fri, Dec 13, 2024 at 11:36:51AM +0100, Karthik Nayak wrote: > diff --git a/refs.h b/refs.h > index a5bedf48cf6de91005a7e8d0bf58ca98350397a6..67f8b3eef3f2101409e5cc6eb2241d99e9f7d95c 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 update. 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); > + Nit: it would be great to explain what the index does in the doc, as it is completely non-obvious. Patrick
Christian Couder <christian.couder@gmail.com> writes: > On Fri, Dec 13, 2024 at 11:36 AM Karthik Nayak <karthik.188@gmail.com> wrote: > >> +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); >> + >> + if (!transaction_refname_valid(refname, new_oid, flags, 1, err)) >> + return -1; >> + >> + flags |= REF_LOG_ONLY | REF_NO_DEREF; > > If we could switch the above lines like this: > > flags |= REF_LOG_ONLY | REF_NO_DEREF; > > if (!transaction_refname_valid(refname, new_oid, flags, 1, err)) > return -1; > > maybe we wouldn't need transaction_refname_valid() to take an > 'unsigned int reflog' argument and we could instead use 'flags & > REF_LOG_ONLY' inside that function? > The issue is the that this changes existing behavior, since `ref_transaction_update()` can also be called with the `REF_LOG_ONLY` flag set. But, I think it is a worthwhile change, because earlier even for reflog updates we would show 'refusing to update ref ...' as the message. I'll add this in and also make a note in the commit message. Thanks >> + 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.c b/refs.c index 428ca256f3e5860554e9a7fa42a8368bb2689b31..9f539369bc94a25594adc3e95847f2fe72f58a08 100644 --- a/refs.c +++ b/refs.c @@ -1203,20 +1203,21 @@ struct ref_update *ref_transaction_add_update( static int transaction_refname_valid(const char *refname, const struct object_id *new_oid, - unsigned int flags, struct strbuf *err) + unsigned int flags, unsigned int reflog, + struct strbuf *err) { if (flags & REF_SKIP_REFNAME_VERIFICATION) return 1; if (is_pseudo_ref(refname)) { - strbuf_addf(err, _("refusing to update pseudoref '%s'"), - refname); + const char *what = reflog ? "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 = reflog ? "reflog with bad name" : "ref with bad name"; + strbuf_addf(err, _("refusing to update %s '%s'"), what, refname); return 0; } @@ -1240,7 +1241,7 @@ int ref_transaction_update(struct ref_transaction *transaction, return -1; } - if (!transaction_refname_valid(refname, new_oid, flags, err)) + if (!transaction_refname_valid(refname, new_oid, flags, 0, err)) return -1; if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS) @@ -1259,6 +1260,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); + + if (!transaction_refname_valid(refname, new_oid, flags, 1, err)) + return -1; + + 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; } diff --git a/refs.h b/refs.h index a5bedf48cf6de91005a7e8d0bf58ca98350397a6..67f8b3eef3f2101409e5cc6eb2241d99e9f7d95c 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 update. 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 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,
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. 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 | 44 ++++++++++++++++++++++++++++++++++++++------ refs.h | 12 ++++++++++++ refs/files-backend.c | 24 ++++++++++++++++-------- 3 files changed, 66 insertions(+), 14 deletions(-)