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;
+}