shithub: git9

Download patch

ref: 0c37f24b47058890e08f2bbb38ecbc21c4baa9b0
parent: 44a6f2799e78fb097b5d99914dfe83cc1436b2a7
author: Ori Bernstein <[email protected]>
date: Sat Jan 16 15:42:41 EST 2021

git/save: prune empty directories on commit

Until now, git9 did not remove directories when
they became empty. This commit prunes directories
when the last file gets removed.

Eventually, we should just handle empty directories
correctly, allowing them to be created, added, and
removed -- but this should tide us over until that
code gets written.

--- a/save.c
+++ b/save.c
@@ -118,7 +118,7 @@
 	}
 }
 
-void
+int
 writetree(Dirent *ent, int nent, Hash *h)
 {
 	char *t, *txt, *etxt, hdr[128];
@@ -148,6 +148,7 @@
 	nhdr = snprint(hdr, sizeof(hdr), "%T %lld", GTree, (vlong)(t - txt)) + 1;
 	writeobj(h, hdr, nhdr, txt, t - txt);
 	free(txt);
+	return nent;
 }
 
 void
@@ -230,7 +231,7 @@
 int
 treeify(Object *t, char **path, char **epath, int off, Hash *h)
 {
-	int r, ne, nsub, nent, isdir;
+	int r, n, ne, nsub, nent, isdir;
 	char **p, **ep;
 	char elt[256];
 	Object **sub;
@@ -261,7 +262,18 @@
 			sub[nsub] = readobject(e->h);
 			if(sub[nsub] == nil || sub[nsub]->type != GTree)
 				sub[nsub] = emptydir();
-			if(treeify(sub[nsub], p, ep, off + ne + 1, &e->h) == -1)
+			/*
+			 * if after processing deletions, a tree is empty,
+			 * mark it for removal from the parent.
+			 *
+			 * Note, it is still written to the object store,
+			 * but this is fine -- and ensures that an empty
+			 * repository will continue to work.
+			 */
+			n = treeify(sub[nsub], p, ep, off + ne + 1, &e->h);
+			if(n == 0)
+				e->name = nil;
+			else if(n == -1)
 				goto err;
 		}else{
 			d = dirstat(*p);
@@ -277,8 +289,7 @@
 		goto err;
 	}
 
-	writetree(ent, nent, h);
-	r = 0;
+	r = writetree(ent, nent, h);
 err:
 	free(sub);
 	return r;