ref: 6d91601a775db1fa873f64f90da764ece2c2da6d
parent: d0485d345db63b0ee82301251339e72d6093107d
author: cinap_lenrek <cinap_lenrek@localhost>
date: Mon Jun 27 23:51:05 EDT 2011
hgfs: get previous file revisions with appending .n or .revn
--- a/sys/src/cmd/hgfs/dat.h
+++ b/sys/src/cmd/hgfs/dat.h
@@ -33,6 +33,10 @@
struct Revlog
{
+ Ref;
+
+ char *path;
+
int ifd;
int dfd;
@@ -51,6 +55,7 @@
Revnode *up;
Revnode *next;
Revnode *down;
+ Revnode *before;
char mode;
};
@@ -82,6 +87,7 @@
Revinfo *info;
Revtree *tree;
Revnode *node;
+ Revlog *rlog;
char *buf;
int fd;
--- a/sys/src/cmd/hgfs/fns.h
+++ b/sys/src/cmd/hgfs/fns.h
@@ -25,6 +25,7 @@
/* 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);
--- a/sys/src/cmd/hgfs/fs.c
+++ b/sys/src/cmd/hgfs/fs.c
@@ -21,9 +21,10 @@
Qfiles,
Qchanges,
Qtree,
+ Qtreerev,
};
-static char *nametab[Qtree+1] = {
+static char *nametab[] = {
"/",
nil,
"rev1",
@@ -34,11 +35,41 @@
"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 @@
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 @@
case Qrev1:
case Qrev2:
ri = aux;
+ Revgen:
rev = hashrev(&changelog, ri->chash);
if(level == Qrev1)
rev = changelog.map[rev].p1rev;
@@ -208,6 +241,8 @@
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 @@
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 @@
rf->info = nil;
rf->tree = nil;
rf->node = nil;
+ rf->rlog = nil;
rf->fd = -1;
rf->buf = nil;
@@ -326,9 +364,11 @@
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 @@
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 @@
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 @@
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 @@
Revfile *rf;
if(rf = fid->aux){
+ closerevlog(rf->rlog);
closerevtree(rf->tree);
if(rf->fd >= 0)
close(rf->fd);
@@ -508,7 +596,6 @@
{
Revfile *rf;
char buf[MAXPATH];
- Revlog rl;
char *s;
int i, n;
vlong off;
@@ -539,10 +626,16 @@
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 @@
}
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){
+ if((rf->fd = revlogopentemp(rf->rlog, hashrev(rf->rlog, rf->node->hash))) < 0){
responderror(r);
return;
}
- if((rf->fd = revlogopentemp(&rl, hashrev(&rl, 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);
--- a/sys/src/cmd/hgfs/revlog.c
+++ b/sys/src/cmd/hgfs/revlog.c
@@ -68,7 +68,10 @@
}
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 @@
free(r->map);
r->map = nil;
r->nmap = 0;
+ free(r->path);
}
uchar*
--- a/sys/src/cmd/hgfs/tree.c
+++ b/sys/src/cmd/hgfs/tree.c
@@ -22,7 +22,7 @@
p = nd->name;
for(i=0; i<nelem(frogs); i++)
- if(strcmp(frogs[i], p) == 0)
+ if(strncmp(frogs[i], p, strlen(frogs[i])) == 0)
return seprint(s, e, "%.2s~%.2x%s", p, p[2], p+3);
for(; s+4 < e && *p; p++){
@@ -43,10 +43,35 @@
return s;
}
+Revnode*
+mknode(char *name, uchar *hash, char mode)
+{
+ Revnode *d;
+ char *s;
+
+ d = malloc(sizeof(*d) + (hash ? HASHSZ : 0) + (name ? strlen(name)+1 : 0));
+ d->up = 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 @@
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 @@
c->next = d->down;
d->down = c;
}
-
if(c->hash){
p = c;
p->path = *((uvlong*)c->hash);
@@ -170,21 +182,12 @@
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 @@
return;
freenode(nd->down);
freenode(nd->next);
+ freenode(nd->before);
free(nd);
}