shithub: riscv

Download patch

ref: 559d2fc8359bb9f2c6517861f084b70fe51fc573
parent: 6812f4679be6b8fcd96bc2cad9c38a8344bae78e
author: cinap_lenrek <[email protected]>
date: Mon Oct 29 18:00:38 EDT 2012

hgfs: work in progress stuff...

--- /dev/null
+++ b/sys/src/cmd/hgfs/ancestor.c
@@ -1,0 +1,108 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include "dat.h"
+#include "fns.h"
+
+typedef struct XNode XNode;
+struct XNode
+{
+	XNode	*next;
+	XNode	*queue;
+	char	mark;
+	uchar	hash[HASHSZ];
+};
+
+static XNode*
+hnode(XNode *ht[], uchar hash[])
+{
+	XNode *h;
+
+	for(h = ht[hash[0]]; h; h = h->next)
+		if(memcmp(h->hash, hash, HASHSZ) == 0)
+			return h;
+
+	h = malloc(sizeof(*h));
+	memmove(h->hash, hash, HASHSZ);
+	h->mark = 0;
+	h->queue = nil;
+	h->next = ht[hash[0]];
+	ht[hash[0]] = h;
+	return h;
+}
+
+/*
+ * find common ancestor revision ahash for xhash and yhash
+ * in the give hgfs mount point. sets ahash to nullid if
+ * no common ancestor.
+ */
+void
+ancestor(char *mtpt, uchar xhash[], uchar yhash[], uchar ahash[])
+{
+	XNode *ht[256], *h, *q, *q1, *q2;
+	char buf[MAXPATH], rev[6];
+	int i;
+
+	if(memcmp(xhash, yhash, HASHSZ) == 0){
+		memmove(ahash, xhash, HASHSZ);
+		return;
+	}
+	if(memcmp(xhash, nullid, HASHSZ) == 0){
+		memmove(ahash, nullid, HASHSZ);
+		return;
+	}
+	if(memcmp(yhash, nullid, HASHSZ) == 0){
+		memmove(ahash, nullid, HASHSZ);
+		return;
+	}
+
+	memset(ht, 0, sizeof(ht));
+	q1 = nil;
+
+	h = hnode(ht, xhash);
+	h->mark = 'x';
+	h->queue = q1;
+	q1 = h;
+
+	h = hnode(ht, yhash);
+	h->mark = 'y';
+	h->queue = q1;
+	q1 = h;
+
+	for(;;){
+		q2 = nil;
+		while(q = q1){
+			q1 = q->queue;
+			q->queue = nil;
+			snprint(buf, sizeof(buf), "%s/%H", mtpt, q->hash);
+			for(i=1; i<=2; i++){
+				sprint(rev, "rev%d", i);
+				if(readhash(buf, rev, ahash) != 0)
+					continue;
+				if(memcmp(ahash, nullid, HASHSZ) == 0)
+					continue;
+				h = hnode(ht, ahash);
+				if(h->mark){
+					if(h->mark != q->mark)
+						goto Done;
+				} else {
+					h->mark = q->mark;
+					h->queue = q2;
+					q2 = h;
+				}
+			}
+		}
+		if(q2 == nil){
+			memmove(ahash, nullid, HASHSZ);
+			break;
+		}
+		q1 = q2;
+	}
+
+Done:
+	for(i=0; i<nelem(ht); i++)
+		while(h = ht[i]){
+			ht[i] = h->next;
+			free(h);
+		}
+}
--- a/sys/src/cmd/hgfs/fns.h
+++ b/sys/src/cmd/hgfs/fns.h
@@ -3,6 +3,7 @@
 int hex2hash(char *s, uchar *h);
 uvlong hash2qid(uchar *h);
 int fhash(int fd, uchar p1[], uchar p2[], uchar h[]);
+int readhash(char *path, char *name, uchar hash[]);
 
 /* patch */
 int fpatchmark(int pfd, char *mark);
@@ -34,3 +35,7 @@
 /* util */
 ulong hashstr(char *s);
 int getworkdir(char *work, char *path);
+int readfile(char *path, char *buf, int nbuf);
+
+/* ancestor */
+void ancestor(char *mtpt, uchar xhash[], uchar yhash[], uchar ahash[]);
--- a/sys/src/cmd/hgfs/hash.c
+++ b/sys/src/cmd/hgfs/hash.c
@@ -78,3 +78,21 @@
 		v |= (uvlong)h[i]<<(56-8*i);
 	return v;
 }
+
+int
+readhash(char *path, char *name, uchar hash[])
+{
+	char buf[MAXPATH], *p;
+	int n;
+
+	snprint(buf, sizeof(buf), "%s/%s", path, name);
+	readfile(buf, buf, sizeof(buf));
+	if(p = strchr(buf, '.'))
+		p++;
+	else
+		p = buf;
+	n = hex2hash(p, hash);
+	if(n != HASHSZ)
+		return -1;
+	return 0;
+}
--- a/sys/src/cmd/hgfs/hgdb.c
+++ b/sys/src/cmd/hgfs/hgdb.c
@@ -1,4 +1,4 @@
-/* hg debug stuff, just dumps dirstate database right now */
+/* hg debug stuff, will become update/merge program */
 
 #include <u.h>
 #include <libc.h>
@@ -119,9 +119,9 @@
 }
 
 void
-changes(char *ppath, char *rpath)
+changes(char *lpath, char *rpath, char *apath)
 {
-	print("diff -r %s %s\n", ppath, rpath);
+	print("local=%s\nremote=%s\nancestor=%s\n", lpath, rpath, apath);
 }
 
 void
@@ -134,7 +134,8 @@
 void
 main(int argc, char *argv[])
 {
-	char ppath[MAXPATH], rpath[MAXPATH];
+	char lpath[MAXPATH], rpath[MAXPATH], apath[MAXPATH];
+	uchar rhash[HASHSZ], ahash[HASHSZ];
 	char *mtpt, *rev;
 	Workdir wd;
 
@@ -156,15 +157,30 @@
 	if(loadworkdir(&wd, *argv) < 0)
 		sysfatal("loadworkdir: %r");
 
-	print("%s\n%H\n%H\n", wd.path, wd.p1hash, wd.p2hash);
-
 	if(memcmp(wd.p2hash, nullid, HASHSZ))
 		sysfatal("outstanding merge");
 
-	snprint(ppath, sizeof(ppath), "%s/%H/files", mtpt, wd.p1hash);
-	snprint(rpath, sizeof(rpath), "%s/%s/files", mtpt, rev);
+	snprint(rpath, sizeof(rpath), "%s/%s", mtpt, rev);
+	if(readhash(rpath, "rev", rhash) != 0)
+		sysfatal("unable to get hash for %s", rev);
 
-	changes(ppath, rpath);
+	if(memcmp(rhash, wd.p1hash, HASHSZ) == 0){
+		fprint(2, "up to date\n");
+		exits(0);
+	}
+
+	ancestor(mtpt, wd.p1hash, rhash, ahash);
+	if(memcmp(ahash, nullid, HASHSZ) == 0)
+		sysfatal("no common ancestor between %H and %H", wd.p1hash, rhash);
+
+	if(memcmp(ahash, rhash, HASHSZ) == 0)
+		memmove(ahash, wd.p1hash, HASHSZ);
+
+	snprint(lpath, sizeof(lpath), "%s/%H/files", mtpt, wd.p1hash);
+	snprint(rpath, sizeof(rpath), "%s/%H/files", mtpt, rhash);
+	snprint(apath, sizeof(apath), "%s/%H/files", mtpt, ahash);
+	
+	changes(lpath, rpath, apath);
 	
 	exits(0);
 }
--- a/sys/src/cmd/hgfs/mkfile
+++ b/sys/src/cmd/hgfs/mkfile
@@ -11,5 +11,5 @@
 </sys/src/cmd/mkone
 
 # debug stuff
-$O.hgdb: hgdb.$O hash.$O util.$O
+$O.hgdb: hgdb.$O hash.$O util.$O ancestor.$O
 	$LD $LDFLAGS -o $target $prereq
--- a/sys/src/cmd/hgfs/util.c
+++ b/sys/src/cmd/hgfs/util.c
@@ -42,3 +42,18 @@
 	}
 	return -1;
 }
+
+int
+readfile(char *path, char *buf, int nbuf)
+{
+	int fd, n;
+
+	n = 0;
+	if((fd = open(path, OREAD)) >= 0){
+		if((n = read(fd, buf, nbuf-1)) < 0)
+			n = 0;
+		close(fd);
+	}
+	buf[n] = '\0';
+	return n;
+}