ref: 0c37f24b47058890e08f2bbb38ecbc21c4baa9b0
parent: 44a6f2799e78fb097b5d99914dfe83cc1436b2a7
author: Ori Bernstein <ori@eigenstate.org>
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;