]> git.lizzy.rs Git - plan9front.git/commitdiff
hgfs: get previous file revisions with appending .n or .revn
authorcinap_lenrek <cinap_lenrek@localhost>
Tue, 28 Jun 2011 01:51:05 +0000 (03:51 +0200)
committercinap_lenrek <cinap_lenrek@localhost>
Tue, 28 Jun 2011 01:51:05 +0000 (03:51 +0200)
sys/src/cmd/hgfs/dat.h
sys/src/cmd/hgfs/fns.h
sys/src/cmd/hgfs/fs.c
sys/src/cmd/hgfs/revlog.c
sys/src/cmd/hgfs/tree.c

index 9d19400447e45adf8e6719f018410afdfce8b4c0..b2f0be931412605314d58373f5a451da8b571a5a 100644 (file)
@@ -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;
index 00bac4601a047369507ef019991cc4e66d40670e..4b3450d0e9bd7044e2f9f89e97714c10ec1521f3 100644 (file)
@@ -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);
index 46478be6c2790e8ea09a2fe85c6fcad378feab26..f6fa011c40b9b14a4fc676bfd9f1b0c8dad1ec85 100644 (file)
@@ -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);
index 8153585686db2654713c8bd51a0c156d63c07134..8de571eb77ca1899d610cadc8f7dec6e7d258efb 100644 (file)
@@ -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*
index 5e5a3685670c1b12c265fb9c10ff39f578a2b036..62a3ab97f20045bf0266bb7d7a00b1a1998320ca 100644 (file)
@@ -22,7 +22,7 @@ nodepath(char *s, char *e, Revnode *nd)
 
        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 @@ nodepath(char *s, char *e, Revnode *nd)
        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 @@ 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);
 }