1 /* hg debug stuff, will become update/merge program */
10 typedef struct Workdir Workdir;
11 typedef struct Dstate Dstate;
34 dslookup(Workdir *wd, char *path)
38 hp = &wd->ht[hashstr(path) % nelem(wd->ht)];
39 for(h = *hp; h != nil; h = *hp){
40 if(strcmp(path, h->path) == 0)
48 clearworkdir(Workdir *wd)
53 for(i=0; i<nelem(wd->ht); i++)
58 memset(wd, 0, sizeof(*wd));
62 loadworkdir(Workdir *wd, char *path)
65 char buf[MAXPATH], *err;
69 memset(wd, 0, sizeof(*wd));
70 if(getworkdir(wd->path, path) < 0)
72 snprint(buf, sizeof(buf), "%s/.hg/dirstate", wd->path);
73 if((fd = open(buf, OREAD)) < 0)
75 err = "dirstate truncated";
76 if(read(fd, wd->p1hash, HASHSZ) != HASHSZ)
78 if(read(fd, wd->p2hash, HASHSZ) != HASHSZ)
81 if((n = read(fd, hdr, sizeof(hdr))) == 0)
84 err = "reading dirstate: %r";
89 n = hdr[16] | hdr[15]<<8 | hdr[14]<<16 | hdr[13]<<24;
90 if(n < 0 || n >= sizeof(buf)){
91 err = "bad path length in dirstate";
94 if(read(fd, buf, n) != n)
97 hp = dslookup(wd, buf);
99 err = "duplicate entry in dirstate";
102 h = malloc(sizeof(*h) + n);
104 err = "out of memory";
107 memmove(h->path, buf, n);
109 h->mode = hdr[4] | hdr[3]<<8 | hdr[2]<<16 | hdr[1]<<24;
110 h->size = hdr[8] | hdr[7]<<8 | hdr[6]<<16 | hdr[5]<<24;
111 h->mtime = hdr[12] | hdr[11]<<8 | hdr[10]<<16 | hdr[9]<<24;
125 pjoin(char *path, char *name)
131 if(path[strlen(path)-1] == '/' || name[0] == '/')
132 return smprint("%s%s", path, name);
133 return smprint("%s/%s", path, name);
137 changes1(int fd, char *lpath, char *rpath, char *apath,
138 void (*apply)(char *, char *, char *, char *, char *, void *), void *aux)
143 Binit(&bin, fd, OREAD);
144 while((state = Brdstr(&bin, '\n', 1)) != nil){
145 if((name = strchr(state, '\t')) == nil)
147 while(*name == '\t' || *name == ' ')
149 if(name[0] == '.' && name[1] == '/')
151 apply(state, name, lpath, rpath, apath, aux);
157 changes(char *opt, char *lp, char *rp, char *ap,
158 void (*apply)(char *, char *, char *, char *, char *, void *), void *aux)
165 pid = rfork(RFPROC|RFMEM|RFFDG);
175 execl("/bin/derp", "derp", opt, "-p", "0111", lp, ap, rp, nil);
179 changes1(pfd[0], lp, rp, ap, apply, aux);
183 if(w->msg[0] != '\0'){
184 werrstr("%s", w->msg);
197 apply(char *state, char *name, char *lp, char *rp, char *ap, Workdir *)
202 // fprint(2, "### %s %s ->\t", state, name);
203 if(strcmp(state, "na") == 0){
206 if(rd->qid.type & QTDIR)
207 print("mkdir %s\n", lp);
209 print("cp %s %s\n", rp, lp);
212 else if(strcmp(state, "an") == 0){
214 else if(strcmp(state, "nm") == 0){
215 print("cp %s %s\n", rp, lp);
217 else if(strcmp(state, "mn") == 0){
219 else if(strcmp(state, "nd") == 0){
220 print("rm %s\n", lp);
222 else if(strcmp(state, "dn") == 0){
224 else if(strcmp(state, "aa!") == 0 || strcmp(state, "mm!") == 0){
227 if(ld != nil && rd != nil){
228 if(rd->qid.type & QTDIR)
229 print("# conflict # mkdir %s\n", lp);
230 else if(ld->qid.type & QTDIR)
231 print("# conflict # rm -r %s\n", lp);
233 print("# conflict # ape/diff3 %s %s %s >%s\n", lp, ap, rp, lp);
236 else if(strcmp(state, "md!") == 0){
237 print("# delete conflict # rm %s\n", lp);
239 else if(strcmp(state, "dm!") == 0){
240 print("# delete conflict # cp %s %s\n", rp, lp);
243 print("# unknown status %s %s\n", state, name);
250 apply1(char *state, char *name, char *lp, char *rp, char *ap, void *aux)
254 lp = pjoin(lp, name);
255 rp = pjoin(rp, name);
256 ap = pjoin(ap, name);
257 apply(state, lp + strlen(wd->path)+1, lp, rp, ap, wd);
264 apply0(char *state, char *name, char *lp, char *rp, char *ap, void *aux)
270 /* working dir clean */
271 apply1(state, name, wd->path, rp, ap, wd);
274 lp = pjoin(wd->path, name);
276 if(clean == 0 && ld != nil && (ld->qid.type & QTDIR) == 0){
277 /* check for changes in working directory */
278 rp = pjoin(rp, name);
279 ap = pjoin(ap, name);
280 changes("-Lcq", lp, rp, ap, apply1, wd);
284 /* working dir clean */
285 apply1(state, name, wd->path, rp, ap, wd);
294 fprint(2, "usage: %s [-m mtpt] [-r rev] [root]\n", argv0);
299 main(int argc, char *argv[])
301 char lp[MAXPATH], rp[MAXPATH], ap[MAXPATH];
302 uchar rh[HASHSZ], ah[HASHSZ];
306 fmtinstall('H', Hfmt);
313 mtpt = EARGF(usage());
316 rev = EARGF(usage());
323 memset(&wd, 0, sizeof(wd));
324 if(loadworkdir(&wd, *argv) < 0)
325 sysfatal("loadworkdir: %r");
327 if(memcmp(wd.p2hash, nullid, HASHSZ))
328 sysfatal("outstanding merge");
330 snprint(rp, sizeof(rp), "%s/%s", mtpt, rev);
331 if(readhash(rp, "rev", rh) != 0)
332 sysfatal("unable to get hash for %s", rev);
334 if(memcmp(rh, wd.p1hash, HASHSZ) == 0){
335 fprint(2, "up to date\n");
339 ancestor(mtpt, wd.p1hash, rh, ah);
340 if(memcmp(ah, nullid, HASHSZ) == 0)
341 sysfatal("no common ancestor between %H and %H", wd.p1hash, rh);
343 if(memcmp(ah, rh, HASHSZ) == 0)
344 memmove(ah, wd.p1hash, HASHSZ);
346 snprint(lp, sizeof(lp), "%s/%H/files", mtpt, wd.p1hash);
347 snprint(rp, sizeof(rp), "%s/%H/files", mtpt, rh);
348 snprint(ap, sizeof(ap), "%s/%H/files", mtpt, ah);
350 changes("-L", lp, rp, ap, apply0, &wd);