enum {
Qroot,
Qrev,
+ Qrev0,
Qrev1,
Qrev2,
Qlog,
static char *nametab[] = {
"/",
nil,
+ "rev",
"rev1",
"rev2",
"log",
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;
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);
case Qchanges:
q->type = QTDIR;
if(0){
+ case Qrev0:
case Qrev1:
case Qrev2:
case Qlog:
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:
fsmkqid(&d->qid, level, aux);
d->mode = 0444;
- if(d->qid.type == QTDIR)
+ if(d->qid.type & QTDIR)
d->mode |= DMDIR | 0111;
ri = nil;
case Qroot:
goto Namegen;
case Qrev:
+ case Qrev0:
case Qrev1:
case Qrev2:
ri = 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);
rf->rlog = nil;
rf->fd = -1;
+ rf->doff = 0;
rf->buf = nil;
r->fid->aux = rf;
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);
}
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)
Revfile *rf;
int i, level;
- if(!(fid->qid.type&QTDIR))
+ if((fid->qid.type & QTDIR) == 0)
return "walk in non-directory";
rf = fid->aux;
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;
}
dirread9p(r, revgen, rf->info);
respond(r, nil);
return;
+ case Qrev0:
case Qrev1:
case Qrev2:
s = nil;
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);
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;
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;
}
fmtinstall('H', Hfmt);
srv = nil;
- mtpt = "/n/hg";
+ mtpt = "/mnt/hg";
ARGBEGIN {
case 'D':
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);
}