diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-21 15:34:12 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-21 15:34:12 +0100 |
commit | 73744b9f4896c513d4d7c40ef4ce1d24703810e9 (patch) | |
tree | 0138790a8096a5117cceab05b82afded9e26618d | |
parent | f188f2f0738b4888130f9f07181f4cc367afb2d1 (diff) |
derp: handle file type changes
handle cases when files become directories or directories
become files.
-rw-r--r-- | sys/man/1/derp | 6 | ||||
-rw-r--r-- | sys/src/cmd/derp.c | 140 |
2 files changed, 100 insertions, 46 deletions
diff --git a/sys/man/1/derp b/sys/man/1/derp index 47d8a3c54..e3fb514a7 100644 --- a/sys/man/1/derp +++ b/sys/man/1/derp @@ -22,8 +22,10 @@ using a third common backup directory .I oldfile as reference. The changes found are printed to standard output, one per line, with the file -status describing either side followed by tabulator -and the relative file path. +status describing either sides actions followed +by tabulator and the relative file path which might +be empty in case when the changed files refers to the +ones given at program arguments. .LP The possible status codes: .TP diff --git a/sys/src/cmd/derp.c b/sys/src/cmd/derp.c index a16ef3b1e..6a3e1b560 100644 --- a/sys/src/cmd/derp.c +++ b/sys/src/cmd/derp.c @@ -31,6 +31,18 @@ error(char *fmt, ...) #pragma varargck argpos error 1 +void* +emalloc(int n) +{ + void *v; + + if((v = malloc(n)) == nil){ + noerror = 0; + error("out of memory"); + } + return v; +} + enum { BUFSIZE = 8*1024, }; @@ -146,16 +158,33 @@ statdir(char *path) d = dirstat(path); if(d == nil) error("can't stat %s: %r", path); - else - d->name = strdup(path); + else { + d->name = emalloc(strlen(path)+1); + strcpy(d->name, path); + } return d; } +char* +pjoin(char *path, char *name) +{ + char *s; + int n; + + n = strlen(path); + s = emalloc(n+strlen(name)+2); + strcpy(s, path); + if(path[0] != '\0' && path[n-1] != '/') + s[n++] = '/'; + strcpy(s+n, name); + return s; +} + Dir* absdir(Dir *d, char *path) { if(d != nil) - d->name = smprint("%s/%s", path, d->name); + d->name = pjoin(path, d->name); return d; } @@ -252,7 +281,7 @@ diffdir(Dir *ld, Dir *rd, Dir *ad, char *path) od = nil; if(t < 0){ - sp = smprint("%s/%s", path, ld[i].name); + sp = pjoin(path, ld[i].name); if(ap == lp) od = &ld[i]; else while(k < o){ @@ -270,7 +299,7 @@ diffdir(Dir *ld, Dir *rd, Dir *ad, char *path) od = nil; i++; } else { - sp = smprint("%s/%s", path, rd[j].name); + sp = pjoin(path, rd[j].name); if(ap == rp) od = &rd[j]; else while(k < o){ @@ -310,22 +339,23 @@ diffdir(Dir *ld, Dir *rd, Dir *ad, char *path) void diffgen(Dir *ld, Dir *rd, Dir *ad, char *path) { - char *p; - if(dcmp(ld, rd) == 0) return; - p = nil; if(ld == nil || rd == nil){ /* one side doesnt exit anymore */ if(ad != nil){ /* existed before, is deletion */ if(ld != nil && (ad->qid.type & QTDIR) && (ld->qid.type & QTDIR)){ /* remote deleted direcotry, remote newer */ - p = smprint("nd\t%s\n", path); + diffdir(ld, nil, ad, path); + print("nd\t%s\n", path); + return; } else if(rd != nil && (ad->qid.type & QTDIR) && (rd->qid.type & QTDIR)){ /* local deleted direcotry, local newer */ - p = smprint("dn\t%s\n", path); + diffdir(nil, rd, ad, path); + print("dn\t%s\n", path); + return; } else if(dcmp(rd, ad) == 0){ /* local deleted file, local newer */ print("dn\t%s\n", path); @@ -333,11 +363,23 @@ diffgen(Dir *ld, Dir *rd, Dir *ad, char *path) /* remote deleted file, remote newer */ print("nd\t%s\n", path); } else if(ld != nil){ + if((ld->qid.type ^ ad->qid.type) & QTDIR){ + /* local file type change, remote deleted, no conflict */ + diffgen(ld, nil, nil, path); + return; + } /* local modified, remote deleted, conflict */ print("md!\t%s\n", path); + return; } else { + if((rd->qid.type ^ ad->qid.type) & QTDIR){ + /* remote file type change, local deleted, no conflict */ + diffgen(nil, rd, nil, path); + return; + } /* remote modified, local deleted, conflict */ print("dm!\t%s\n", path); + return; } } else { /* didnt exist before, is addition */ @@ -355,70 +397,80 @@ diffgen(Dir *ld, Dir *rd, Dir *ad, char *path) if((ad->qid.type & QTDIR) && (ld->qid.type & QTDIR) && (rd->qid.type & QTDIR)){ /* all still directories, no problem */ } else if(dcmp(rd, ad) == 0){ + if((ld->qid.type ^ ad->qid.type) & QTDIR){ + /* local file type change */ + diffgen(nil, ad, ad, path); + diffgen(ld, nil, nil, path); + return; + } /* local modified file, local newer */ print("mn\t%s\n", path); } else if(dcmp(ld, ad) == 0){ + if((rd->qid.type ^ ad->qid.type) & QTDIR){ + /* remote file type change */ + diffgen(ad, nil, ad, path); + diffgen(nil, rd, nil, path); + return; + } /* remote modified file, remote newer */ print("nm\t%s\n", path); } else { - /* local and remote modified, conflict */ - print("mm!\t%s\n", path); + if((ld->qid.type & QTDIR) != (ad->qid.type & QTDIR) && + (rd->qid.type & QTDIR) != (ad->qid.type & QTDIR) && + (ld->qid.type & QTDIR) == (rd->qid.type & QTDIR)){ + if((ad->qid.type & QTDIR) == 0){ + /* local and remote became directories, was file before */ + diffdir(ld, rd, nil, path); + } else { + /* local and remote became diverging files, conflict */ + print("aa!\t%s\n", path); + } + } else { + /* local and remote modified, conflict */ + print("mm!\t%s\n", path); + } + return; } } else { /* didnt exist before, is addition from both */ if((ld->qid.type & QTDIR) && (rd->qid.type & QTDIR)){ /* local and remote added directories, no problem */ } else { - /* local and remote added files, conflict */ + /* local and remote added diverging files, conflict */ print("aa!\t%s\n", path); + return; } } } diffdir(ld, rd, ad, path); - - if(p != nil){ - print("%s", p); - free(p); - } } void diff3(char *lp, char *ap, char *rp) { Dir *ld, *rd, *ad; - char *name; - rd = ad = nil; - if((ld = statdir(lp)) == nil) - goto Out; - if((rd = statdir(rp)) == nil) + ad = nil; + ld = statdir(lp); + rd = statdir(rp); + if(ld == nil && rd == nil) goto Out; - - if(strcmp(ap, lp) == 0) + else if(strcmp(ap, lp) == 0) ad = ld; else if(strcmp(ap, rp) == 0) ad = rd; - else if((ad = statdir(ap)) == nil) - goto Out; - else if(samefile(ad, ld)){ - freedir(ad); - ad = ld; - } - else if(samefile(ad, rd)){ - freedir(ad); - ad = rd; - } - - if(ld->qid.type & QTDIR) - name = "."; - else { - if(name = strrchr(lp, '/')) - name++; - else - name = lp; + else if((ad = statdir(ap)) != nil){ + if(ld != nil && samefile(ad, ld)){ + freedir(ad); + ad = ld; + } + else if(rd != nil && samefile(ad, rd)){ + freedir(ad); + ad = rd; + } } - diffgen(ld, rd, ad, name); + diffgen(ld, rd, ad, ""); Out: freedir(ld); freedir(rd); |