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

[RFC] git-pack-refs --prune

From
Junio C Hamano <junkio@cox.net>
Date
Sep 18, 2006, 07:25 UTC
Message-ID
<7vy7shr5zw.fsf_-_@assigned-by-dhcp.cox.net>
In-Reply-To
<Pine.LNX.4.64.0609111632050.27779@g5.osdl.org>

"git pack-refs --prune", after successfully packing the existing refs, removes the loose ref files. It tries to protect against race by doing the usual lock_ref_sha1() which makes sure the contents of the ref has not changed since we last looked at.

I am not sure I got the locking right, hence this RFC.

We would probably need to perform some sort of 'sync' after closing and renaming the lockfile to its final location before pruning. Is there a way cheaper than sync(2) to make sure the effect of rename(2) hits the disk platter?

---
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
index 0f5d827..2b3a483 100644
--- a/builtin-pack-refs.c
+++ b/builtin-pack-refs.c
@@ -3,6 +3,15 @@ #include "refs.h"
 
 static FILE *refs_file;
 static const char *result_path, *lock_path;
+static const char builtin_pack_refs_usage[] =
+"git-pack-refs [--prune]";
+
+static int prune;
+struct keepref {
+	struct keepref *next;
+	unsigned char sha1[20];
+	char name[FLEX_ARRAY];
+} *keepref;
 
 static void remove_lock_file(void)
 {
@@ -13,12 +22,50 @@ static void remove_lock_file(void)
 static int handle_one_ref(const char *path, const unsigned char *sha1)
 {
 	fprintf(refs_file, "%s %s\n", sha1_to_hex(sha1), path);
+	if (prune) {
+		int namelen = strlen(path) + 1;
+		struct keepref *n = xcalloc(1, sizeof(*n) + namelen);
+		hashcpy(n->sha1, sha1);
+		strcpy(n->name, path);
+		n->next = keepref;
+		keepref = n;
+	}
 	return 0;
 }
 
+/* make sure nobody touched the ref, and unlink */
+static void prune_ref(struct keepref *r)
+{
+	struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1, 1);
+
+	if (lock) {
+		unlink(git_path(r->name));
+		unlock_ref(lock);
+	}
+}
+
+static void prune_refs(void)
+{
+	struct keepref *r;
+	for (r = keepref; r; r = r->next)
+		prune_ref(r);
+}
+
 int cmd_pack_refs(int argc, const char **argv, const char *prefix)
 {
-	int fd;
+	int fd, i;
+
+	for (i = 1; i < argc; i++) {
+		const char *arg = argv[i];
+		if (!strcmp(arg, "--prune")) {
+			prune = 1;
+			continue;
+		}
+		/* perhaps other parameters later... */
+		break;
+	}
+	if (i != argc)
+		usage(builtin_pack_refs_usage);
 
 	result_path = xstrdup(git_path("packed-refs"));
 	lock_path = xstrdup(mkpath("%s.lock", result_path));
@@ -37,5 +84,7 @@ int cmd_pack_refs(int argc, const char *
 	if (rename(lock_path, result_path) < 0)
 		die("unable to overwrite old ref-pack file (%s)", strerror(errno));
 	lock_path = NULL;
+	if (prune)
+		prune_refs();
 	return 0;
 }
Previous: Linus TorvaldsNext: Linus Torvalds
Message 11 of 21 in “Allow multiple "git_path()" uses”
  1. Linus TorvaldsSep 11, 2006
  2. Start handling references internally as a sorted in-memory listLinus Torvalds, Sep 11, 2006
  3. Linus TorvaldsSep 11, 2006
  4. Junio C HamanoSep 11, 2006
  5. Linus TorvaldsSep 12, 2006
  6. Chris WedgwoodSep 12, 2006
  7. Add support for negative refsLinus Torvalds, Sep 12, 2006
  8. Make ref resolution sanerLinus Torvalds, Sep 12, 2006
  9. Jeff KingSep 12, 2006
  10. Linus TorvaldsSep 12, 2006
  11. [RFC] git-pack-refs --pruneJunio C Hamano, Sep 18, 2006
  12. Linus TorvaldsSep 18, 2006
  13. Junio C HamanoSep 18, 2006
  14. Junio C HamanoSep 21, 2006
  15. 1/5 symbolit-ref: fix resolve_ref conversion.Junio C Hamano, Sep 21, 2006
  16. 2/5 Add callback data to for_each_ref() family.Junio C Hamano, Sep 21, 2006
  17. 3/5 Tell between packed, unpacked and symbolic refs.Junio C Hamano, Sep 21, 2006
  18. 4/5 pack-refs: do not pack symbolic refs.Junio C Hamano, Sep 21, 2006
  19. 5/5 git-pack-refs --pruneJunio C Hamano, Sep 21, 2006
  20. Linus TorvaldsSep 21, 2006
  21. Junio C HamanoSep 22, 2006

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.