From: Junio C Hamano Date: Mon, 20 May 2024 18:20:04 +0000 (-0700) Subject: Merge branch 'kn/ref-transaction-symref' X-Git-Tag: v2.46.0-rc0~117 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4beb7a3b066c98d614d402aec32fc87d76206c89;p=thirdparty%2Fgit.git Merge branch 'kn/ref-transaction-symref' Updates to symbolic refs can now be made as a part of ref transaction. * kn/ref-transaction-symref: refs: remove `create_symref` and associated dead code refs: rename `refs_create_symref()` to `refs_update_symref()` refs: use transaction in `refs_create_symref()` refs: add support for transactional symref updates refs: move `original_update_refname` to 'refs.c' refs: support symrefs in 'reference-transaction' hook files-backend: extract out `create_symref_lock()` refs: accept symref values in `ref_transaction_update()` --- 4beb7a3b066c98d614d402aec32fc87d76206c89 diff --cc builtin/checkout.c index 536b894190,2b6166c284..f90a4ca4b7 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@@ -1011,7 -1007,7 +1011,7 @@@ static void update_refs_for_switch(cons describe_detached_head(_("HEAD is now at"), new_branch_info->commit); } } else if (new_branch_info->path) { /* Switch branches. */ - if (refs_create_symref(get_main_ref_store(the_repository), "HEAD", new_branch_info->path, msg.buf) < 0) - if (create_symref("HEAD", new_branch_info->path, msg.buf) < 0) ++ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", new_branch_info->path, msg.buf) < 0) die(_("unable to update HEAD")); if (!opts->quiet) { if (old_branch_info->path && !strcmp(new_branch_info->path, old_branch_info->path)) { @@@ -1472,8 -1464,7 +1472,8 @@@ static int switch_unborn_to_new_branch( if (!opts->new_branch) die(_("You are on a branch yet to be born")); strbuf_addf(&branch_ref, "refs/heads/%s", opts->new_branch); - status = refs_create_symref(get_main_ref_store(the_repository), - status = create_symref("HEAD", branch_ref.buf, "checkout -b"); ++ status = refs_update_symref(get_main_ref_store(the_repository), + "HEAD", branch_ref.buf, "checkout -b"); strbuf_release(&branch_ref); if (!opts->quiet) fprintf(stderr, _("Switched to a new branch '%s'\n"), diff --cc builtin/clone.c index 554b29768c,74ec14542e..23993b905b --- a/builtin/clone.c +++ b/builtin/clone.c @@@ -653,9 -623,9 +653,9 @@@ static void update_remote_refs(const st struct strbuf head_ref = STRBUF_INIT; strbuf_addstr(&head_ref, branch_top); strbuf_addstr(&head_ref, "HEAD"); - if (refs_create_symref(get_main_ref_store(the_repository), head_ref.buf, - if (create_symref(head_ref.buf, - remote_head_points_at->peer_ref->name, - msg) < 0) ++ if (refs_update_symref(get_main_ref_store(the_repository), head_ref.buf, + remote_head_points_at->peer_ref->name, + msg) < 0) die(_("unable to update %s"), head_ref.buf); strbuf_release(&head_ref); } @@@ -667,12 -637,11 +667,12 @@@ static void update_head(const struct re const char *head; if (our && skip_prefix(our->name, "refs/heads/", &head)) { /* Local default branch link */ - if (refs_create_symref(get_main_ref_store(the_repository), "HEAD", our->name, NULL) < 0) - if (create_symref("HEAD", our->name, NULL) < 0) ++ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", our->name, NULL) < 0) die(_("unable to update HEAD")); if (!option_bare) { - update_ref(msg, "HEAD", &our->old_oid, NULL, 0, - UPDATE_REFS_DIE_ON_ERR); + refs_update_ref(get_main_ref_store(the_repository), + msg, "HEAD", &our->old_oid, NULL, 0, + UPDATE_REFS_DIE_ON_ERR); install_branch_config(0, head, remote_name, our->name); } } else if (our) { @@@ -696,7 -663,7 +696,7 @@@ * Unborn head from remote; same as "our" case above except * that we have no ref to update. */ - if (refs_create_symref(get_main_ref_store(the_repository), "HEAD", unborn, NULL) < 0) - if (create_symref("HEAD", unborn, NULL) < 0) ++ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", unborn, NULL) < 0) die(_("unable to update HEAD")); if (!option_bare) install_branch_config(0, head, remote_name, unborn); diff --cc builtin/fast-import.c index 184cfa9f57,6a0b39de32..d1c0243d04 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@@ -1632,11 -1631,10 +1632,11 @@@ static int update_branch(struct branch return -1; } } - transaction = ref_transaction_begin(&err); + transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), + &err); if (!transaction || ref_transaction_update(transaction, b->name, &b->oid, &old_oid, - 0, msg, &err) || + NULL, NULL, 0, msg, &err) || ref_transaction_commit(transaction, &err)) { ref_transaction_free(transaction); error("%s", err.buf); diff --cc builtin/notes.c index a5ce90d9f9,cb011303e6..7f80b3449b --- a/builtin/notes.c +++ b/builtin/notes.c @@@ -981,7 -977,7 +981,7 @@@ static int merge(int argc, const char * die(_("a notes merge into %s is already in-progress at %s"), default_notes_ref(), wt->path); free_worktrees(worktrees); - if (refs_create_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", default_notes_ref(), NULL)) - if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) ++ if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", default_notes_ref(), NULL)) die(_("failed to store link to current notes ref (%s)"), default_notes_ref()); fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s " diff --cc builtin/remote.c index ff70d6835a,8412d12fa5..d52b1c0e10 --- a/builtin/remote.c +++ b/builtin/remote.c @@@ -240,7 -240,7 +240,7 @@@ static int add(int argc, const char **a strbuf_reset(&buf2); strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master); - if (refs_create_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote add")) - if (create_symref(buf.buf, buf2.buf, "remote add")) ++ if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote add")) return error(_("Could not setup master '%s'"), master); } @@@ -845,7 -843,7 +845,7 @@@ static int mv(int argc, const char **ar strbuf_reset(&buf3); strbuf_addf(&buf3, "remote: renamed %s to %s", item->string, buf.buf); - if (refs_create_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, buf3.buf)) - if (create_symref(buf.buf, buf2.buf, buf3.buf)) ++ if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, buf3.buf)) die(_("creating '%s' failed"), buf.buf); display_progress(progress, ++refs_renamed_nr); } @@@ -1421,9 -1415,9 +1421,9 @@@ static int set_head(int argc, const cha if (head_name) { strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name); /* make sure it's valid */ - if (!ref_exists(buf2.buf)) + if (!refs_ref_exists(get_main_ref_store(the_repository), buf2.buf)) result |= error(_("Not a valid ref: %s"), buf2.buf); - else if (refs_create_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote set-head")) - else if (create_symref(buf.buf, buf2.buf, "remote set-head")) ++ else if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote set-head")) result |= error(_("Could not setup %s"), buf.buf); else if (opt_a) printf("%s/HEAD set to %s\n", argv[0], head_name); diff --cc builtin/replace.c index bc2a948c80,7690687b0e..f46ff57691 --- a/builtin/replace.c +++ b/builtin/replace.c @@@ -198,11 -198,10 +198,11 @@@ static int replace_object_oid(const cha return -1; } - transaction = ref_transaction_begin(&err); + transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), + &err); if (!transaction || ref_transaction_update(transaction, ref.buf, repl, &prev, - 0, NULL, &err) || + NULL, NULL, 0, NULL, &err) || ref_transaction_commit(transaction, &err)) res = error("%s", err.buf); diff --cc builtin/symbolic-ref.c index b2b0a41fb6,c9defe4d2e..81abdd170f --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@@ -83,8 -79,7 +83,8 @@@ int cmd_symbolic_ref(int argc, const ch die("Refusing to point HEAD outside of refs/"); if (check_refname_format(argv[1], REFNAME_ALLOW_ONELEVEL) < 0) die("Refusing to set '%s' to invalid ref '%s'", argv[0], argv[1]); - ret = !!refs_create_symref(get_main_ref_store(the_repository), - ret = !!create_symref(argv[0], argv[1], msg); ++ ret = !!refs_update_symref(get_main_ref_store(the_repository), + argv[0], argv[1], msg); break; default: usage_with_options(git_symbolic_ref_usage, options); diff --cc builtin/tag.c index b18eec91ab,40a65fdebc..6e2c0cf342 --- a/builtin/tag.c +++ b/builtin/tag.c @@@ -673,13 -654,13 +673,14 @@@ int cmd_tag(int argc, const char **argv opt.sign = 1; path = git_pathdup("TAG_EDITMSG"); create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, - path); + &trailer_args, path); } - transaction = ref_transaction_begin(&err); + transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), + &err); if (!transaction || ref_transaction_update(transaction, ref.buf, &object, &prev, + NULL, NULL, create_reflog ? REF_FORCE_CREATE_REFLOG : 0, reflog_msg.buf, &err) || ref_transaction_commit(transaction, &err)) { diff --cc refs.c index a26c50a401,fa5471d219..32e91ff740 --- a/refs.c +++ b/refs.c @@@ -2181,21 -2284,36 +2199,29 @@@ int peel_iterated_oid(const struct obje return peel_object(base, peeled) ? -1 : 0; } - int refs_create_symref(struct ref_store *refs, - const char *ref_target, - const char *refs_heads_master, - const char *logmsg) + int refs_update_symref(struct ref_store *refs, const char *ref, + const char *target, const char *logmsg) { - char *msg; - int retval; + struct ref_transaction *transaction; + struct strbuf err = STRBUF_INIT; + int ret = 0; - msg = normalize_reflog_message(logmsg); - retval = refs->be->create_symref(refs, ref_target, refs_heads_master, - msg); - free(msg); - return retval; + transaction = ref_store_transaction_begin(refs, &err); + if (!transaction || + ref_transaction_update(transaction, ref, NULL, NULL, + target, NULL, REF_NO_DEREF, + logmsg, &err) || + ref_transaction_commit(transaction, &err)) { + ret = error("%s", err.buf); + } + + strbuf_release(&err); + if (transaction) + ref_transaction_free(transaction); + + return ret; } -int create_symref(const char *ref_target, const char *refs_heads_master, - const char *logmsg) -{ - return refs_update_symref(get_main_ref_store(the_repository), ref_target, - refs_heads_master, logmsg); -} - int ref_update_reject_duplicates(struct string_list *refnames, struct strbuf *err) { @@@ -2634,3 -2823,43 +2672,38 @@@ int refs_copy_existing_ref(struct ref_s free(msg); return retval; } + -int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg) -{ - return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg); -} - + const char *ref_update_original_update_refname(struct ref_update *update) + { + while (update->parent_update) + update = update->parent_update; + + return update->refname; + } + + int ref_update_has_null_new_value(struct ref_update *update) + { + return !update->new_target && is_null_oid(&update->new_oid); + } + + int ref_update_check_old_target(const char *referent, struct ref_update *update, + struct strbuf *err) + { + if (!update->old_target) + BUG("called without old_target set"); + + if (!strcmp(referent, update->old_target)) + return 0; + + if (!strcmp(referent, "")) + strbuf_addf(err, "verifying symref target: '%s': " + "reference is missing but expected %s", + ref_update_original_update_refname(update), + update->old_target); + else + strbuf_addf(err, "verifying symref target: '%s': " + "is at %s but expected %s", + ref_update_original_update_refname(update), + referent, update->old_target); + return -1; + } diff --cc refs.h index d02dd79ca6,71cc1c58e0..fb419ab2ed --- a/refs.h +++ b/refs.h @@@ -562,9 -603,12 +562,9 @@@ int refs_rename_ref(struct ref_store *r /** copy ref, return 0 on success **/ int refs_copy_existing_ref(struct ref_store *refs, const char *oldref, const char *newref, const char *logmsg); -int copy_existing_ref(const char *oldref, const char *newref, - const char *logmsg); - int refs_create_symref(struct ref_store *refs, const char *refname, + int refs_update_symref(struct ref_store *refs, const char *refname, const char *target, const char *logmsg); -int create_symref(const char *refname, const char *target, const char *logmsg); enum action_on_err { UPDATE_REFS_MSG_ON_ERR, diff --cc refs/reftable-backend.c index 010ef811b6,8f5165c4ba..98cebbcf39 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@@ -1088,18 -1080,35 +1087,35 @@@ static int write_transaction_table(stru (u->flags & REF_FORCE_CREATE_REFLOG || should_write_log(&arg->refs->base, u->refname))) { struct reftable_log_record *log; + int create_reflog = 1; + + if (u->new_target) { + if (!refs_resolve_ref_unsafe(&arg->refs->base, u->new_target, + RESOLVE_REF_READING, &u->new_oid, NULL)) { + /* + * TODO: currently we skip creating reflogs for dangling + * symref updates. It would be nice to capture this as + * zero oid updates however. + */ + create_reflog = 0; + } + } - ALLOC_GROW(logs, logs_nr + 1, logs_alloc); - log = &logs[logs_nr++]; - memset(log, 0, sizeof(*log)); - - fill_reftable_log_record(log, &committer_ident); - log->update_index = ts; - log->refname = xstrdup(u->refname); - memcpy(log->value.update.new_hash, u->new_oid.hash, GIT_MAX_RAWSZ); - memcpy(log->value.update.old_hash, tx_update->current_oid.hash, GIT_MAX_RAWSZ); - log->value.update.message = - xstrndup(u->msg, arg->refs->write_options.block_size / 2); + if (create_reflog) { + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + log = &logs[logs_nr++]; + memset(log, 0, sizeof(*log)); + - fill_reftable_log_record(log); ++ fill_reftable_log_record(log, &committer_ident); + log->update_index = ts; + log->refname = xstrdup(u->refname); + memcpy(log->value.update.new_hash, + u->new_oid.hash, GIT_MAX_RAWSZ); + memcpy(log->value.update.old_hash, + tx_update->current_oid.hash, GIT_MAX_RAWSZ); + log->value.update.message = + xstrndup(u->msg, arg->refs->write_options.block_size / 2); + } } if (u->flags & REF_LOG_ONLY) diff --cc reset.c index 59ebb1f842,d619cb7115..937f11c0f4 --- a/reset.c +++ b/reset.c @@@ -62,19 -60,16 +62,19 @@@ static int update_refs(const struct res reflog_head = msg.buf; } if (!switch_to_branch) - ret = update_ref(reflog_head, "HEAD", oid, head, - detach_head ? REF_NO_DEREF : 0, - UPDATE_REFS_MSG_ON_ERR); + ret = refs_update_ref(get_main_ref_store(the_repository), + reflog_head, "HEAD", oid, head, + detach_head ? REF_NO_DEREF : 0, + UPDATE_REFS_MSG_ON_ERR); else { - ret = update_ref(reflog_branch ? reflog_branch : reflog_head, - switch_to_branch, oid, NULL, 0, - UPDATE_REFS_MSG_ON_ERR); + ret = refs_update_ref(get_main_ref_store(the_repository), + reflog_branch ? reflog_branch : reflog_head, + switch_to_branch, oid, NULL, 0, + UPDATE_REFS_MSG_ON_ERR); if (!ret) - ret = refs_create_symref(get_main_ref_store(the_repository), - ret = create_symref("HEAD", switch_to_branch, - reflog_head); ++ ret = refs_update_symref(get_main_ref_store(the_repository), + "HEAD", switch_to_branch, + reflog_head); } if (!ret && run_hook) run_hooks_l("post-checkout", diff --cc sequencer.c index 19421cbdb8,af1b25692b..dbd60d79b9 --- a/sequencer.c +++ b/sequencer.c @@@ -5043,7 -4976,7 +5044,7 @@@ cleanup_head_ref } msg = reflog_message(opts, "finish", "returning to %s", head_ref.buf); - if (refs_create_symref(get_main_ref_store(the_repository), "HEAD", head_ref.buf, msg)) { - if (create_symref("HEAD", head_ref.buf, msg)) { ++ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", head_ref.buf, msg)) { res = error(_("could not update HEAD to %s"), head_ref.buf); goto cleanup_head_ref; diff --cc setup.c index c7d3375645,f4b32f76e3..9247cded6a --- a/setup.c +++ b/setup.c @@@ -2067,7 -2001,7 +2067,7 @@@ void create_reference_database(unsigne die(_("invalid initial branch name: '%s'"), initial_branch); - if (refs_create_symref(get_main_ref_store(the_repository), "HEAD", ref, NULL) < 0) - if (create_symref("HEAD", ref, NULL) < 0) ++ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", ref, NULL) < 0) exit(1); free(ref); }