26 static char *nametab[Qtree+1] = {
39 static Revlog changelog;
40 static Revlog manifest;
47 if(rev < 0 || rev >= changelog.nmap)
49 if(ri = changelog.map[rev].aux)
51 if(ri = loadrevinfo(&changelog, rev))
52 changelog.map[rev].aux = ri;
57 getrevtree(Revtree *(*fn)(Revlog *, Revlog *, Revinfo *), Revinfo *ri)
69 for(i=j=0; i<nelem(cache); i++){
70 if(cache[i].t == nil){
74 if(cache[i].f == fn && cache[i].i == ri){
79 if(cache[j].t && cache[i].g < cache[j].g)
82 if((rt = (*fn)(&changelog, &manifest, ri)) == nil)
85 closerevtree(cache[j].t);
103 while(x = strchr(s, '<'))
106 if(x = strchr(s, '>'))
108 if(x = strchr(s, '@'))
110 if(x = strchr(s, '\n'))
113 if(s == nil || *s == 0){
115 s = estrdup9p("hgfs");
121 fsmkqid(Qid *q, int level, void *aux)
145 q->path = *((uvlong*)ri->chash) + (level - Qrev);
162 fsmkdir(Dir *d, int level, void *aux)
169 memset(d, 0, sizeof(*d));
171 fsmkqid(&d->qid, level, aux);
174 if(d->qid.type == QTDIR)
175 d->mode |= DMDIR | 0111;
186 rev = hashrev(&changelog, ri->chash);
188 rev = changelog.map[rev].p1rev;
189 else if(level == Qrev2)
190 rev = changelog.map[rev].p2rev;
192 snprint(s = buf, sizeof(buf), "%d.%H", rev, changelog.map[rev].hash);
194 d->name = estrdup9p(buf);
200 d->length = ri->loglen;
210 d->length = s ? strlen(s)+1 : 0;
216 d->name = estrdup9p(nametab[level]);
220 d->name = estrdup9p(nd->name);
227 nodepath(seprint(path, path+MAXPATH, ".hg/store/data"), path+MAXPATH, nd);
228 if(revlogopen(&rl, path, OREAD) < 0)
230 if((rev = hashrev(&rl, nd->hash)) >= 0){
231 d->length = rl.map[rev].flen;
232 ri = getrevinfo(rl.map[rev].linkrev);
240 d->atime = d->mtime = ri->when;
241 d->muid = fsmkuid(ri->who);
242 d->uid = fsmkuid(ri->who);
244 d->atime = d->mtime = time(0);
247 d->uid = fsmkuid(nil);
249 d->gid = fsmkuid(nil);
251 d->muid = fsmkuid(nil);
259 if(r->ifcall.aname && r->ifcall.aname[0]){
260 respond(r, "invalid attach specifier");
263 r->fid->qid.path = Qroot;
264 r->fid->qid.type = QTDIR;
265 r->fid->qid.vers = 0;
266 r->ofcall.qid = r->fid->qid;
268 rf = emalloc9p(sizeof(*rf));
288 if(rf->level < Qtree)
289 fsmkdir(&r->d, rf->level, rf->info);
291 fsmkdir(&r->d, rf->level, rf->node);
296 findrev(Revlog *rl, char *name)
302 if(strcmp(name, "tip") == 0)
304 rev = strtol(name, &s, 10);
305 if(s > name && (*s == 0 || ispunct(*s)))
308 if(s = strchr(name, '.'))
310 if((n = strhash(name, hash)) > 0){
311 for(i=0; i<rl->nmap; i++){
312 if(memcmp(rl->map[i].hash, hash, n) == 0){
326 fswalk1(Fid *fid, char *name, Qid *qid)
328 Revtree* (*loadfn)(Revlog *, Revlog *, Revinfo *);
333 if(!(fid->qid.type&QTDIR))
334 return "walk in non-directory";
337 if(strcmp(name, "..") == 0){
347 closerevtree(rf->tree);
352 if((rf->node = rf->node->up) == rf->tree->root)
353 rf->level = rf->tree->level;
359 revlogupdate(&changelog);
360 revlogupdate(&manifest);
362 i = findrev(&changelog, name);
363 if(rf->info = getrevinfo(i)){
368 return "directory entry not found";
371 for(i = Qrev+1; i < Qtree; i++){
372 if(nametab[i] == nil)
374 if(strcmp(name, nametab[i]) == 0)
382 loadfn = loadfilestree;
385 loadfn = loadchangestree;
389 if((rf->tree = getrevtree(loadfn, rf->info)) == nil)
391 rf->node = rf->tree->root;
399 for(nd = rf->node->down; nd; nd = nd->next)
400 if(strcmp(nd->name, name) == 0)
410 if(rf->level < Qtree)
411 fsmkqid(qid, rf->level, rf->info);
413 fsmkqid(qid, rf->level, rf->node);
420 fsclone(Fid *oldfid, Fid *newfid)
425 if(orf = oldfid->aux){
426 rf = emalloc9p(sizeof(*rf));
431 rf->fd = dup(rf->fd, -1);
433 rf->buf = estrdup9p(rf->buf);
440 fsdestroyfid(Fid *fid)
445 closerevtree(rf->tree);
459 switch(r->ifcall.mode & 3){
461 if(rf->node == nil || rf->node->mode != 'x')
467 respond(r, "permission denied");
471 rootgen(int i, Dir *d, void *)
475 if((ri = getrevinfo(i)) == nil)
477 fsmkdir(d, Qrev, ri);
482 revgen(int i, Dir *d, void *aux)
492 treegen(int i, Dir *d, void *aux)
502 fsmkdir(d, Qtree, nd);
517 off = r->ifcall.offset;
518 len = r->ifcall.count;
523 revlogupdate(&changelog);
524 revlogupdate(&manifest);
525 dirread9p(r, rootgen, nil);
529 dirread9p(r, revgen, rf->info);
537 if((i = hashrev(&changelog, rf->info->chash)) >= 0){
538 if(rf->level == Qrev1)
539 i = changelog.map[i].p1rev;
541 i = changelog.map[i].p2rev;
543 snprint(s = buf, sizeof(buf), "%d.%H", i, changelog.map[i].hash);
547 if(off >= rf->info->loglen)
549 else if((off + len) >= rf->info->loglen)
550 len = rf->info->loglen - off;
551 off += rf->info->logoff;
554 if((rf->fd = revlogopentemp(&changelog, hashrev(&changelog, rf->info->chash))) < 0){
566 rf->buf = s ? smprint("%s\n", s) : estrdup9p("");
574 dirread9p(r, treegen, rf->node->down);
580 nodepath(seprint(buf, buf+sizeof(buf), ".hg/store/data"), buf+sizeof(buf), rf->node);
581 if(revlogopen(&rl, buf, OREAD) < 0){
585 if((rf->fd = revlogopentemp(&rl, hashrev(&rl, rf->node->hash))) < 0){
592 if((n = pread(rf->fd, r->ofcall.data, len, off)) < 0){
600 respond(r, "bug in fsread");
609 .destroyfid=fsdestroyfid,
617 fprint(2, "usage: %s [-D] [-m mtpt] [-s srv]\n", argv0);
622 main(int argc, char *argv[])
627 fmtinstall('H', Hfmt);
637 mtpt = EARGF(usage());
640 srv = EARGF(usage());
646 if(revlogopen(&changelog, ".hg/store/00changelog", OREAD) < 0)
647 sysfatal("can't open changelog: %r\n");
648 if(revlogopen(&manifest, ".hg/store/00manifest", OREAD) < 0)
649 sysfatal("can't open menifest: %r\n");
651 postmountsrv(&fs, srv, mtpt, MREPL);