X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2Fcmd%2Fhgfs%2Ffs.c;h=9c61233c36139cb95fc1bd54c15145900b334518;hb=5cb6be9ce3bb53909879d6911cc2411f8458ed10;hp=c63048127aab74bc3ba3f43f6f56f8c3b38f0066;hpb=62186910fa0c833f8a5716cb83581494adde1b4e;p=plan9front.git diff --git a/sys/src/cmd/hgfs/fs.c b/sys/src/cmd/hgfs/fs.c index c63048127..9c61233c3 100644 --- a/sys/src/cmd/hgfs/fs.c +++ b/sys/src/cmd/hgfs/fs.c @@ -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; inmap; 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); }