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;
}
--
⑨