From: cinap_lenrek Date: Tue, 28 Jun 2011 01:51:05 +0000 (+0200) Subject: hgfs: get previous file revisions with appending .n or .revn X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=6d91601a775db1fa873f64f90da764ece2c2da6d;p=plan9front.git hgfs: get previous file revisions with appending .n or .revn --- diff --git a/sys/src/cmd/hgfs/dat.h b/sys/src/cmd/hgfs/dat.h index 9d1940044..b2f0be931 100644 --- a/sys/src/cmd/hgfs/dat.h +++ b/sys/src/cmd/hgfs/dat.h @@ -33,6 +33,10 @@ struct Revmap struct Revlog { + Ref; + + char *path; + int ifd; int dfd; @@ -51,6 +55,7 @@ struct Revnode Revnode *up; Revnode *next; Revnode *down; + Revnode *before; char mode; }; @@ -82,6 +87,7 @@ struct Revfile Revinfo *info; Revtree *tree; Revnode *node; + Revlog *rlog; char *buf; int fd; diff --git a/sys/src/cmd/hgfs/fns.h b/sys/src/cmd/hgfs/fns.h index 00bac4601..4b3450d0e 100644 --- a/sys/src/cmd/hgfs/fns.h +++ b/sys/src/cmd/hgfs/fns.h @@ -25,6 +25,7 @@ Revinfo *loadrevinfo(Revlog *changelog, int rev); /* tree */ char *nodepath(char *s, char *e, Revnode *nd); +Revnode *mknode(char *name, uchar *hash, char mode); Revtree *loadfilestree(Revlog *changelog, Revlog *manifest, Revinfo *ri); Revtree *loadchangestree(Revlog *changelog, Revlog *manifest, Revinfo *ri); void closerevtree(Revtree *t); diff --git a/sys/src/cmd/hgfs/fs.c b/sys/src/cmd/hgfs/fs.c index 46478be6c..f6fa011c4 100644 --- a/sys/src/cmd/hgfs/fs.c +++ b/sys/src/cmd/hgfs/fs.c @@ -21,9 +21,10 @@ enum { Qfiles, Qchanges, Qtree, + Qtreerev, }; -static char *nametab[Qtree+1] = { +static char *nametab[] = { "/", nil, "rev1", @@ -34,11 +35,41 @@ static char *nametab[Qtree+1] = { "files", "changes", nil, + nil, }; static Revlog changelog; static Revlog manifest; +static Revlog* +getrevlog(Revnode *nd) +{ + char path[MAXPATH]; + Revlog *rl; + + nodepath(seprint(path, path+MAXPATH, ".hg/store/data"), path+MAXPATH, nd); + rl = emalloc9p(sizeof(*rl)); + memset(rl, 0, sizeof(*rl)); + if(revlogopen(rl, path, OREAD) < 0){ + fprint(2, "getrevlod %s: %r\n", path); + free(rl); + return nil; + } + incref(rl); + return rl; +} + +static void +closerevlog(Revlog *rl) +{ + if(rl == nil) + return; + if(decref(rl)) + return; + revlogclose(rl); + free(rl); +} + static Revinfo* getrevinfo(int rev) { @@ -146,13 +177,14 @@ fsmkqid(Qid *q, int level, void *aux) q->vers = 0; break; case Qtree: + case Qtreerev: nd = aux; - if(nd->down){ + if(level == Qtree && nd->down){ q->type = QTDIR; } else { q->type = 0; } - q->path = nd->path; + q->path = nd->path + (level - Qtree); q->vers = 0; break; } @@ -183,6 +215,7 @@ fsmkdir(Dir *d, int level, void *aux) case Qrev1: case Qrev2: ri = aux; + Revgen: rev = hashrev(&changelog, ri->chash); if(level == Qrev1) rev = changelog.map[rev].p1rev; @@ -208,6 +241,8 @@ fsmkdir(Dir *d, int level, void *aux) s = ri->why; Strgen: d->length = s ? strlen(s)+1 : 0; + if(level == Qtreerev) + break; case Qfiles: case Qchanges: ri = aux; @@ -216,22 +251,24 @@ fsmkdir(Dir *d, int level, void *aux) d->name = estrdup9p(nametab[level]); break; case Qtree: + case Qtreerev: nd = aux; d->name = estrdup9p(nd->name); if(nd->mode == 'x') d->mode |= 0111; if(nd->hash){ - char path[MAXPATH]; - Revlog rl; + Revlog *rl; - nodepath(seprint(path, path+MAXPATH, ".hg/store/data"), path+MAXPATH, nd); - if(revlogopen(&rl, path, OREAD) < 0) + if((rl = getrevlog(nd)) == nil) break; - if((rev = hashrev(&rl, nd->hash)) >= 0){ - d->length = rl.map[rev].flen; - ri = getrevinfo(rl.map[rev].linkrev); + if((rev = hashrev(rl, nd->hash)) >= 0){ + if(level == Qtree) + d->length = rl->map[rev].flen; + ri = getrevinfo(rl->map[rev].linkrev); } - revlogclose(&rl); + closerevlog(rl); + if(level == Qtreerev && ri) + goto Revgen; } break; } @@ -270,6 +307,7 @@ fsattach(Req *r) rf->info = nil; rf->tree = nil; rf->node = nil; + rf->rlog = nil; rf->fd = -1; rf->buf = nil; @@ -326,9 +364,11 @@ static char* fswalk1(Fid *fid, char *name, Qid *qid) { Revtree* (*loadfn)(Revlog *, Revlog *, Revinfo *); - Revfile *rf; + char path[MAXPATH]; Revnode *nd; - int i; + Revfile *rf; + char *sname; + int i, level; if(!(fid->qid.type&QTDIR)) return "walk in non-directory"; @@ -349,6 +389,8 @@ fswalk1(Fid *fid, char *name, Qid *qid) rf->level = Qrev; break; case Qtree: + closerevlog(rf->rlog); + rf->rlog = nil; if((rf->node = rf->node->up) == rf->tree->root) rf->level = rf->tree->level; break; @@ -396,13 +438,56 @@ fswalk1(Fid *fid, char *name, Qid *qid) case Qtree: case Qfiles: case Qchanges: + i = 0; + level = Qtree; + sname = name; + Searchtree: for(nd = rf->node->down; nd; nd = nd->next) - if(strcmp(nd->name, name) == 0) + if(strcmp(nd->name, sname) == 0) break; - if(nd == nil) + if(nd == nil){ + if(sname == name){ + sname = strrchr(name, '.'); + if((i = sname - name) > 0){ + sname++; + if(strncmp(sname, "rev", 3) == 0){ + level = Qtreerev; + sname += 3; + } + snprint(path, sizeof(path), "%.*s", i, name); + i = atoi(sname); + sname = path; + goto Searchtree; + } + } + goto Notfound; + } + if(nd->hash){ + Revnode *nb; + int j; + + if((rf->rlog = getrevlog(nd)) == nil) + goto Notfound; + j = hashrev(rf->rlog, nd->hash) - i; + if(i < 0 || j < 0 || j >= rf->rlog->nmap){ + closerevlog(rf->rlog); + rf->rlog = nil; + goto Notfound; + } + for(nb = nd; nb; nb = nb->before) + if(hashrev(rf->rlog, nb->hash) == j) + break; + if(nb == nil){ + nb = mknode(nd->name, revhash(rf->rlog, j), nd->mode); + nb->up = nd->up; + nb->before = nd->before; + nd->before = nb; + } + nd = nb; + } else if(i || level != Qtree) goto Notfound; rf->node = nd; - rf->level = Qtree; + rf->level = level; break; } } @@ -425,6 +510,8 @@ fsclone(Fid *oldfid, Fid *newfid) if(orf = oldfid->aux){ rf = emalloc9p(sizeof(*rf)); *rf = *orf; + if(rf->rlog) + incref(rf->rlog); if(rf->tree) incref(rf->tree); if(rf->fd >= 0) @@ -442,6 +529,7 @@ fsdestroyfid(Fid *fid) Revfile *rf; if(rf = fid->aux){ + closerevlog(rf->rlog); closerevtree(rf->tree); if(rf->fd >= 0) close(rf->fd); @@ -508,7 +596,6 @@ fsread(Req *r) { Revfile *rf; char buf[MAXPATH]; - Revlog rl; char *s; int i, n; vlong off; @@ -539,10 +626,16 @@ fsread(Req *r) i = changelog.map[i].p1rev; else i = changelog.map[i].p2rev; + Revgen: if(i >= 0) snprint(s = buf, sizeof(buf), "%d.%H", i, changelog.map[i].hash); } goto Strgen; + case Qtreerev: + s = nil; + if((i = hashrev(rf->rlog, rf->node->hash)) >= 0) + i = rf->rlog->map[i].linkrev; + goto Revgen; case Qlog: if(off >= rf->info->loglen) len = 0; @@ -577,17 +670,10 @@ fsread(Req *r) } if(rf->fd >= 0) goto Fdgen; - nodepath(seprint(buf, buf+sizeof(buf), ".hg/store/data"), buf+sizeof(buf), rf->node); - if(revlogopen(&rl, buf, OREAD) < 0){ - responderror(r); - return; - } - if((rf->fd = revlogopentemp(&rl, hashrev(&rl, rf->node->hash))) < 0){ + if((rf->fd = revlogopentemp(rf->rlog, hashrev(rf->rlog, rf->node->hash))) < 0){ responderror(r); - revlogclose(&rl); return; } - revlogclose(&rl); Fdgen: if((n = pread(rf->fd, r->ofcall.data, len, off)) < 0){ responderror(r); diff --git a/sys/src/cmd/hgfs/revlog.c b/sys/src/cmd/hgfs/revlog.c index 815358568..8de571eb7 100644 --- a/sys/src/cmd/hgfs/revlog.c +++ b/sys/src/cmd/hgfs/revlog.c @@ -68,7 +68,10 @@ revlogopen(Revlog *r, char *path, int mode) } path[strlen(path)-1] = 'd'; r->dfd = open(path, mode); - free(path); + + path[strlen(path)-2] = 0; + r->path = path; + r->ioff = 0; r->nmap = 0; r->map = nil; @@ -90,6 +93,7 @@ revlogclose(Revlog *r) free(r->map); r->map = nil; r->nmap = 0; + free(r->path); } uchar* diff --git a/sys/src/cmd/hgfs/tree.c b/sys/src/cmd/hgfs/tree.c index 5e5a36856..62a3ab97f 100644 --- a/sys/src/cmd/hgfs/tree.c +++ b/sys/src/cmd/hgfs/tree.c @@ -22,7 +22,7 @@ nodepath(char *s, char *e, Revnode *nd) p = nd->name; for(i=0; iup = d->down = d->next = d->before = nil; + s = (char*)&d[1]; + if(hash){ + d->path = *((uvlong*)hash); + memmove(d->hash = (uchar*)s, hash, HASHSZ); + s += HASHSZ; + } else { + d->path = 1; + d->hash = nil; + } + if(name) + strcpy(d->name = s, name); + else + d->name = nil; + d->mode = mode; + return d; +} + static void addnode(Revnode *d, char *path, uchar *hash, char mode) { - char *slash, *x; + char *slash; Revnode *c, *p; while(path && *path){ @@ -57,20 +82,8 @@ addnode(Revnode *d, char *path, uchar *hash, char mode) if(strcmp(c->name, path) == 0) break; if(c == nil){ - c = malloc(sizeof(*c) + (!slash ? HASHSZ : 0) + strlen(path)+1); - c->path = 1; - x = (char*)&c[1]; - if(!slash){ - c->mode = mode; - memmove(c->hash = (uchar*)x, hash, HASHSZ); - x += HASHSZ; - }else{ - c->mode = 0; - c->hash = nil; - } - strcpy(c->name = x, path); + c = mknode(path, slash ? nil : hash, slash ? 0 : mode); c->up = d; - c->down = nil; if(p){ c->next = p->next; p->next = c; @@ -78,7 +91,6 @@ addnode(Revnode *d, char *path, uchar *hash, char mode) c->next = d->down; d->down = c; } - if(c->hash){ p = c; p->path = *((uvlong*)c->hash); @@ -170,21 +182,12 @@ loadtree(Revlog *manifest, Revinfo *ri, Hashstr **ht, int nh) t = malloc(sizeof(*t)); memset(t, 0, sizeof(*t)); incref(t); - - t->root = malloc(sizeof(Revnode)); - t->root->path = 0; - t->root->name = 0; - t->root->up = nil; - t->root->down = nil; - t->root->next = nil; - t->root->hash = nil; - + t->root = mknode(nil, nil, 0); if(loadmanifest(t->root, fd, ht, nh) < 0){ close(fd); closerevtree(t); return nil; } - close(fd); return t; @@ -259,6 +262,7 @@ freenode(Revnode *nd) return; freenode(nd->down); freenode(nd->next); + freenode(nd->before); free(nd); }