shithub: riscv

Download patch

ref: 6d91601a775db1fa873f64f90da764ece2c2da6d
parent: d0485d345db63b0ee82301251339e72d6093107d
author: cinap_lenrek <cinap_lenrek@localhost>
date: Mon Jun 27 23:51:05 EDT 2011

hgfs: get previous file revisions with appending .n or .revn

--- a/sys/src/cmd/hgfs/dat.h
+++ b/sys/src/cmd/hgfs/dat.h
@@ -33,6 +33,10 @@
 
 struct Revlog
 {
+	Ref;
+
+	char	*path;
+
 	int	ifd;
 	int	dfd;
 
@@ -51,6 +55,7 @@
 	Revnode	*up;
 	Revnode	*next;
 	Revnode	*down;
+	Revnode *before;
 
 	char	mode;
 };
@@ -82,6 +87,7 @@
 	Revinfo	*info;
 	Revtree	*tree;
 	Revnode	*node;
+	Revlog	*rlog;
 
 	char	*buf;
 	int	fd;
--- a/sys/src/cmd/hgfs/fns.h
+++ b/sys/src/cmd/hgfs/fns.h
@@ -25,6 +25,7 @@
 
 /* tree */
 char *nodepath(char *s, char *e, Revnode *nd);
+Revnode *mknode(char *name, uchar *hash, char mode);
 Revtree *loadfilestree(Revlog *changelog, Revlog *manifest, Revinfo *ri);
 Revtree *loadchangestree(Revlog *changelog, Revlog *manifest, Revinfo *ri);
 void closerevtree(Revtree *t);
--- a/sys/src/cmd/hgfs/fs.c
+++ b/sys/src/cmd/hgfs/fs.c
@@ -21,9 +21,10 @@
 			Qfiles,
 			Qchanges,
 				Qtree,
+				Qtreerev,
 };
 
-static char *nametab[Qtree+1] = {
+static char *nametab[] = {
 	"/",
 		nil,
 			"rev1",
@@ -34,11 +35,41 @@
 			"files",
 			"changes",
 				nil,
+				nil,
 };
 
 static Revlog changelog;
 static Revlog manifest;
 
+static Revlog*
+getrevlog(Revnode *nd)
+{
+	char path[MAXPATH];
+	Revlog *rl;
+
+	nodepath(seprint(path, path+MAXPATH, ".hg/store/data"), path+MAXPATH, nd);
+	rl = emalloc9p(sizeof(*rl));
+	memset(rl, 0, sizeof(*rl));
+	if(revlogopen(rl, path, OREAD) < 0){
+		fprint(2, "getrevlod %s: %r\n", path);
+		free(rl);
+		return nil;
+	}
+	incref(rl);
+	return rl;
+}
+
+static void
+closerevlog(Revlog *rl)
+{
+	if(rl == nil)
+		return;
+	if(decref(rl))
+		return;
+	revlogclose(rl);
+	free(rl);
+}
+
 static Revinfo*
 getrevinfo(int rev)
 {
@@ -146,13 +177,14 @@
 		q->vers = 0;
 		break;
 	case Qtree:
+	case Qtreerev:
 		nd = aux;
-		if(nd->down){
+		if(level == Qtree && nd->down){
 			q->type = QTDIR;
 		} else {
 			q->type = 0;
 		}
-		q->path = nd->path;
+		q->path = nd->path + (level - Qtree);
 		q->vers = 0;
 		break;
 	}
@@ -183,6 +215,7 @@
 	case Qrev1:
 	case Qrev2:
 		ri = aux;
+	Revgen:
 		rev = hashrev(&changelog, ri->chash);
 		if(level == Qrev1)
 			rev = changelog.map[rev].p1rev;
@@ -208,6 +241,8 @@
 		s = ri->why;
 	Strgen:
 		d->length = s ? strlen(s)+1 : 0;
+		if(level == Qtreerev)
+			break;
 	case Qfiles:
 	case Qchanges:
 		ri = aux;
@@ -216,22 +251,24 @@
 		d->name = estrdup9p(nametab[level]);
 		break;
 	case Qtree:
+	case Qtreerev:
 		nd = aux;
 		d->name = estrdup9p(nd->name);
 		if(nd->mode == 'x')
 			d->mode |= 0111;
 		if(nd->hash){
-			char path[MAXPATH];
-			Revlog rl;
+			Revlog *rl;
 
-			nodepath(seprint(path, path+MAXPATH, ".hg/store/data"), path+MAXPATH, nd);
-			if(revlogopen(&rl, path, OREAD) < 0)
+			if((rl = getrevlog(nd)) == nil)
 				break;
-			if((rev = hashrev(&rl, nd->hash)) >= 0){
-				d->length = rl.map[rev].flen;
-				ri = getrevinfo(rl.map[rev].linkrev);
+			if((rev = hashrev(rl, nd->hash)) >= 0){
+				if(level == Qtree)
+					d->length = rl->map[rev].flen;
+				ri = getrevinfo(rl->map[rev].linkrev);
 			}
-			revlogclose(&rl);
+			closerevlog(rl);
+			if(level == Qtreerev && ri)
+				goto Revgen;
 		}
 		break;
 	}
@@ -270,6 +307,7 @@
 	rf->info = nil;
 	rf->tree = nil;
 	rf->node = nil;
+	rf->rlog = nil;
 
 	rf->fd = -1;
 	rf->buf = nil;
@@ -326,9 +364,11 @@
 fswalk1(Fid *fid, char *name, Qid *qid)
 {
 	Revtree* (*loadfn)(Revlog *, Revlog *, Revinfo *);
-	Revfile *rf;
+	char path[MAXPATH];
 	Revnode *nd;
-	int i;
+	Revfile *rf;
+	char *sname;
+	int i, level;
 
 	if(!(fid->qid.type&QTDIR))
 		return "walk in non-directory";
@@ -349,6 +389,8 @@
 			rf->level = Qrev;
 			break;
 		case Qtree:
+			closerevlog(rf->rlog);
+			rf->rlog = nil;
 			if((rf->node = rf->node->up) == rf->tree->root)
 				rf->level = rf->tree->level;
 			break;
@@ -396,13 +438,56 @@
 		case Qtree:
 		case Qfiles:
 		case Qchanges:
+			i = 0;
+			level = Qtree;
+			sname = name;
+		Searchtree:
 			for(nd = rf->node->down; nd; nd = nd->next)
-				if(strcmp(nd->name, name) == 0)
+				if(strcmp(nd->name, sname) == 0)
 					break;
-			if(nd == nil)
+			if(nd == nil){
+				if(sname == name){
+					sname = strrchr(name, '.');
+					if((i = sname - name) > 0){
+						sname++;
+						if(strncmp(sname, "rev", 3) == 0){
+							level = Qtreerev;
+							sname += 3;
+						}
+						snprint(path, sizeof(path), "%.*s", i, name);
+						i = atoi(sname);
+						sname = path;
+						goto Searchtree;
+					}
+				}
 				goto Notfound;
+			}
+			if(nd->hash){
+				Revnode *nb;
+				int j;
+
+				if((rf->rlog = getrevlog(nd)) == nil)
+					goto Notfound;
+				j = hashrev(rf->rlog, nd->hash) - i;
+				if(i < 0 || j < 0 || j >= rf->rlog->nmap){
+					closerevlog(rf->rlog);
+					rf->rlog = nil;
+					goto Notfound;
+				}
+				for(nb = nd; nb; nb = nb->before)
+					if(hashrev(rf->rlog, nb->hash) == j)
+						break;
+				if(nb == nil){
+					nb = mknode(nd->name, revhash(rf->rlog, j), nd->mode);
+					nb->up = nd->up;
+					nb->before = nd->before;
+					nd->before = nb;
+				}
+				nd = nb;
+			} else if(i || level != Qtree)
+				goto Notfound;
 			rf->node = nd;
-			rf->level = Qtree;
+			rf->level = level;
 			break;
 		}
 	}
@@ -425,6 +510,8 @@
 	if(orf = oldfid->aux){
 		rf = emalloc9p(sizeof(*rf));
 		*rf = *orf;
+		if(rf->rlog)
+			incref(rf->rlog);
 		if(rf->tree)
 			incref(rf->tree);
 		if(rf->fd >= 0)
@@ -442,6 +529,7 @@
 	Revfile *rf;
 
 	if(rf = fid->aux){
+		closerevlog(rf->rlog);
 		closerevtree(rf->tree);
 		if(rf->fd >= 0)
 			close(rf->fd);
@@ -508,7 +596,6 @@
 {
 	Revfile *rf;
 	char buf[MAXPATH];
-	Revlog rl;
 	char *s;
 	int i, n;
 	vlong off;
@@ -539,10 +626,16 @@
 				i = changelog.map[i].p1rev;
 			else
 				i = changelog.map[i].p2rev;
+	Revgen:
 			if(i >= 0)
 				snprint(s = buf, sizeof(buf), "%d.%H", i, changelog.map[i].hash);
 		}
 		goto Strgen;
+	case Qtreerev:
+		s = nil;
+		if((i = hashrev(rf->rlog, rf->node->hash)) >= 0)
+			i = rf->rlog->map[i].linkrev;
+		goto Revgen;
 	case Qlog:
 		if(off >= rf->info->loglen)
 			len = 0;
@@ -577,17 +670,10 @@
 		}
 		if(rf->fd >= 0)
 			goto Fdgen;
-		nodepath(seprint(buf, buf+sizeof(buf), ".hg/store/data"), buf+sizeof(buf), rf->node);
-		if(revlogopen(&rl, buf, OREAD) < 0){
+		if((rf->fd = revlogopentemp(rf->rlog, hashrev(rf->rlog, rf->node->hash))) < 0){
 			responderror(r);
 			return;
 		}
-		if((rf->fd = revlogopentemp(&rl, hashrev(&rl, rf->node->hash))) < 0){
-			responderror(r);
-			revlogclose(&rl);
-			return;
-		}
-		revlogclose(&rl);
 	Fdgen:
 		if((n = pread(rf->fd, r->ofcall.data, len, off)) < 0){
 			responderror(r);
--- a/sys/src/cmd/hgfs/revlog.c
+++ b/sys/src/cmd/hgfs/revlog.c
@@ -68,7 +68,10 @@
 	}
 	path[strlen(path)-1] = 'd';
 	r->dfd = open(path, mode);
-	free(path);
+
+	path[strlen(path)-2] = 0;
+	r->path = path;
+
 	r->ioff = 0;
 	r->nmap = 0;
 	r->map = nil;
@@ -90,6 +93,7 @@
 	free(r->map);
 	r->map = nil;
 	r->nmap = 0;
+	free(r->path);
 }
 
 uchar*
--- a/sys/src/cmd/hgfs/tree.c
+++ b/sys/src/cmd/hgfs/tree.c
@@ -22,7 +22,7 @@
 
 	p = nd->name;
 	for(i=0; i<nelem(frogs); i++)
-		if(strcmp(frogs[i], p) == 0)
+		if(strncmp(frogs[i], p, strlen(frogs[i])) == 0)
 			return seprint(s, e, "%.2s~%.2x%s", p, p[2], p+3);
 
 	for(; s+4 < e && *p; p++){
@@ -43,10 +43,35 @@
 	return s;
 }
 
+Revnode*
+mknode(char *name, uchar *hash, char mode)
+{
+	Revnode *d;
+	char *s;
+
+	d = malloc(sizeof(*d) + (hash ? HASHSZ : 0) + (name ? strlen(name)+1 : 0));
+	d->up = d->down = d->next = d->before = nil;
+	s = (char*)&d[1];
+	if(hash){
+		d->path = *((uvlong*)hash);
+		memmove(d->hash = (uchar*)s, hash, HASHSZ);
+		s += HASHSZ;
+	} else {
+		d->path = 1;
+		d->hash = nil;
+	}
+	if(name)
+		strcpy(d->name = s, name);
+	else
+		d->name = nil;
+	d->mode = mode;
+	return d;
+}
+
 static void
 addnode(Revnode *d, char *path, uchar *hash, char mode)
 {
-	char *slash, *x;
+	char *slash;
 	Revnode *c, *p;
 
 	while(path && *path){
@@ -57,20 +82,8 @@
 			if(strcmp(c->name, path) == 0)
 				break;
 		if(c == nil){
-			c = malloc(sizeof(*c) + (!slash ? HASHSZ : 0) + strlen(path)+1);
-			c->path = 1;
-			x = (char*)&c[1];
-			if(!slash){
-				c->mode = mode;
-				memmove(c->hash = (uchar*)x, hash, HASHSZ);
-				x += HASHSZ;
-			}else{
-				c->mode = 0;
-				c->hash = nil;
-			}
-			strcpy(c->name = x, path);
+			c = mknode(path, slash ? nil : hash, slash ? 0 : mode);
 			c->up = d;
-			c->down = nil;
 			if(p){
 				c->next = p->next;
 				p->next = c;
@@ -78,7 +91,6 @@
 				c->next = d->down;
 				d->down = c;
 			}
-
 			if(c->hash){
 				p = c;
 				p->path = *((uvlong*)c->hash);
@@ -170,21 +182,12 @@
 	t = malloc(sizeof(*t));
 	memset(t, 0, sizeof(*t));
 	incref(t);
-
-	t->root = malloc(sizeof(Revnode));
-	t->root->path = 0;
-	t->root->name = 0;
-	t->root->up = nil;
-	t->root->down = nil;
-	t->root->next = nil;
-	t->root->hash = nil;
-
+	t->root = mknode(nil, nil, 0);
 	if(loadmanifest(t->root, fd, ht, nh) < 0){
 		close(fd);
 		closerevtree(t);
 		return nil;
 	}
-
 	close(fd);
 
 	return t;
@@ -259,6 +262,7 @@
 		return;
 	freenode(nd->down);
 	freenode(nd->next);
+	freenode(nd->before);
 	free(nd);
 }