Git development
 help / color / mirror / Atom feed
From: Maciej Ciemborowicz <maciej.ciemborowicz@gmail.com>
To: git@vger.kernel.org
Cc: Patrick Steinhardt <ps@pks.im>,
	Junio C Hamano <gitster@pobox.com>,
	Karthik Nayak <karthik.188@gmail.com>
Subject: [PATCH v3 4/4] refs: remove backend-specific copy and rename callbacks
Date: Wed, 07 Oct 2026 20:05:17 +0200	[thread overview]
Message-ID: <83fa644fb3dbf1807e232cac22f9dd7528b766c1.1791395643.git.maciej.ciemborowicz@gmail.com> (raw)
In-Reply-To: <cover.1791395643.git.maciej.ciemborowicz@gmail.com>

Copy and rename now use the transaction API for refs and reflogs. Remove
the unused callbacks, backend implementations, and their private
helpers. The files backend no longer needs a shared temporary reflog
name or rollback writes that reconstruct previously visible refs and
logs.

Signed-off-by: Maciej Ciemborowicz <maciej.ciemborowicz@gmail.com>
---
 refs/debug.c            |  24 ---
 refs/files-backend.c    | 334 ----------------------------------------
 refs/packed-backend.c   |   2 -
 refs/refs-internal.h    |   9 --
 refs/reftable-backend.c | 287 ----------------------------------
 5 files changed, 656 deletions(-)

diff --git a/refs/debug.c b/refs/debug.c
index 639db0f26e..b4991f71ae 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -143,28 +143,6 @@ static int debug_optimize_required(struct ref_store *ref_store,
 	return res;
 }
 
-static int debug_rename_ref(struct ref_store *ref_store, const char *oldref,
-			    const char *newref, const char *logmsg)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res = drefs->refs->be->rename_ref(drefs->refs, oldref, newref,
-					      logmsg);
-	trace_printf_key(&trace_refs, "rename_ref: %s -> %s \"%s\": %d\n", oldref, newref,
-		logmsg, res);
-	return res;
-}
-
-static int debug_copy_ref(struct ref_store *ref_store, const char *oldref,
-			  const char *newref, const char *logmsg)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res =
-		drefs->refs->be->copy_ref(drefs->refs, oldref, newref, logmsg);
-	trace_printf_key(&trace_refs, "copy_ref: %s -> %s \"%s\": %d\n", oldref, newref,
-		logmsg, res);
-	return res;
-}
-
 struct debug_ref_iterator {
 	struct ref_iterator base;
 	struct ref_iterator *iter;
@@ -453,8 +431,6 @@ struct ref_storage_be refs_be_debug = {
 	.optimize = debug_optimize,
 	.optimize_required = debug_optimize_required,
 
-	.rename_ref = debug_rename_ref,
-	.copy_ref = debug_copy_ref,
 
 	.iterator_begin = debug_ref_iterator_begin,
 	.read_raw_ref = debug_read_raw_ref,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 9e22f62d3f..a00cfc6be5 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1623,273 +1623,6 @@ static int files_optimize_required(struct ref_store *ref_store,
 	return 0;
 }
 
-/*
- * People using contrib's git-new-workdir have .git/logs/refs ->
- * /some/other/path/.git/logs/refs, and that may live on another device.
- *
- * IOW, to avoid cross device rename errors, the temporary renamed log must
- * live into logs/refs.
- */
-#define TMP_RENAMED_LOG  "refs/.tmp-renamed-log"
-
-struct rename_cb {
-	const char *tmp_renamed_log;
-	int true_errno;
-};
-
-static int rename_tmp_log_callback(const char *path, void *cb_data)
-{
-	struct rename_cb *cb = cb_data;
-
-	if (rename(cb->tmp_renamed_log, path)) {
-		/*
-		 * rename(a, b) when b is an existing directory ought
-		 * to result in ISDIR, but Solaris 5.8 gives ENOTDIR.
-		 * Sheesh. Record the true errno for error reporting,
-		 * but report EISDIR to raceproof_create_file() so
-		 * that it knows to retry.
-		 */
-		cb->true_errno = errno;
-		if (errno == ENOTDIR)
-			errno = EISDIR;
-		return -1;
-	} else {
-		return 0;
-	}
-}
-
-static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
-{
-	struct strbuf path = STRBUF_INIT;
-	struct strbuf tmp = STRBUF_INIT;
-	struct rename_cb cb;
-	int ret;
-
-	files_reflog_path(refs, &path, newrefname);
-	files_reflog_path(refs, &tmp, TMP_RENAMED_LOG);
-	cb.tmp_renamed_log = tmp.buf;
-	ret = raceproof_create_file(refs, path.buf, rename_tmp_log_callback, &cb);
-	if (ret) {
-		if (errno == EISDIR)
-			error("directory not empty: %s", path.buf);
-		else
-			error("unable to move logfile %s to %s: %s",
-			      tmp.buf, path.buf,
-			      strerror(cb.true_errno));
-	}
-
-	strbuf_release(&path);
-	strbuf_release(&tmp);
-	return ret;
-}
-
-static enum ref_transaction_error write_ref_to_lockfile(struct files_ref_store *refs,
-							struct ref_lock *lock,
-							const struct object_id *oid,
-							struct strbuf *err);
-static int commit_ref_update(struct files_ref_store *refs,
-			     struct ref_lock *lock,
-			     const struct object_id *oid, const char *logmsg,
-			     int flags,
-			     struct strbuf *err);
-
-/*
- * Emit a better error message than lockfile.c's
- * unable_to_lock_message() would in case there is a D/F conflict with
- * another existing reference. If there would be a conflict, emit an error
- * message and return false; otherwise, return true.
- *
- * Note that this function is not safe against all races with other
- * processes, and that's not its job. We'll emit a more verbose error on D/f
- * conflicts if we get past it into lock_ref_oid_basic().
- */
-static int refs_rename_ref_available(struct ref_store *refs,
-			      const char *old_refname,
-			      const char *new_refname)
-{
-	struct string_list skip = STRING_LIST_INIT_NODUP;
-	struct strbuf err = STRBUF_INIT;
-	int ok;
-
-	string_list_insert(&skip, old_refname);
-	ok = !refs_verify_refname_available(refs, new_refname,
-					    NULL, &skip, 0, &err);
-	if (!ok)
-		error("%s", err.buf);
-
-	string_list_clear(&skip, 0);
-	strbuf_release(&err);
-	return ok;
-}
-
-static int files_copy_or_rename_ref(struct ref_store *ref_store,
-			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg, int copy)
-{
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "rename_ref");
-	struct object_id orig_oid;
-	int flag = 0, logmoved = 0;
-	struct ref_lock *lock;
-	struct stat loginfo;
-	struct strbuf sb_oldref = STRBUF_INIT;
-	struct strbuf sb_newref = STRBUF_INIT;
-	struct strbuf tmp_renamed_log = STRBUF_INIT;
-	int log, ret;
-	struct strbuf err = STRBUF_INIT;
-
-	files_reflog_path(refs, &sb_oldref, oldrefname);
-	files_reflog_path(refs, &sb_newref, newrefname);
-	files_reflog_path(refs, &tmp_renamed_log, TMP_RENAMED_LOG);
-
-	log = !lstat(sb_oldref.buf, &loginfo);
-	if (log && S_ISLNK(loginfo.st_mode)) {
-		ret = error("reflog for %s is a symlink", oldrefname);
-		goto out;
-	}
-
-	if (!refs_resolve_ref_unsafe(&refs->base, oldrefname,
-				     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-				     &orig_oid, &flag)) {
-		ret = error("refname %s not found", oldrefname);
-		goto out;
-	}
-
-	if (flag & REF_ISSYMREF) {
-		if (copy)
-			ret = error("refname %s is a symbolic ref, copying it is not supported",
-				    oldrefname);
-		else
-			ret = error("refname %s is a symbolic ref, renaming it is not supported",
-				    oldrefname);
-		goto out;
-	}
-	if (!refs_rename_ref_available(&refs->base, oldrefname, newrefname)) {
-		ret = 1;
-		goto out;
-	}
-
-	if (!copy && log && rename(sb_oldref.buf, tmp_renamed_log.buf)) {
-		ret = error("unable to move logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
-			    oldrefname, strerror(errno));
-		goto out;
-	}
-
-	if (copy && log && copy_file(refs->base.repo, tmp_renamed_log.buf, sb_oldref.buf, 0644)) {
-		ret = error("unable to copy logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
-			    oldrefname, strerror(errno));
-		goto out;
-	}
-
-	if (!copy && refs_delete_ref(&refs->base, logmsg, oldrefname,
-			    &orig_oid, REF_NO_DEREF)) {
-		error("unable to delete old %s", oldrefname);
-		goto rollback;
-	}
-
-	/*
-	 * Since we are doing a shallow lookup, oid is not the
-	 * correct value to pass to delete_ref as old_oid. But that
-	 * doesn't matter, because an old_oid check wouldn't add to
-	 * the safety anyway; we want to delete the reference whatever
-	 * its current value.
-	 */
-	if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname,
-					     RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
-					     NULL, NULL) &&
-	    refs_delete_ref(&refs->base, NULL, newrefname,
-			    NULL, REF_NO_DEREF)) {
-		if (errno == EISDIR) {
-			struct strbuf path = STRBUF_INIT;
-			int result;
-
-			files_ref_path(refs, &path, newrefname);
-			result = remove_empty_directories(&path);
-			strbuf_release(&path);
-
-			if (result) {
-				error("Directory not empty: %s", newrefname);
-				goto rollback;
-			}
-		} else {
-			error("unable to delete existing %s", newrefname);
-			goto rollback;
-		}
-	}
-
-	if (log && rename_tmp_log(refs, newrefname))
-		goto rollback;
-
-	logmoved = log;
-
-	lock = lock_ref_oid_basic(refs, newrefname, &err);
-	if (!lock) {
-		if (copy)
-			error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf);
-		else
-			error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
-		strbuf_release(&err);
-		goto rollback;
-	}
-	oidcpy(&lock->old_oid, &orig_oid);
-
-	if (write_ref_to_lockfile(refs, lock, &orig_oid, &err) ||
-	    commit_ref_update(refs, lock, &orig_oid, logmsg, 0, &err)) {
-		error("unable to write current sha1 into %s: %s", newrefname, err.buf);
-		strbuf_release(&err);
-		goto rollback;
-	}
-
-	ret = 0;
-	goto out;
-
- rollback:
-	lock = lock_ref_oid_basic(refs, oldrefname, &err);
-	if (!lock) {
-		error("unable to lock %s for rollback: %s", oldrefname, err.buf);
-		strbuf_release(&err);
-		goto rollbacklog;
-	}
-
-	if (write_ref_to_lockfile(refs, lock, &orig_oid, &err) ||
-	    commit_ref_update(refs, lock, &orig_oid, NULL, REF_SKIP_CREATE_REFLOG, &err)) {
-		error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
-		strbuf_release(&err);
-	}
-
- rollbacklog:
-	if (logmoved && rename(sb_newref.buf, sb_oldref.buf))
-		error("unable to restore logfile %s from %s: %s",
-			oldrefname, newrefname, strerror(errno));
-	if (!logmoved && log &&
-	    rename(tmp_renamed_log.buf, sb_oldref.buf))
-		error("unable to restore logfile %s from logs/"TMP_RENAMED_LOG": %s",
-			oldrefname, strerror(errno));
-	ret = 1;
- out:
-	strbuf_release(&sb_newref);
-	strbuf_release(&sb_oldref);
-	strbuf_release(&tmp_renamed_log);
-
-	return ret;
-}
-
-static int files_rename_ref(struct ref_store *ref_store,
-			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg)
-{
-	return files_copy_or_rename_ref(ref_store, oldrefname,
-				 newrefname, logmsg, 0);
-}
-
-static int files_copy_ref(struct ref_store *ref_store,
-			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg)
-{
-	return files_copy_or_rename_ref(ref_store, oldrefname,
-				 newrefname, logmsg, 1);
-}
-
 static int close_ref_gently(struct ref_lock *lock)
 {
 	if (close_lock_file_gently(&lock->lk))
@@ -2121,71 +1854,6 @@ static enum ref_transaction_error write_ref_to_lockfile(struct files_ref_store *
 	return 0;
 }
 
-/*
- * Commit a change to a loose reference that has already been written
- * to the loose reference lockfile. Also update the reflogs if
- * necessary, using the specified lockmsg (which can be NULL).
- */
-static int commit_ref_update(struct files_ref_store *refs,
-			     struct ref_lock *lock,
-			     const struct object_id *oid, const char *logmsg,
-			     int flags,
-			     struct strbuf *err)
-{
-	files_assert_main_repository(refs, "commit_ref_update");
-
-	clear_loose_ref_cache(refs);
-	if (files_log_ref_write(refs, lock->ref_name, &lock->old_oid, oid, NULL,
-				logmsg, flags, err)) {
-		char *old_msg = strbuf_detach(err, NULL);
-		strbuf_addf(err, "cannot update the ref '%s': %s",
-			    lock->ref_name, old_msg);
-		free(old_msg);
-		unlock_ref(lock);
-		return -1;
-	}
-
-	if (strcmp(lock->ref_name, "HEAD") != 0) {
-		/*
-		 * Special hack: If a branch is updated directly and HEAD
-		 * points to it (may happen on the remote side of a push
-		 * for example) then logically the HEAD reflog should be
-		 * updated too.
-		 * A generic solution implies reverse symref information,
-		 * but finding all symrefs pointing to the given branch
-		 * would be rather costly for this rare event (the direct
-		 * update of a branch) to be worth it.  So let's cheat and
-		 * check with HEAD only which should cover 99% of all usage
-		 * scenarios (even 100% of the default ones).
-		 */
-		int head_flag;
-		const char *head_ref;
-
-		head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD",
-						   RESOLVE_REF_READING,
-						   NULL, &head_flag);
-		if (head_ref && (head_flag & REF_ISSYMREF) &&
-		    !strcmp(head_ref, lock->ref_name)) {
-			struct strbuf log_err = STRBUF_INIT;
-			if (files_log_ref_write(refs, "HEAD", &lock->old_oid,
-						oid, NULL, logmsg, flags,
-						&log_err)) {
-				error("%s", log_err.buf);
-				strbuf_release(&log_err);
-			}
-		}
-	}
-
-	if (commit_ref(lock)) {
-		strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
-		unlock_ref(lock);
-		return -1;
-	}
-
-	unlock_ref(lock);
-	return 0;
-}
-
 #if defined(NO_SYMLINK_HEAD) || defined(WITH_BREAKING_CHANGES)
 #define create_ref_symlink(a, b) (-1)
 #else
@@ -4468,8 +4136,6 @@ struct ref_storage_be refs_be_files = {
 
 	.optimize = files_optimize,
 	.optimize_required = files_optimize_required,
-	.rename_ref = files_rename_ref,
-	.copy_ref = files_copy_ref,
 
 	.iterator_begin = files_ref_iterator_begin,
 	.read_raw_ref = files_read_raw_ref,
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index a73fc6aca7..364a912912 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -2164,8 +2164,6 @@ struct ref_storage_be refs_be_packed = {
 	.optimize = packed_optimize,
 	.optimize_required = packed_optimize_required,
 
-	.rename_ref = NULL,
-	.copy_ref = NULL,
 
 	.iterator_begin = packed_ref_iterator_begin,
 	.read_raw_ref = packed_read_raw_ref,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 2746ce5b49..c415ba0a4e 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -470,13 +470,6 @@ typedef int optimize_required_fn(struct ref_store *ref_store,
 				 struct refs_optimize_opts *opts,
 				 bool *required);
 
-typedef int rename_ref_fn(struct ref_store *ref_store,
-			  const char *oldref, const char *newref,
-			  const char *logmsg);
-typedef int copy_ref_fn(struct ref_store *ref_store,
-			  const char *oldref, const char *newref,
-			  const char *logmsg);
-
 /*
  * Iterate over the references in `ref_store` whose names start with
  * `prefix`. `prefix` is matched as a literal string, without regard
@@ -596,8 +589,6 @@ struct ref_storage_be {
 
 	optimize_fn *optimize;
 	optimize_required_fn *optimize_required;
-	rename_ref_fn *rename_ref;
-	copy_ref_fn *copy_ref;
 
 	ref_iterator_begin_fn *iterator_begin;
 	read_raw_ref_fn *read_raw_ref;
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 72c1596c11..ef3bab69ee 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1798,290 +1798,6 @@ struct write_create_symref_arg {
 	const char *logmsg;
 };
 
-struct write_copy_arg {
-	struct reftable_ref_store *refs;
-	struct reftable_backend *be;
-	const char *oldname;
-	const char *newname;
-	const char *logmsg;
-	int delete_old;
-};
-
-static int write_copy_table(struct reftable_writer *writer, void *cb_data)
-{
-	struct write_copy_arg *arg = cb_data;
-	uint64_t deletion_ts, creation_ts;
-	struct reftable_ref_record old_ref = {0}, refs[2] = {0};
-	struct reftable_log_record old_log = {0}, *logs = NULL;
-	struct reftable_iterator it = {0};
-	struct string_list skip = STRING_LIST_INIT_NODUP;
-	struct ident_split committer_ident = {0};
-	struct strbuf errbuf = STRBUF_INIT;
-	size_t logs_nr = 0, logs_alloc = 0, i;
-	const char *committer_info;
-	int ret;
-
-	committer_info = git_committer_info(0);
-	if (split_ident_line(&committer_ident, committer_info, strlen(committer_info)))
-		BUG("failed splitting committer info");
-
-	if (reftable_stack_read_ref(arg->be->stack, arg->oldname, &old_ref)) {
-		ret = error(_("refname %s not found"), arg->oldname);
-		goto done;
-	}
-	if (old_ref.value_type == REFTABLE_REF_SYMREF) {
-		ret = error(_("refname %s is a symbolic ref, copying it is not supported"),
-			    arg->oldname);
-		goto done;
-	}
-
-	/*
-	 * There's nothing to do in case the old and new name are the same, so
-	 * we exit early in that case.
-	 */
-	if (!strcmp(arg->oldname, arg->newname)) {
-		ret = 0;
-		goto done;
-	}
-
-	/*
-	 * Verify that the new refname is available.
-	 */
-	if (arg->delete_old)
-		string_list_insert(&skip, arg->oldname);
-	ret = refs_verify_refname_available(&arg->refs->base, arg->newname,
-					    NULL, &skip, 0, &errbuf);
-	if (ret < 0) {
-		error("%s", errbuf.buf);
-		goto done;
-	}
-
-	/*
-	 * When deleting the old reference we have to use two update indices:
-	 * once to delete the old ref and its reflog, and once to create the
-	 * new ref and its reflog. They need to be staged with two separate
-	 * indices because the new reflog needs to encode both the deletion of
-	 * the old branch and the creation of the new branch, and we cannot do
-	 * two changes to a reflog in a single update.
-	 */
-	deletion_ts = creation_ts = reftable_stack_next_update_index(arg->be->stack);
-	if (arg->delete_old)
-		creation_ts++;
-	ret = reftable_writer_set_limits(writer, deletion_ts, creation_ts);
-	if (ret < 0)
-		goto done;
-
-	/*
-	 * Add the new reference. If this is a rename then we also delete the
-	 * old reference.
-	 */
-	refs[0] = old_ref;
-	refs[0].refname = xstrdup(arg->newname);
-	refs[0].update_index = creation_ts;
-	if (arg->delete_old) {
-		refs[1].refname = xstrdup(arg->oldname);
-		refs[1].value_type = REFTABLE_REF_DELETION;
-		refs[1].update_index = deletion_ts;
-	}
-	ret = reftable_writer_add_refs(writer, refs, arg->delete_old ? 2 : 1);
-	if (ret < 0)
-		goto done;
-
-	/*
-	 * When deleting the old branch we need to create a reflog entry on the
-	 * new branch name that indicates that the old branch has been deleted
-	 * and then recreated. This is a tad weird, but matches what the files
-	 * backend does.
-	 */
-	if (arg->delete_old) {
-		struct strbuf head_referent = STRBUF_INIT;
-		struct object_id head_oid;
-		int append_head_reflog;
-		unsigned head_type = 0;
-
-		ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
-		memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
-		fill_reftable_log_record(&logs[logs_nr], &committer_ident);
-		logs[logs_nr].refname = xstrdup(arg->newname);
-		logs[logs_nr].update_index = deletion_ts;
-		logs[logs_nr].value.update.message =
-			xstrndup(arg->logmsg, reftable_be_write_options(arg->refs)->opts.block_size / 2);
-		memcpy(logs[logs_nr].value.update.old_hash, old_ref.value.val1, GIT_MAX_RAWSZ);
-		logs_nr++;
-
-		ret = reftable_backend_read_ref(arg->be, "HEAD", &head_oid,
-						&head_referent, &head_type);
-		if (ret < 0)
-			goto done;
-		append_head_reflog = (head_type & REF_ISSYMREF) && !strcmp(head_referent.buf, arg->oldname);
-		strbuf_release(&head_referent);
-
-		/*
-		 * The files backend uses `refs_delete_ref()` to delete the old
-		 * branch name, which will append a reflog entry for HEAD in
-		 * case it points to the old branch.
-		 */
-		if (append_head_reflog) {
-			ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
-			logs[logs_nr] = logs[logs_nr - 1];
-			logs[logs_nr].refname = xstrdup("HEAD");
-			logs[logs_nr].value.update.name =
-				xstrdup(logs[logs_nr].value.update.name);
-			logs[logs_nr].value.update.email =
-				xstrdup(logs[logs_nr].value.update.email);
-			logs[logs_nr].value.update.message =
-				xstrdup(logs[logs_nr].value.update.message);
-			logs_nr++;
-		}
-	}
-
-	/*
-	 * Create the reflog entry for the newly created branch.
-	 */
-	ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
-	memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
-	fill_reftable_log_record(&logs[logs_nr], &committer_ident);
-	logs[logs_nr].refname = xstrdup(arg->newname);
-	logs[logs_nr].update_index = creation_ts;
-	logs[logs_nr].value.update.message =
-		xstrndup(arg->logmsg, reftable_be_write_options(arg->refs)->opts.block_size / 2);
-	memcpy(logs[logs_nr].value.update.new_hash, old_ref.value.val1, GIT_MAX_RAWSZ);
-	logs_nr++;
-
-	/*
-	 * In addition to writing the reflog entry for the new branch, we also
-	 * copy over all log entries from the old reflog. Last but not least,
-	 * when renaming we also have to delete all the old reflog entries.
-	 */
-	ret = reftable_stack_init_log_iterator(arg->be->stack, &it);
-	if (ret < 0)
-		goto done;
-
-	ret = reftable_iterator_seek_log(&it, arg->oldname);
-	if (ret < 0)
-		goto done;
-
-	while (1) {
-		ret = reftable_iterator_next_log(&it, &old_log);
-		if (ret < 0)
-			goto done;
-		if (ret > 0 || strcmp(old_log.refname, arg->oldname)) {
-			ret = 0;
-			break;
-		}
-		if (reftable_log_record_is_deletion(&old_log))
-			continue;
-
-		free(old_log.refname);
-
-		/*
-		 * Copy over the old reflog entry with the new refname.
-		 */
-		ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
-		logs[logs_nr] = old_log;
-		logs[logs_nr].refname = xstrdup(arg->newname);
-		logs_nr++;
-
-		/*
-		 * Delete the old reflog entry in case we are renaming.
-		 */
-		if (arg->delete_old) {
-			ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
-			memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
-			logs[logs_nr].refname = xstrdup(arg->oldname);
-			logs[logs_nr].value_type = REFTABLE_LOG_DELETION;
-			logs[logs_nr].update_index = old_log.update_index;
-			logs_nr++;
-		}
-
-		/*
-		 * Transfer ownership of the log record we're iterating over to
-		 * the array of log records. Otherwise, the pointers would get
-		 * free'd or reallocated by the iterator.
-		 */
-		memset(&old_log, 0, sizeof(old_log));
-	}
-
-	ret = reftable_writer_add_logs(writer, logs, logs_nr);
-	if (ret < 0)
-		goto done;
-
-done:
-	assert(ret != REFTABLE_API_ERROR);
-	reftable_iterator_destroy(&it);
-	string_list_clear(&skip, 0);
-	strbuf_release(&errbuf);
-	for (i = 0; i < logs_nr; i++)
-		reftable_log_record_release(&logs[i]);
-	free(logs);
-	for (i = 0; i < ARRAY_SIZE(refs); i++)
-		reftable_ref_record_release(&refs[i]);
-	reftable_ref_record_release(&old_ref);
-	reftable_log_record_release(&old_log);
-	return ret;
-}
-
-static int reftable_be_rename_ref(struct ref_store *ref_store,
-				  const char *oldrefname,
-				  const char *newrefname,
-				  const char *logmsg)
-{
-	struct reftable_ref_store *refs =
-		reftable_be_downcast(ref_store, REF_STORE_WRITE, "rename_ref");
-	struct write_copy_arg arg = {
-		.refs = refs,
-		.oldname = oldrefname,
-		.newname = newrefname,
-		.logmsg = logmsg,
-		.delete_old = 1,
-	};
-	int ret;
-
-	ret = refs->err;
-	if (ret < 0)
-		goto done;
-
-	ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
-	if (ret)
-		goto done;
-	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
-				 &reftable_be_write_options(refs)->opts);
-
-done:
-	assert(ret != REFTABLE_API_ERROR);
-	return ret;
-}
-
-static int reftable_be_copy_ref(struct ref_store *ref_store,
-				const char *oldrefname,
-				const char *newrefname,
-				const char *logmsg)
-{
-	struct reftable_ref_store *refs =
-		reftable_be_downcast(ref_store, REF_STORE_WRITE, "copy_ref");
-	struct write_copy_arg arg = {
-		.refs = refs,
-		.oldname = oldrefname,
-		.newname = newrefname,
-		.logmsg = logmsg,
-	};
-	int ret;
-
-	ret = refs->err;
-	if (ret < 0)
-		goto done;
-
-	ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
-	if (ret)
-		goto done;
-	ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
-				 &reftable_be_write_options(refs)->opts);
-
-done:
-	assert(ret != REFTABLE_API_ERROR);
-	return ret;
-}
-
 struct reftable_reflog_iterator {
 	struct ref_iterator base;
 	struct reftable_ref_store *refs;
@@ -2909,9 +2625,6 @@ struct ref_storage_be refs_be_reftable = {
 	.optimize = reftable_be_optimize,
 	.optimize_required = reftable_be_optimize_required,
 
-	.rename_ref = reftable_be_rename_ref,
-	.copy_ref = reftable_be_copy_ref,
-
 	.iterator_begin = reftable_be_iterator_begin,
 	.read_raw_ref = reftable_be_read_raw_ref,
 	.read_symbolic_ref = reftable_be_read_symbolic_ref,
-- 
2.39.3 (Apple Git-146)


  parent reply	other threads:[~2026-10-07 18:05 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19 13:33 [BUG] reference-transaction hook misses destination of git branch -m Maciej Ciemborowicz
2026-09-19 20:52 ` Karthik Nayak
2026-09-20 16:50   ` [PATCH] refs: run copy and rename through transactions Maciej Ciemborowicz
2026-09-21 17:54     ` Junio C Hamano
2026-09-21 23:28       ` Junio C Hamano
2026-09-22 13:08         ` Maciej Ciemborowicz
2026-09-23 13:36     ` [PATCH v2] " Maciej Ciemborowicz
2026-09-30  3:32       ` Maciej Ciemborowicz
2026-10-02 10:56       ` Patrick Steinhardt
2026-10-02 14:16         ` Maciej Ciemborowicz
2026-10-05  6:03           ` Patrick Steinhardt
2026-10-07 18:05     ` [PATCH v3 0/4] " Maciej Ciemborowicz
2026-10-07 18:05       ` [PATCH v3 1/4] refs: distinguish internal transactions from logical updates Maciej Ciemborowicz
2026-10-07 18:05       ` [PATCH v3 2/4] refs: support replacing reflogs in a transaction Maciej Ciemborowicz
2026-10-07 18:05       ` [PATCH v3 3/4] refs: run copy and rename through ordinary transactions Maciej Ciemborowicz
2026-10-07 18:05       ` Maciej Ciemborowicz [this message]
2026-10-07 19:55       ` [PATCH v3 0/4] refs: run copy and rename through transactions Junio C Hamano
2026-10-08  9:44     ` [PATCH v4 " Maciej Ciemborowicz
2026-10-08  9:44       ` [PATCH v4 1/4] refs: distinguish internal transactions from logical updates Maciej Ciemborowicz
2026-10-08  9:44       ` [PATCH v4 2/4] refs: support replacing reflogs in a transaction Maciej Ciemborowicz
2026-10-08  9:44       ` [PATCH v4 3/4] refs: run copy and rename through ordinary transactions Maciej Ciemborowicz
2026-10-08  9:44       ` [PATCH v4 4/4] refs: remove backend-specific copy and rename callbacks Maciej Ciemborowicz
2026-10-08 10:10       ` [PATCH v4 0/4] refs: run copy and rename through transactions Patrick Steinhardt
2026-10-08 10:43         ` Maciej Ciemborowicz
2026-10-08 11:01           ` Maciej Ciemborowicz
2026-10-08 15:45             ` Junio C Hamano
2026-10-08 19:06               ` Maciej Ciemborowicz
2026-10-08 19:19                 ` Kristoffer Haugsbakk
2026-10-08 21:11                   ` Maciej Ciemborowicz
2026-10-09  5:41                 ` Patrick Steinhardt
2026-10-08 15:54         ` Junio C Hamano
2026-09-23 12:49   ` [PATCH v4 0/3] refs: report old OIDs for batched deletions Maciej Ciemborowicz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=83fa644fb3dbf1807e232cac22f9dd7528b766c1.1791395643.git.maciej.ciemborowicz@gmail.com \
    --to=maciej.ciemborowicz@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=karthik.188@gmail.com \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox