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;
62 while(x = strchr(s, '<'))
65 if(x = strchr(s, '>'))
67 if(x = strchr(s, '@'))
69 if(x = strchr(s, '\n'))
72 if(s == nil || *s == 0){
74 s = estrdup9p("hgfs");
80 fsmkqid(Qid *q, int level, void *aux)
104 q->path = *((uvlong*)ri->chash) + (level - Qrev);
121 fsmkdir(Dir *d, int level, void *aux)
128 memset(d, 0, sizeof(*d));
130 fsmkqid(&d->qid, level, aux);
133 if(d->qid.type == QTDIR)
134 d->mode |= DMDIR | 0111;
145 rev = hashrev(&changelog, ri->chash);
147 rev = changelog.map[rev].p1rev;
148 else if(level == Qrev2)
149 rev = changelog.map[rev].p2rev;
151 snprint(s = buf, sizeof(buf), "%d.%H", rev, changelog.map[rev].hash);
153 d->name = estrdup9p(buf);
159 if((rev = hashrev(&changelog, ri->chash)) >= 0)
160 d->length = changelog.map[rev].flen;
170 d->length = s ? strlen(s)+1 : 0;
176 d->name = estrdup9p(nametab[level]);
180 d->name = estrdup9p(nd->name);
185 nodepath(seprint(path, path+MAXPATH, ".hg/store/data"), path+MAXPATH, nd);
186 if(revlogopen(&rl, path, OREAD) < 0)
188 if((rev = hashrev(&rl, nd->hash)) >= 0){
189 d->length = rl.map[rev].flen;
190 ri = getrevinfo(rl.map[rev].linkrev);
198 d->atime = d->mtime = ri->when;
199 d->muid = fsmkuid(ri->who);
200 d->uid = fsmkuid(ri->who);
202 d->atime = d->mtime = time(0);
205 d->uid = fsmkuid(nil);
207 d->gid = fsmkuid(nil);
209 d->muid = fsmkuid(nil);
217 if(r->ifcall.aname && r->ifcall.aname[0]){
218 respond(r, "invalid attach specifier");
221 r->fid->qid.path = Qroot;
222 r->fid->qid.type = QTDIR;
223 r->fid->qid.vers = 0;
224 r->ofcall.qid = r->fid->qid;
226 rf = emalloc9p(sizeof(*rf));
246 if(rf->level < Qtree)
247 fsmkdir(&r->d, rf->level, rf->info);
249 fsmkdir(&r->d, rf->level, rf->node);
254 findrev(Revlog *rl, char *name)
260 rev = strtol(name, &s, 10);
261 if(s > name && (*s == 0 || ispunct(*s)))
264 if(s = strchr(name, '.'))
266 if((n = strhash(name, hash)) > 0){
267 for(i=0; i<rl->nmap; i++){
268 if(memcmp(rl->map[i].hash, hash, n) == 0){
282 fswalk1(Fid *fid, char *name, Qid *qid)
288 if(!(fid->qid.type&QTDIR))
289 return "walk in non-directory";
292 if(strcmp(name, "..") == 0){
302 closerevtree(rf->tree);
307 if((rf->node = rf->node->up) == rf->tree->root)
308 rf->level = rf->tree->level;
314 revlogupdate(&changelog);
315 revlogupdate(&manifest);
317 i = findrev(&changelog, name);
318 if(rf->info = getrevinfo(i)){
323 return "directory entry not found";
326 for(i = Qrev+1; i < Qtree; i++){
327 if(nametab[i] == nil)
329 if(strcmp(name, nametab[i]) == 0)
336 if((rf->tree = loadfilestree(&changelog, &manifest, rf->info)) == nil)
340 if((rf->tree = loadchangestree(&changelog, &manifest, rf->info)) == nil)
345 rf->node = rf->tree->root;
353 for(nd = rf->node->down; nd; nd = nd->next)
354 if(strcmp(nd->name, name) == 0)
364 if(rf->level < Qtree)
365 fsmkqid(qid, rf->level, rf->info);
367 fsmkqid(qid, rf->level, rf->node);
374 fsclone(Fid *oldfid, Fid *newfid)
379 if(orf = oldfid->aux){
380 rf = emalloc9p(sizeof(*rf));
385 rf->fd = dup(rf->fd, -1);
387 rf->buf = estrdup9p(rf->buf);
394 fsdestroyfid(Fid *fid)
399 closerevtree(rf->tree);
414 rootgen(int i, Dir *d, void *)
418 if((ri = getrevinfo(i)) == nil)
420 fsmkdir(d, Qrev, ri);
425 revgen(int i, Dir *d, void *aux)
435 treegen(int i, Dir *d, void *aux)
445 fsmkdir(d, Qtree, nd);
455 if(r->fid->qid.type == QTDIR){
458 respond(r, "bug in fsread");
461 revlogupdate(&changelog);
462 revlogupdate(&manifest);
464 dirread9p(r, rootgen, nil);
468 dirread9p(r, revgen, rf->info);
474 dirread9p(r, treegen, rf->node->down);
486 respond(r, "bug in fsread");
491 if((rf->fd = revlogopentemp(&changelog, hashrev(&changelog, rf->info->chash))) < 0){
499 if((i = hashrev(&changelog, rf->info->chash)) >= 0){
500 if(rf->level == Qrev1)
501 i = changelog.map[i].p1rev;
503 i = changelog.map[i].p2rev;
505 snprint(s = buf, sizeof(buf), "%d.%H", i, changelog.map[i].hash);
515 rf->buf = s ? smprint("%s\n", s) : estrdup9p("");
522 nodepath(seprint(buf, buf+sizeof(buf), ".hg/store/data"), buf+sizeof(buf), rf->node);
523 if(revlogopen(&rl, buf, OREAD) < 0){
527 if((rf->fd = revlogopentemp(&rl, hashrev(&rl, rf->node->hash))) < 0){
535 if((n = pread(rf->fd, r->ofcall.data, r->ifcall.count, r->ifcall.offset)) < 0){
550 .destroyfid=fsdestroyfid,
558 fprint(2, "usage: %s [-D] [-m mtpt] [-s srv]\n", argv0);
563 main(int argc, char *argv[])
568 fmtinstall('H', Hfmt);
578 mtpt = EARGF(usage());
581 srv = EARGF(usage());
587 if(revlogopen(&changelog, ".hg/store/00changelog", OREAD) < 0)
588 sysfatal("can't open changelog: %r\n");
589 if(revlogopen(&manifest, ".hg/store/00manifest", OREAD) < 0)
590 sysfatal("can't open menifest: %r\n");
592 postmountsrv(&fs, srv, mtpt, MREPL);