git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] refs: fix format migration on Cygwin

From
Patrick Steinhardt <ps@pks.im>
Date
Jul 23, 2024, 12:31 UTC
Message-ID
<d031aef5552d894784650a8c6580925e877df794.1721731179.git.ps@pks.im>
In-Reply-To
<aacb4067-a16b-4953-a72f-3c66efd3cf25@ramsayjones.plus.com>

It was reported that t1460-refs-migrate.sh fails when using Cygwin with errors like the following:

    error: could not link file '.git/ref_migration.sr9pEF/reftable' to '.git/reftable': Permission denied

As some debugging surfaced, the root cause of this is that some files of the newly-initialized ref store are still open when the target format is the "reftable" format, and Cygwin refuses to rename open files.

Fix this issue by closing the new ref store before renaming its files into place. This is a slight change in behaviour compared to before, where we kept the new ref store open and then updated the repository's ref store to point to it.

While we could re-open the new ref store after we have moved files around, this is ultimately unnecessary. We know that the only user of `repo_migrate_ref_storage_format()` is the git-refs(1) command, and it won't access the ref store after it has been migrated anyway. So reinitializing the ref store would be a waste of time. Regardless of that it is still sensible to leave the repository in a consistent state. But instead of reinitializing the ref store, we can simply unset the repo's ref store altogether and let `get_main_ref_store()` lazily initialize the new ref store as required.

Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/refs.c b/refs.c
index bb90a18875..915aeb4d1d 100644
--- a/refs.c
+++ b/refs.c
@@ -2843,6 +2843,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 		goto done;
 	}
 
+	/*
+	 * Release the new ref store such that any potentially-open files will
+	 * be closed. This is required for platforms like Cygwin, where
+	 * renaming an open file results in EPERM.
+	 */
+	ref_store_release(new_refs);
+	FREE_AND_NULL(new_refs);
+
 	/*
 	 * Until now we were in the non-destructive phase, where we only
 	 * populated the new ref store. From hereon though we are about
@@ -2874,10 +2882,14 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 	 */
 	initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1);
 
-	free(new_refs->gitdir);
-	new_refs->gitdir = xstrdup(old_refs->gitdir);
-	repo->refs_private = new_refs;
+	/*
+	 * Unset the old ref store and release it. `get_main_ref_store()` will
+	 * make sure to lazily re-initialize the repository's ref store with
+	 * the new format.
+	 */
 	ref_store_release(old_refs);
+	FREE_AND_NULL(old_refs);
+	repo->refs_private = NULL;
 
 	ret = 0;
 
@@ -2888,8 +2900,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
 			    new_gitdir.buf);
 	}
 
-	if (ret && new_refs)
+	if (new_refs) {
 		ref_store_release(new_refs);
+		free(new_refs);
+	}
 	ref_transaction_free(transaction);
 	strbuf_release(&new_gitdir);
 	return ret;
-- 
2.46.0.rc1.dirty
Previous: Jeff KingNext: Ramsay Jones
Message 12 of 15 in “v2.46.0-rc0 test failures on cygwin”
  1. Ramsay JonesJul 16, 2024
  2. Jeff KingJul 17, 2024
  3. Junio C HamanoJul 17, 2024
  4. Ramsay JonesJul 17, 2024
  5. Ramsay JonesJul 17, 2024
  6. Jeff KingJul 18, 2024
  7. Ramsay JonesJul 18, 2024
  8. Junio C HamanoJul 18, 2024
  9. Adam DinwoodieJul 21, 2024
  10. Patrick SteinhardtJul 23, 2024
  11. Jeff KingJul 23, 2024
  12. refs: fix format migration on CygwinPatrick Steinhardt, Jul 23, 2024
  13. Ramsay JonesJul 23, 2024
  14. Junio C HamanoJul 23, 2024
  15. Jeff KingJul 23, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.