]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/hgfs/fs.c
hgfs: fix metaheader offset for log
[plan9front.git] / sys / src / cmd / hgfs / fs.c
index c63048127aab74bc3ba3f43f6f56f8c3b38f0066..9c61233c36139cb95fc1bd54c15145900b334518 100644 (file)
@@ -13,6 +13,7 @@
 enum {
        Qroot,
                Qrev,
+                       Qrev0,
                        Qrev1,
                        Qrev2,
                        Qlog,
@@ -27,6 +28,7 @@ enum {
 static char *nametab[] = {
        "/",
                nil,
+                       "rev",
                        "rev1",
                        "rev2",
                        "log",
@@ -42,15 +44,20 @@ static Revlog changelog;
 static Revlog manifest;
 static Revlog *revlogs;
 
-static char dothg[MAXPATH];
+static char workdir[MAXPATH];
+static int mangle = 0;
 
 static Revlog*
 getrevlog(Revnode *nd)
 {
        char buf[MAXPATH];
        Revlog *rl;
+       int mang;
 
-       nodepath(seprint(buf, buf+sizeof(buf), "%s/store/data", dothg), buf+sizeof(buf), nd);
+       mang = mangle;
+Again:
+       nodepath(seprint(buf, buf+sizeof(buf), "%s/.hg/store/data", workdir),
+               buf+sizeof(buf), nd, mang);
        for(rl = revlogs; rl; rl = rl->next)
                if(strcmp(buf, rl->path) == 0)
                        break;
@@ -59,10 +66,14 @@ getrevlog(Revnode *nd)
                memset(rl, 0, sizeof(*rl));
                if(revlogopen(rl, buf, OREAD) < 0){
                        free(rl);
+                       if(mang++ == 0)
+                               goto Again;
                        return nil;
                }
                rl->next = revlogs;
                revlogs = rl;
+               if(mang)
+                       mangle = 1;
        } else
                revlogupdate(rl);
        incref(rl);
@@ -181,6 +192,7 @@ fsmkqid(Qid *q, int level, void *aux)
        case Qchanges:
                q->type = QTDIR;
                if(0){
+       case Qrev0:
        case Qrev1:
        case Qrev2:
        case Qlog:
@@ -189,7 +201,7 @@ fsmkqid(Qid *q, int level, void *aux)
                q->type = 0;
                }
                ri = aux;
-               q->path = *((uvlong*)ri->chash) + (level - Qrev);
+               q->path = hash2qid(ri->chash) + (level - Qrev);
                q->vers = 0;
                break;
        case Qtree:
@@ -228,7 +240,7 @@ fsmkdir(Dir *d, int level, void *aux)
        fsmkqid(&d->qid, level, aux);
 
        d->mode = 0444;
-       if(d->qid.type == QTDIR)
+       if(d->qid.type & QTDIR)
                d->mode |= DMDIR | 0111;
 
        ri = nil;
@@ -236,6 +248,7 @@ fsmkdir(Dir *d, int level, void *aux)
        case Qroot:
                goto Namegen;
        case Qrev:
+       case Qrev0:
        case Qrev1:
        case Qrev2:
                ri = aux;
@@ -285,8 +298,17 @@ fsmkdir(Dir *d, int level, void *aux)
                        if((rl = getrevlog(nd)) == nil)
                                break;
                        if((rev = hashrev(rl, nd->hash)) >= 0){
-                               if(level == Qtree)
+                               if(level == Qtree){
+                                       /*
+                                        * BUG: this is not correct. mercurial might
+                                        * prefix the data log with random \1\n escaped
+                                        * metadata strings (see fmetaheader()) and the flen
+                                        * *includes* the metadata part. we try to compensate
+                                        * for this once the revision got extracted and
+                                        * subtract the metadata header in fsstat().
+                                        */
                                        d->length = rl->map[rev].flen;
+                               }
                                ri = getrevinfo(rl->map[rev].linkrev);
                        }
                        closerevlog(rl);
@@ -333,6 +355,7 @@ fsattach(Req *r)
        rf->rlog = nil;
 
        rf->fd = -1;
+       rf->doff = 0;
        rf->buf = nil;
 
        r->fid->aux = rf;
@@ -348,8 +371,11 @@ fsstat(Req *r)
        rf = r->fid->aux;
        if(rf->level < Qtree)
                fsmkdir(&r->d, rf->level,  rf->info);
-       else
+       else {
                fsmkdir(&r->d, rf->level,  rf->node);
+               if(rf->level == Qtree)
+                       r->d.length -= rf->doff;
+       }
        respond(r, nil);
 }
 
@@ -368,7 +394,7 @@ findrev(Revlog *rl, char *name)
        rev = -1;
        if(s = strchr(name, '.'))
                name = s+1;
-       if((n = strhash(name, hash)) > 0){
+       if((n = hex2hash(name, hash)) > 0){
                for(i=0; i<rl->nmap; i++){
                        if(memcmp(rl->map[i].hash, hash, n) == 0){
                                if(rev < 0)
@@ -392,7 +418,7 @@ fswalk1(Fid *fid, char *name, Qid *qid)
        Revfile *rf;
        int i, level;
 
-       if(!(fid->qid.type&QTDIR))
+       if((fid->qid.type & QTDIR) == 0)
                return "walk in non-directory";
 
        rf = fid->aux;
@@ -477,7 +503,13 @@ fswalk1(Fid *fid, char *name, Qid *qid)
                                                        sname += 3;
                                                }
                                                snprint(buf, sizeof(buf), "%.*s", i, name);
-                                               i = atoi(sname);
+                                               if(*sname == 0)
+                                                       i = 0;
+                                               else {
+                                                       i = strtol(sname, &sname, 10);
+                                                       if(i < 0 || *sname != '\0')
+                                                               goto Notfound;
+                                               }
                                                sname = buf;
                                                goto Searchtree;
                                        }
@@ -637,6 +669,7 @@ fsread(Req *r)
                dirread9p(r, revgen, rf->info);
                respond(r, nil);
                return;
+       case Qrev0:
        case Qrev1:
        case Qrev2:
                s = nil;
@@ -645,7 +678,7 @@ fsread(Req *r)
                i = hashrev(&changelog, rf->info->chash);
                if(rf->level == Qrev1)
                        i = changelog.map[i].p1rev;
-               else
+               else if(rf->level == Qrev2)
                        i = changelog.map[i].p2rev;
        Revgen:
                s = fsmkrevname(buf, sizeof(buf), i);
@@ -659,13 +692,13 @@ fsread(Req *r)
                        len = 0;
                else if((off + len) >= rf->info->loglen)
                        len = rf->info->loglen - off;
-               off += rf->info->logoff;
                if(rf->fd >= 0)
                        goto Fdgen;
                if((rf->fd = revlogopentemp(&changelog, hashrev(&changelog, rf->info->chash))) < 0){
                        responderror(r);
                        return;
                }
+               rf->doff = rf->info->logoff;
                goto Fdgen;
        case Qwho:
                s = rf->info->who;
@@ -692,8 +725,9 @@ fsread(Req *r)
                        responderror(r);
                        return;
                }
+               rf->doff = fmetaheader(rf->fd);
        Fdgen:
-               if((n = pread(rf->fd, r->ofcall.data, len, off)) < 0){
+               if((n = pread(rf->fd, r->ofcall.data, len, off + rf->doff)) < 0){
                        responderror(r);
                        return;
                }
@@ -732,7 +766,7 @@ main(int argc, char *argv[])
        fmtinstall('H', Hfmt);
 
        srv = nil;
-       mtpt = "/n/hg";
+       mtpt = "/mnt/hg";
 
        ARGBEGIN {
        case 'D':
@@ -748,30 +782,17 @@ main(int argc, char *argv[])
                usage();
        } ARGEND;
 
-       if(*argv){
-               snprint(dothg, sizeof(dothg), "%s/.hg", *argv);
-       }else{
-               if(getwd(buf, sizeof(buf)) == nil)
-                       sysfatal("can't get working dir: %r");
-               for(;;){
-                       char *s;
-
-                       snprint(dothg, sizeof(dothg), "%s/.hg", buf);
-                       if(access(dothg, AEXIST) == 0)
-                               break;
-                       if((s = strrchr(buf, '/')) == nil)
-                               break;
-                       *s = 0;
-               }
-       }
-       cleanname(dothg);
+       if(getworkdir(workdir, *argv) < 0)
+               sysfatal("can't find workdir: %r");
 
-       snprint(buf, sizeof(buf), "%s/store/00changelog", dothg);
+       snprint(buf, sizeof(buf), "%s/.hg/store/00changelog", workdir);
        if(revlogopen(&changelog, buf, OREAD) < 0)
                sysfatal("can't open changelog: %r\n");
-       snprint(buf, sizeof(buf), "%s/store/00manifest", dothg);
+       snprint(buf, sizeof(buf), "%s/.hg/store/00manifest", workdir);
        if(revlogopen(&manifest, buf, OREAD) < 0)
                sysfatal("can't open menifest: %r\n");
 
        postmountsrv(&fs, srv, mtpt, MREPL);
+
+       exits(0);
 }