hgfs: work in progress stuff...

This commit is contained in:
cinap_lenrek 2012-11-22 00:02:43 +01:00
parent 1d4ab25265
commit 5be7e69c26

View file

@ -28,6 +28,8 @@ struct Workdir
Dstate *ht[256]; Dstate *ht[256];
}; };
int clean = 0;
static Dstate** static Dstate**
dslookup(Workdir *wd, char *path) dslookup(Workdir *wd, char *path)
{ {
@ -119,37 +121,21 @@ Error:
return -1; return -1;
} }
void char*
apply1(char *state, char *name, char *lpath, char *rpath, Workdir *wd) pjoin(char *path, char *name)
{ {
char buf[MAXPATH]; if(path[0] == '\0')
Dir *d; path = "/";
Dstate *ds; if(name[0] == '\0')
return strdup(path);
ds = *dslookup(wd, name); if(path[strlen(path)-1] == '/' || name[0] == '/')
if(ds != nil){ return smprint("%s%s", path, name);
snprint(buf, sizeof(buf), "%s/%s", wd->path, name); return smprint("%s/%s", 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);
} }
void 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; char *state, *name;
Biobuf bin; Biobuf bin;
@ -162,31 +148,144 @@ applychanges(int fd, char *lpath, char *rpath, Workdir *wd)
*name++ = '\0'; *name++ = '\0';
if(name[0] == '.' && name[1] == '/') if(name[0] == '.' && name[1] == '/')
name += 2; name += 2;
apply1(state, name, lpath, rpath, wd); apply(state, name, lpath, rpath, apath, aux);
} }
Bterm(&bin); Bterm(&bin);
} }
void int
changes(char *lpath, char *rpath, char *apath, Workdir *wd) 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) if(pipe(pfd) < 0)
sysfatal("pipe: %r"); return -1;
switch(rfork(RFPROC|RFMEM|RFFDG)){ pid = rfork(RFPROC|RFMEM|RFFDG);
switch(pid){
case -1: case -1:
sysfatal("rfork: %r"); close(pfd[0]);
close(pfd[1]);
return -1;
case 0: case 0:
close(pfd[0]); close(pfd[0]);
dup(pfd[1], 1); dup(pfd[1], 1);
close(pfd[1]); close(pfd[1]);
execl("/bin/derp", "derp", "-L", "-p", "0111", lpath, apath, rpath, nil); execl("/bin/derp", "derp", opt, "-p", "0111", lp, ap, rp, nil);
sysfatal("execl: %r"); exits("exec");
} }
close(pfd[1]); close(pfd[1]);
applychanges(pfd[0], lpath, rpath, wd); changes1(pfd[0], lp, rp, ap, apply, aux);
close(pfd[0]); 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 void
@ -199,8 +298,8 @@ usage(void)
void void
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char lpath[MAXPATH], rpath[MAXPATH], apath[MAXPATH]; char lp[MAXPATH], rp[MAXPATH], ap[MAXPATH];
uchar rhash[HASHSZ], ahash[HASHSZ]; uchar rh[HASHSZ], ah[HASHSZ];
char *mtpt, *rev; char *mtpt, *rev;
Workdir wd; Workdir wd;
@ -216,6 +315,9 @@ main(int argc, char *argv[])
case 'r': case 'r':
rev = EARGF(usage()); rev = EARGF(usage());
break; break;
case 'c':
clean = 1;
break;
} ARGEND; } ARGEND;
memset(&wd, 0, sizeof(wd)); memset(&wd, 0, sizeof(wd));
@ -225,27 +327,27 @@ main(int argc, char *argv[])
if(memcmp(wd.p2hash, nullid, HASHSZ)) if(memcmp(wd.p2hash, nullid, HASHSZ))
sysfatal("outstanding merge"); sysfatal("outstanding merge");
snprint(rpath, sizeof(rpath), "%s/%s", mtpt, rev); snprint(rp, sizeof(rp), "%s/%s", mtpt, rev);
if(readhash(rpath, "rev", rhash) != 0) if(readhash(rp, "rev", rh) != 0)
sysfatal("unable to get hash for %s", rev); 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"); fprint(2, "up to date\n");
exits(0); exits(0);
} }
ancestor(mtpt, wd.p1hash, rhash, ahash); ancestor(mtpt, wd.p1hash, rh, ah);
if(memcmp(ahash, nullid, HASHSZ) == 0) if(memcmp(ah, nullid, HASHSZ) == 0)
sysfatal("no common ancestor between %H and %H", wd.p1hash, rhash); sysfatal("no common ancestor between %H and %H", wd.p1hash, rh);
if(memcmp(ahash, rhash, HASHSZ) == 0) if(memcmp(ah, rh, HASHSZ) == 0)
memmove(ahash, wd.p1hash, HASHSZ); memmove(ah, wd.p1hash, HASHSZ);
snprint(lpath, sizeof(lpath), "%s/%H/files", mtpt, wd.p1hash); snprint(lp, sizeof(lp), "%s/%H/files", mtpt, wd.p1hash);
snprint(rpath, sizeof(rpath), "%s/%H/files", mtpt, rhash); snprint(rp, sizeof(rp), "%s/%H/files", mtpt, rh);
snprint(apath, sizeof(apath), "%s/%H/files", mtpt, ahash); snprint(ap, sizeof(ap), "%s/%H/files", mtpt, ah);
changes(lpath, rpath, apath, &wd); changes("-L", lp, rp, ap, apply0, &wd);
exits(0); exits(0);
} }