shithub: riscv

Download patch

ref: 5be7e69c26c93309fb6035b3170226cf4dffd810
parent: 1d4ab252653dfad292a5a90f5e61e9a0cba47083
author: cinap_lenrek <[email protected]>
date: Wed Nov 21 19:02:43 EST 2012

hgfs: work in progress stuff...

--- a/sys/src/cmd/hgfs/hgdb.c
+++ b/sys/src/cmd/hgfs/hgdb.c
@@ -28,6 +28,8 @@
 	Dstate	*ht[256];
 };
 
+int clean = 0;
+
 static Dstate**
 dslookup(Workdir *wd, char *path)
 {
@@ -119,37 +121,21 @@
 	return -1;
 }
 
-void
-apply1(char *state, char *name, char *lpath, char *rpath, Workdir *wd)
+char*
+pjoin(char *path, char *name)
 {
-	char buf[MAXPATH];
-	Dir *d;
-	Dstate *ds;
-
-	ds = *dslookup(wd, name);
-	if(ds != nil){
-		snprint(buf, sizeof(buf), "%s/%s", wd->path, name);
-		d = dirstat(buf);
-	}
-	if(strcmp(state, "na") == 0){
-		snprint(buf, sizeof(buf), "%s/%s", rpath, name);
-		d = dirstat(buf);
-		if(d != nil){
-			if(d->qid.type & QTDIR)
-				print("mkdir %s/%s\n", wd->path, name);
-			else
-				print("cp %s %s/%s\n", buf, wd->path, name);
-			free(d);
-		}
-	}
-	else if(strcmp(state, "nm") == 0)
-		print("cp %s/%s %s/%s\n", rpath, name, wd->path, name);
-	else if(strcmp(state, "nd") == 0)
-		print("rm %s/%s\n", wd->path, name);
+	if(path[0] == '\0')
+		path = "/";
+	if(name[0] == '\0')
+		return strdup(path);
+	if(path[strlen(path)-1] == '/' || name[0] == '/')
+		return smprint("%s%s", path, name);
+	return smprint("%s/%s", path, name);
 }
 
 void
-applychanges(int fd, char *lpath, char *rpath, Workdir *wd)
+changes1(int fd, char *lpath, char *rpath, char *apath,
+	void (*apply)(char *, char *, char *, char *, char *, void *), void *aux)
 {
 	char *state, *name;
 	Biobuf bin;
@@ -162,34 +148,147 @@
 			*name++ = '\0';
 		if(name[0] == '.' && name[1] == '/')
 			name += 2;
-		apply1(state, name, lpath, rpath, wd);
+		apply(state, name, lpath, rpath, apath, aux);
 	}
 	Bterm(&bin);
 }
 
-void
-changes(char *lpath, char *rpath, char *apath, Workdir *wd)
+int
+changes(char *opt, char *lp, char *rp, char *ap,
+	void (*apply)(char *, char *, char *, char *, char *, void *), void *aux)
 {
-	int pfd[2];
+	int pfd[2], pid;
+	Waitmsg *w;
 
 	if(pipe(pfd) < 0)
-		sysfatal("pipe: %r");
-	switch(rfork(RFPROC|RFMEM|RFFDG)){
+		return -1;
+	pid = rfork(RFPROC|RFMEM|RFFDG);
+	switch(pid){
 	case -1:
-		sysfatal("rfork: %r");
+		close(pfd[0]);
+		close(pfd[1]);
+		return -1;
 	case 0:
 		close(pfd[0]);
 		dup(pfd[1], 1);
 		close(pfd[1]);
-		execl("/bin/derp", "derp", "-L", "-p", "0111", lpath, apath, rpath, nil);
-		sysfatal("execl: %r");
+		execl("/bin/derp", "derp", opt, "-p", "0111", lp, ap, rp, nil);
+		exits("exec");
 	}
 	close(pfd[1]);
-	applychanges(pfd[0], lpath, rpath, wd);
+	changes1(pfd[0], lp, rp, ap, apply, aux);
 	close(pfd[0]);
+	while(w = wait()){
+		if(w->pid == pid){
+			if(w->msg[0] != '\0'){
+				werrstr("%s", w->msg);
+				free(w);
+				return 1;
+			}
+			free(w);
+			return 0;
+		}
+		free(w);
+	}
+	return -1;
 }
 
 void
+apply(char *state, char *name, char *lp, char *rp, char *ap, Workdir *)
+{
+	Dir *rd, *ld;
+
+	ld = rd = nil;
+	// fprint(2, "### %s %s ->\t", state, name);
+	if(strcmp(state, "na") == 0){
+		rd = dirstat(rp);
+		if(rd != nil){
+			if(rd->qid.type & QTDIR)
+				print("mkdir %s\n", lp);
+			else
+				print("cp %s %s\n", rp, lp);
+		}
+	}
+	else if(strcmp(state, "an") == 0){
+	}
+	else if(strcmp(state, "nm") == 0){
+		print("cp %s %s\n", rp, lp);
+	}
+	else if(strcmp(state, "mn") == 0){
+	}
+	else if(strcmp(state, "nd") == 0){
+		print("rm %s\n", lp);
+	}
+	else if(strcmp(state, "dn") == 0){
+	}
+	else if(strcmp(state, "aa!") == 0 || strcmp(state, "mm!") == 0){
+		ld = dirstat(lp);
+		rd = dirstat(rp);
+		if(ld != nil && rd != nil){
+			if(rd->qid.type & QTDIR)
+				print("# conflict # mkdir %s\n", lp);
+			else if(ld->qid.type & QTDIR)
+				print("# conflict # rm -r %s\n", lp);
+			else
+				print("# conflict # ape/diff3 %s %s %s >%s\n", lp, ap, rp, lp);
+		}
+	}
+	else if(strcmp(state, "md!") == 0){
+		print("# delete conflict # rm %s\n", lp);
+	}
+	else if(strcmp(state, "dm!") == 0){
+		print("# delete conflict # cp %s %s\n", rp, lp);
+	}
+	else {
+		print("# unknown status %s %s\n", state, name);
+	}
+	free(rd);
+	free(ld);
+}
+
+void
+apply1(char *state, char *name, char *lp, char *rp, char *ap, void *aux)
+{
+	Workdir *wd = aux;
+
+	lp = pjoin(lp, name);
+	rp = pjoin(rp, name);
+	ap = pjoin(ap, name);
+	apply(state, lp + strlen(wd->path)+1, lp, rp, ap, wd);
+	free(ap);
+	free(rp);
+	free(lp);
+}
+
+void
+apply0(char *state, char *name, char *lp, char *rp, char *ap, void *aux)
+{
+	Workdir *wd = aux;
+	Dir *ld;
+
+	if(clean){
+		/* working dir clean */
+		apply1(state, name, wd->path, rp, ap, wd);
+		return;
+	}
+	lp = pjoin(wd->path, name);
+	ld = dirstat(lp);
+	if(clean == 0 && ld != nil && (ld->qid.type & QTDIR) == 0){
+		/* check for changes in working directory */
+		rp = pjoin(rp, name);
+		ap = pjoin(ap, name);
+		changes("-Lcq", lp, rp, ap, apply1, wd);
+		free(ap);
+		free(rp);
+	} else {
+		/* working dir clean */
+		apply1(state, name, wd->path, rp, ap, wd);
+	}
+	free(lp);
+	free(ld);
+}
+
+void
 usage(void)
 {
 	fprint(2, "usage: %s [-m mtpt] [-r rev] [root]\n", argv0);
@@ -199,8 +298,8 @@
 void
 main(int argc, char *argv[])
 {
-	char lpath[MAXPATH], rpath[MAXPATH], apath[MAXPATH];
-	uchar rhash[HASHSZ], ahash[HASHSZ];
+	char lp[MAXPATH], rp[MAXPATH], ap[MAXPATH];
+	uchar rh[HASHSZ], ah[HASHSZ];
 	char *mtpt, *rev;
 	Workdir wd;
 
@@ -216,6 +315,9 @@
 	case 'r':
 		rev = EARGF(usage());
 		break;
+	case 'c':
+		clean = 1;
+		break;
 	} ARGEND;
 
 	memset(&wd, 0, sizeof(wd));
@@ -225,27 +327,27 @@
 	if(memcmp(wd.p2hash, nullid, HASHSZ))
 		sysfatal("outstanding merge");
 
-	snprint(rpath, sizeof(rpath), "%s/%s", mtpt, rev);
-	if(readhash(rpath, "rev", rhash) != 0)
+	snprint(rp, sizeof(rp), "%s/%s", mtpt, rev);
+	if(readhash(rp, "rev", rh) != 0)
 		sysfatal("unable to get hash for %s", rev);
 
-	if(memcmp(rhash, wd.p1hash, HASHSZ) == 0){
+	if(memcmp(rh, 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);
+	ancestor(mtpt, wd.p1hash, rh, ah);
+	if(memcmp(ah, nullid, HASHSZ) == 0)
+		sysfatal("no common ancestor between %H and %H", wd.p1hash, rh);
 
-	if(memcmp(ahash, rhash, HASHSZ) == 0)
-		memmove(ahash, wd.p1hash, HASHSZ);
+	if(memcmp(ah, rh, HASHSZ) == 0)
+		memmove(ah, 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);
+	snprint(lp, sizeof(lp), "%s/%H/files", mtpt, wd.p1hash);
+	snprint(rp, sizeof(rp), "%s/%H/files", mtpt, rh);
+	snprint(ap, sizeof(ap), "%s/%H/files", mtpt, ah);
 	
-	changes(lpath, rpath, apath, &wd);
+	changes("-L", lp, rp, ap, apply0, &wd);
 
 	exits(0);
 }