On Fri, Apr 12, 2024 at 11:59:07AM +0200, Karthik Nayak wrote: > From: Karthik Nayak > > Add 'symref-update' to allow updates of symbolic refs in a transaction > via the 'git-update-ref' command. The 'symref-update' command takes in a > , which the will be updated to. If the doesn't > exist it will be created. > > It also optionally takes either an or . If the > is provided, it checks to see if the ponints to the > before the update. If is provided it checks to > ensure that it is a regular ref and is the OID before the > update. This by extension also means that this when a zero is > provided, it ensures that the ref didn't exist before. > > This command will also support deref mode, to ensure that we can update > dereferenced regular refs to symrefs. > > Signed-off-by: Karthik Nayak > --- > Documentation/git-update-ref.txt | 6 ++ > builtin/update-ref.c | 49 +++++++++++ > refs.c | 24 ++---- > refs/files-backend.c | 15 ++-- > refs/reftable-backend.c | 7 +- > t/t1400-update-ref.sh | 143 +++++++++++++++++++++++++++++++ > 6 files changed, 220 insertions(+), 24 deletions(-) > > diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt > index a5b1f42728..9710c9bc78 100644 > --- a/Documentation/git-update-ref.txt > +++ b/Documentation/git-update-ref.txt > @@ -65,6 +65,7 @@ performs all modifications together. Specify commands of the form: > create SP SP LF > delete SP [SP ] LF > verify SP [SP ] LF > + symref-update SP SP [SP ( | )] LF > symref-create SP SP LF > symref-delete SP [SP ] LF > symref-verify SP [SP ] LF > @@ -89,6 +90,7 @@ quoting: > create SP NUL NUL > delete SP NUL [] NUL > verify SP NUL [] NUL > + symref-update SP NUL [NUL ( | )] NUL > symref-create SP NUL NUL > symref-delete SP [NUL ] NUL > symref-verify SP [NUL ] NUL > @@ -123,6 +125,10 @@ verify:: > Verify against but do not change it. If > is zero or missing, the ref must not exist. > > +symref-update:: > + Set to after verifying or , > + if given. Can be used to delete or create symrefs too. > + > symref-create:: > Create symbolic ref with after verifying > it does not exist. Can only be used in `no-deref` mode. > diff --git a/builtin/update-ref.c b/builtin/update-ref.c > index 24556a28a8..809c1c7a76 100644 > --- a/builtin/update-ref.c > +++ b/builtin/update-ref.c > @@ -238,6 +238,54 @@ static void parse_cmd_update(struct ref_transaction *transaction, > strbuf_release(&err); > } > > +static void parse_cmd_symref_update(struct ref_transaction *transaction, > + const char *next, const char *end) > +{ > + struct strbuf err = STRBUF_INIT; > + char *refname, *new_ref, *old_ref; > + struct object_id old_oid; > + int have_old = 0; > + > + refname = parse_refname(&next); > + if (!refname) > + die("symref-update: missing "); > + > + new_ref = parse_next_refname(&next); > + if (!new_ref) > + die("symref-update %s: missing ", refname); > + if (read_ref(new_ref, NULL)) > + die("symref-update %s: invalid ", refname); > + > + old_ref = parse_next_refname(&next); > + /* > + * Since the user can also send in an old-oid, we try to parse > + * it as such too. > + */ > + if (old_ref && read_ref(old_ref, NULL)) { > + if (!repo_get_oid(the_repository, old_ref, &old_oid)) { > + old_ref = NULL; > + have_old = 1; > + } else > + die("symref-update %s: invalid or ", refname); > + } So we first try to parse it as a ref, and then as an object ID? Wouldn't it preferable to try it the other way round and first check whether it is a valid object ID? That would likely be cheaper, even though it may be premature optimization. Patrick