shithub: front

Download patch

ref: 0e7690a4f8f056fde7074d9483795123a98fc6ea
parent: de7d3753a5f4e50a84bbea66b6f514a66d30a2b3
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Sep 29 12:47:47 EDT 2024

git/save: pffff. revert last change...

--- a/sys/src/cmd/git/save.c
+++ b/sys/src/cmd/git/save.c
@@ -191,6 +191,21 @@
 	return 0; 
 }
 
+int
+pathelt(char *buf, int nbuf, char *p, int *isdir)
+{
+	char *b;
+
+	b = buf;
+	if(*p == '/')
+		p++;
+	while(*p && *p != '/' && b != buf + nbuf)
+		*b++ = *p++;
+	*b = '\0';
+	*isdir = (*p == '/');
+	return b - buf;
+}
+
 Dirent*
 dirent(Dirent **ent, int *nent, char *name)
 {
@@ -210,64 +225,37 @@
 int
 treeify(Object *t, char **path, char **epath, int off, Hash *h)
 {
-	int nent, ne, slash;
-	char *s, **p, **ep;
+	int r, n, ne, nsub, nent, isdir;
+	char **p, **ep;
+	char elt[256];
+	Object **sub;
 	Dirent *e, *ent;
-	Object *o;
 	Dir *d;
 
+	r = -1;
+	nsub = 0;
 	nent = t->tree->nent;
 	ent = eamalloc(nent, sizeof(*ent));
+	sub = eamalloc((epath - path), sizeof(Object*));
 	memcpy(ent, t->tree->ent, nent*sizeof(*ent));
 	for(p = path; p != epath; p = ep){
-		s = *p;
-
-		/*
-		 * paths have been normalized already,
-		 * no leading or double-slashes allowed.
-		 */
-		assert(s[off] != '\0' && s[off] != '/');
-
-		/* get next path element length (from off until '/' or nul) */
-		for(ne = 1; s[off+ne] != '\0' && s[off+ne] != '/'; ne++)
-			ne++;
-
-		/* truncate at '/' or nul */
-		slash = s[off + ne];
-		s[off + ne] = '\0';
-
-		/* skip over children (having s as prefix) */
-		for(ep = p + 1; ep != epath; ep++){
-			if(strncmp(s, *ep, off + ne) != 0)
+		ne = pathelt(elt, sizeof(elt), *p + off, &isdir);
+		for(ep = p; ep != epath; ep++){
+			if(strncmp(elt, *ep + off, ne) != 0)
 				break;
 			if((*ep)[off+ne] != '\0' && (*ep)[off+ne] != '/')
 				break;
 		}
-
-		e = dirent(&ent, &nent, s + off);
-
-		d = dirstat(s);
-		if(d == nil){
-			/* delete */
-			e->name = nil;
-
-			s[off + ne] = slash;
-			continue;
-		}
-
+		e = dirent(&ent, &nent, elt);
 		if(e->islink)
-			sysfatal("symlinks may not be modified: %s", s);
+			sysfatal("symlinks may not be modified: %s", *path);
 		if(e->ismod)
-			sysfatal("submodules may not be modified: %s", s);
-
-		s[off + ne] = slash;
-
-		if(slash && (d->mode & DMDIR) != 0){
-			free(d);
+			sysfatal("submodules may not be modified: %s", *path);
+		if(isdir){
 			e->mode = DMDIR | 0755;
-			o = readobject(e->h);
-			if(o == nil || o->type != GTree)
-				o = emptydir();
+			sub[nsub] = readobject(e->h);
+			if(sub[nsub] == nil || sub[nsub]->type != GTree)
+				sub[nsub] = emptydir();
 			/*
 			 * if after processing deletions, a tree is empty,
 			 * mark it for removal from the parent.
@@ -276,21 +264,29 @@
 			 * but this is fine -- and ensures that an empty
 			 * repository will continue to work.
 			 */
-			if(treeify(o, p, ep, off + ne + 1, &e->h) == 0)
+			n = treeify(sub[nsub], p, ep, off + ne + 1, &e->h);
+			if(n == 0)
 				e->name = nil;
+			else if(n == -1)
+				goto err;
 		}else{
-			if((d->mode & DMDIR) == 0 && tracked(s))
-				blobify(d, s, &e->mode, &e->h);
+			d = dirstat(*p);
+			if(d != nil && tracked(*p))
+				blobify(d, *p, &e->mode, &e->h);
 			else
 				e->name = nil;
 			free(d);
 		}
 	}
-	if(nent == 0)
-		sysfatal("%.*s: refusing to update empty directory", off, *path);
-	nent = writetree(ent, nent, h);
-	free(ent);
-	return nent;		
+	if(nent == 0){
+		werrstr("%.*s: empty directory", off, *path);
+		goto err;
+	}
+
+	r = writetree(ent, nent, h);
+err:
+	free(sub);
+	return r;		
 }
 
 
--