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

[PATCH v3 10/12] refs: implement removal of ref storages

From
Patrick Steinhardt <ps@pks.im>
Date
May 28, 2024, 06:31 UTC
Message-ID
<f9d9420cf93025595e00aa4287bc0cc1a1c067ab.1716877224.git.ps@pks.im>
In-Reply-To
<cover.1716877224.git.ps@pks.im>

We're about to introduce logic to migrate ref storages. One part of the migration will be to delete the files that are part of the old ref storage format. We don't yet have a way to delete such data generically across ref backends though.

Implement a new `delete` callback and expose it via a new `ref_storage_delete()` function.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs.c                  |  5 ++++
 refs.h                  |  5 ++++
 refs/files-backend.c    | 63 +++++++++++++++++++++++++++++++++++++++++
 refs/packed-backend.c   | 15 ++++++++++
 refs/refs-internal.h    |  7 +++++
 refs/reftable-backend.c | 52 ++++++++++++++++++++++++++++++++++
 6 files changed, 147 insertions(+)
diff --git a/refs.c b/refs.c
index 66e9585767..9b112b0527 100644
--- a/refs.c
+++ b/refs.c
@@ -1861,6 +1861,11 @@ int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *e
 	return refs->be->create_on_disk(refs, flags, err);
 }
 
+int ref_store_remove_on_disk(struct ref_store *refs, struct strbuf *err)
+{
+	return refs->be->remove_on_disk(refs, err);
+}
+
 int repo_resolve_gitlink_ref(struct repository *r,
 			     const char *submodule, const char *refname,
 			     struct object_id *oid)
diff --git a/refs.h b/refs.h
index 50a2b3ab09..61ee7b7a15 100644
--- a/refs.h
+++ b/refs.h
@@ -129,6 +129,11 @@ int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *e
  */
 void ref_store_release(struct ref_store *ref_store);
 
+/*
+ * Remove the ref store from disk. This deletes all associated data.
+ */
+int ref_store_remove_on_disk(struct ref_store *refs, struct strbuf *err);
+
 /*
  * Return the peeled value of the oid currently being iterated via
  * for_each_ref(), etc. This is equivalent to calling:
diff --git a/refs/files-backend.c b/refs/files-backend.c
index b7268b26c8..cb752d32b6 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3340,11 +3340,74 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store,
 	return 0;
 }
 
+struct remove_one_root_ref_data {
+	const char *gitdir;
+	struct strbuf *err;
+};
+
+static int remove_one_root_ref(const char *refname,
+			       void *cb_data)
+{
+	struct remove_one_root_ref_data *data = cb_data;
+	struct strbuf buf = STRBUF_INIT;
+	int ret = 0;
+
+	strbuf_addf(&buf, "%s/%s", data->gitdir, refname);
+
+	ret = unlink(buf.buf);
+	if (ret < 0)
+		strbuf_addf(data->err, "could not delete %s: %s\n",
+			    refname, strerror(errno));
+
+	strbuf_release(&buf);
+	return ret;
+}
+
+static int files_ref_store_remove_on_disk(struct ref_store *ref_store,
+					  struct strbuf *err)
+{
+	struct files_ref_store *refs =
+		files_downcast(ref_store, REF_STORE_WRITE, "remove");
+	struct remove_one_root_ref_data data = {
+		.gitdir = refs->base.gitdir,
+		.err = err,
+	};
+	struct strbuf sb = STRBUF_INIT;
+	int ret = 0;
+
+	strbuf_addf(&sb, "%s/refs", refs->base.gitdir);
+	if (remove_dir_recursively(&sb, 0) < 0) {
+		strbuf_addf(err, "could not delete refs: %s",
+			    strerror(errno));
+		ret = -1;
+	}
+	strbuf_reset(&sb);
+
+	strbuf_addf(&sb, "%s/logs", refs->base.gitdir);
+	if (remove_dir_recursively(&sb, 0) < 0) {
+		strbuf_addf(err, "could not delete logs: %s",
+			    strerror(errno));
+		ret = -1;
+	}
+	strbuf_reset(&sb);
+
+	ret = for_each_root_ref(refs, remove_one_root_ref, &data);
+	if (ret < 0)
+		ret = -1;
+
+	if (ref_store_remove_on_disk(refs->packed_ref_store, err) < 0)
+		ret = -1;
+
+	strbuf_release(&sb);
+	return ret;
+}
+
 struct ref_storage_be refs_be_files = {
 	.name = "files",
 	.init = files_ref_store_init,
 	.release = files_ref_store_release,
 	.create_on_disk = files_ref_store_create_on_disk,
+	.remove_on_disk = files_ref_store_remove_on_disk,
 
 	.transaction_prepare = files_transaction_prepare,
 	.transaction_finish = files_transaction_finish,
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 2789fd92f5..c4c1e36aa2 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1,5 +1,6 @@
 #include "../git-compat-util.h"
 #include "../config.h"
+#include "../dir.h"
 #include "../gettext.h"
 #include "../hash.h"
 #include "../hex.h"
@@ -1266,6 +1267,19 @@ static int packed_ref_store_create_on_disk(struct ref_store *ref_store UNUSED,
 	return 0;
 }
 
+static int packed_ref_store_remove_on_disk(struct ref_store *ref_store,
+					   struct strbuf *err)
+{
+	struct packed_ref_store *refs = packed_downcast(ref_store, 0, "remove");
+
+	if (remove_path(refs->path) < 0) {
+		strbuf_addstr(err, "could not delete packed-refs");
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * Write the packed refs from the current snapshot to the packed-refs
  * tempfile, incorporating any changes from `updates`. `updates` must
@@ -1724,6 +1738,7 @@ struct ref_storage_be refs_be_packed = {
 	.init = packed_ref_store_init,
 	.release = packed_ref_store_release,
 	.create_on_disk = packed_ref_store_create_on_disk,
+	.remove_on_disk = packed_ref_store_remove_on_disk,
 
 	.transaction_prepare = packed_transaction_prepare,
 	.transaction_finish = packed_transaction_finish,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 33749fbd83..cbcb6f9c36 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -517,6 +517,12 @@ typedef int ref_store_create_on_disk_fn(struct ref_store *refs,
 					int flags,
 					struct strbuf *err);
 
+/*
+ * Remove the reference store from disk.
+ */
+typedef int ref_store_remove_on_disk_fn(struct ref_store *refs,
+					struct strbuf *err);
+
 typedef int ref_transaction_prepare_fn(struct ref_store *refs,
 				       struct ref_transaction *transaction,
 				       struct strbuf *err);
@@ -649,6 +655,7 @@ struct ref_storage_be {
 	ref_store_init_fn *init;
 	ref_store_release_fn *release;
 	ref_store_create_on_disk_fn *create_on_disk;
+	ref_store_remove_on_disk_fn *remove_on_disk;
 
 	ref_transaction_prepare_fn *transaction_prepare;
 	ref_transaction_finish_fn *transaction_finish;
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index bffed9257f..e555be4671 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1,6 +1,7 @@
 #include "../git-compat-util.h"
 #include "../abspath.h"
 #include "../chdir-notify.h"
+#include "../dir.h"
 #include "../environment.h"
 #include "../gettext.h"
 #include "../hash.h"
@@ -343,6 +344,56 @@ static int reftable_be_create_on_disk(struct ref_store *ref_store,
 	return 0;
 }
 
+static int reftable_be_remove_on_disk(struct ref_store *ref_store,
+				      struct strbuf *err)
+{
+	struct reftable_ref_store *refs =
+		reftable_be_downcast(ref_store, REF_STORE_WRITE, "remove");
+	struct strbuf sb = STRBUF_INIT;
+	int ret = 0;
+
+	/*
+	 * Release the ref store such that all stacks are closed. This is
+	 * required so that the "tables.list" file is not open anymore, which
+	 * would otherwise make it impossible to remove the file on Windows.
+	 */
+	reftable_be_release(ref_store);
+
+	strbuf_addf(&sb, "%s/reftable", refs->base.gitdir);
+	if (remove_dir_recursively(&sb, 0) < 0) {
+		strbuf_addf(err, "could not delete reftables: %s",
+			    strerror(errno));
+		ret = -1;
+	}
+	strbuf_reset(&sb);
+
+	strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir);
+	if (unlink(sb.buf) < 0) {
+		strbuf_addf(err, "could not delete stub HEAD: %s",
+			    strerror(errno));
+		ret = -1;
+	}
+	strbuf_reset(&sb);
+
+	strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir);
+	if (unlink(sb.buf) < 0) {
+		strbuf_addf(err, "could not delete stub heads: %s",
+			    strerror(errno));
+		ret = -1;
+	}
+	strbuf_reset(&sb);
+
+	strbuf_addf(&sb, "%s/refs", refs->base.gitdir);
+	if (rmdir(sb.buf) < 0) {
+		strbuf_addf(err, "could not delete stub heads: %s",
+			    strerror(errno));
+		ret = -1;
+	}
+
+	strbuf_release(&sb);
+	return ret;
+}
+
 struct reftable_ref_iterator {
 	struct ref_iterator base;
 	struct reftable_ref_store *refs;
@@ -2196,6 +2247,7 @@ struct ref_storage_be refs_be_reftable = {
 	.init = reftable_be_init,
 	.release = reftable_be_release,
 	.create_on_disk = reftable_be_create_on_disk,
+	.remove_on_disk = reftable_be_remove_on_disk,
 
 	.transaction_prepare = reftable_be_transaction_prepare,
 	.transaction_finish = reftable_be_transaction_finish,
-- 
2.45.1.246.gb9cfe4845c.dirty
Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 48 of 103 in “refs: ref storage format migrations”
  1. 0/9 refs: ref storage format migrationsPatrick Steinhardt, May 23, 2024
  2. 1/9 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, May 23, 2024
  3. 2/9 refs: convert ref storage format to an enumPatrick Steinhardt, May 23, 2024
  4. 3/9 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, May 23, 2024
  5. 4/9 refs: allow to skip creation of reflog entriesPatrick Steinhardt, May 23, 2024
  6. 5/9 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, May 23, 2024
  7. 6/9 refs/files: extract function to iterate through root refsPatrick Steinhardt, May 23, 2024
  8. 7/9 refs: implement removal of ref storagesPatrick Steinhardt, May 23, 2024
  9. 8/9 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, May 23, 2024
  10. Eric SunshineMay 23, 2024
  11. Patrick SteinhardtMay 24, 2024
  12. Eric SunshineMay 24, 2024
  13. 9/9 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, May 23, 2024
  14. Eric SunshineMay 23, 2024
  15. Patrick SteinhardtMay 24, 2024
  16. Junio C HamanoMay 23, 2024
  17. Patrick SteinhardtMay 24, 2024
  18. Junio C HamanoMay 24, 2024
  19. Patrick SteinhardtMay 28, 2024
  20. Junio C HamanoMay 28, 2024
  21. 0/9 refs: ref storage format migrationsPatrick Steinhardt, May 24, 2024
  22. 1/9 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, May 24, 2024
  23. Justin ToblerMay 24, 2024
  24. Patrick SteinhardtMay 28, 2024
  25. 2/9 refs: convert ref storage format to an enumPatrick Steinhardt, May 24, 2024
  26. 3/9 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, May 24, 2024
  27. 4/9 refs: allow to skip creation of reflog entriesPatrick Steinhardt, May 24, 2024
  28. 5/9 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, May 24, 2024
  29. 6/9 refs/files: extract function to iterate through root refsPatrick Steinhardt, May 24, 2024
  30. 7/9 refs: implement removal of ref storagesPatrick Steinhardt, May 24, 2024
  31. 8/9 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, May 24, 2024
  32. Justin ToblerMay 24, 2024
  33. Patrick SteinhardtMay 28, 2024
  34. 9/9 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, May 24, 2024
  35. Ramsay JonesMay 24, 2024
  36. Eric SunshineMay 24, 2024
  37. Patrick SteinhardtMay 28, 2024
  38. 00/12 refs: ref storage format migrationsPatrick Steinhardt, May 28, 2024
  39. 01/12 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, May 28, 2024
  40. 02/12 refs: convert ref storage format to an enumPatrick Steinhardt, May 28, 2024
  41. 03/12 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, May 28, 2024
  42. 04/12 refs: allow to skip creation of reflog entriesPatrick Steinhardt, May 28, 2024
  43. 05/12 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, May 28, 2024
  44. 06/12 refs/files: extract function to iterate through root refsPatrick Steinhardt, May 28, 2024
  45. 07/12 refs/files: fix NULL pointer deref when releasing ref storePatrick Steinhardt, May 28, 2024
  46. 08/12 reftable: inline `merged_table_release()`Patrick Steinhardt, May 28, 2024
  47. 09/12 worktree: don't store main worktree twicePatrick Steinhardt, May 28, 2024
  48. 10/12 refs: implement removal of ref storagesPatrick Steinhardt, May 28, 2024
  49. 11/12 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, May 28, 2024
  50. 12/12 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, May 28, 2024
  51. Junio C HamanoMay 31, 2024
  52. Junio C HamanoJun 2, 2024
  53. Patrick SteinhardtJun 3, 2024
  54. Junio C HamanoMay 28, 2024
  55. Junio C HamanoMay 28, 2024
  56. 00/12 refs: ref storage migrationsPatrick Steinhardt, Jun 3, 2024
  57. 01/12 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, Jun 3, 2024
  58. 02/12 refs: convert ref storage format to an enumPatrick Steinhardt, Jun 3, 2024
  59. 03/12 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, Jun 3, 2024
  60. Karthik NayakJun 4, 2024
  61. 04/12 refs: allow to skip creation of reflog entriesPatrick Steinhardt, Jun 3, 2024
  62. Karthik NayakJun 4, 2024
  63. 05/12 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, Jun 3, 2024
  64. 06/12 refs/files: extract function to iterate through root refsPatrick Steinhardt, Jun 3, 2024
  65. Jeff KingJun 5, 2024
  66. Patrick SteinhardtJun 6, 2024
  67. Patrick SteinhardtJun 6, 2024
  68. Patrick SteinhardtJun 6, 2024
  69. 07/12 refs/files: fix NULL pointer deref when releasing ref storePatrick Steinhardt, Jun 3, 2024
  70. 08/12 reftable: inline `merged_table_release()`Patrick Steinhardt, Jun 3, 2024
  71. 09/12 worktree: don't store main worktree twicePatrick Steinhardt, Jun 3, 2024
  72. 10/12 refs: implement removal of ref storagesPatrick Steinhardt, Jun 3, 2024
  73. Karthik NayakJun 4, 2024
  74. Jeff KingJun 5, 2024
  75. Junio C HamanoJun 5, 2024
  76. Patrick SteinhardtJun 6, 2024
  77. 11/12 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, Jun 3, 2024
  78. Karthik NayakJun 4, 2024
  79. Patrick SteinhardtJun 5, 2024
  80. Jeff KingJun 5, 2024
  81. Junio C HamanoJun 5, 2024
  82. Patrick SteinhardtJun 6, 2024
  83. Jeff KingJun 6, 2024
  84. Junio C HamanoJun 6, 2024
  85. Jeff KingJun 8, 2024
  86. Junio C HamanoJun 8, 2024
  87. Patrick SteinhardtJun 6, 2024
  88. 12/12 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, Jun 3, 2024
  89. 00/12 refs: ref storage migrationsPatrick Steinhardt, Jun 6, 2024
  90. 01/12 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, Jun 6, 2024
  91. 02/12 refs: convert ref storage format to an enumPatrick Steinhardt, Jun 6, 2024
  92. 03/12 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, Jun 6, 2024
  93. 04/12 refs: allow to skip creation of reflog entriesPatrick Steinhardt, Jun 6, 2024
  94. 05/12 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, Jun 6, 2024
  95. 06/12 refs/files: extract function to iterate through root refsPatrick Steinhardt, Jun 6, 2024
  96. 07/12 refs/files: fix NULL pointer deref when releasing ref storePatrick Steinhardt, Jun 6, 2024
  97. 08/12 reftable: inline `merged_table_release()`Patrick Steinhardt, Jun 6, 2024
  98. 09/12 worktree: don't store main worktree twicePatrick Steinhardt, Jun 6, 2024
  99. 10/12 refs: implement removal of ref storagesPatrick Steinhardt, Jun 6, 2024
  100. 11/12 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, Jun 6, 2024
  101. 12/12 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, Jun 6, 2024
  102. Jeff KingJun 6, 2024
  103. Junio C HamanoJun 6, 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.