derp: handle file type changes
handle cases when files become directories or directories become files.
This commit is contained in:
parent
f188f2f073
commit
73744b9f48
2 changed files with 100 additions and 46 deletions
|
@ -22,8 +22,10 @@ using a third common backup directory
|
||||||
.I oldfile
|
.I oldfile
|
||||||
as reference. The changes found are printed
|
as reference. The changes found are printed
|
||||||
to standard output, one per line, with the file
|
to standard output, one per line, with the file
|
||||||
status describing either side followed by tabulator
|
status describing either sides actions followed
|
||||||
and the relative file path.
|
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
|
.LP
|
||||||
The possible status codes:
|
The possible status codes:
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -31,6 +31,18 @@ error(char *fmt, ...)
|
||||||
|
|
||||||
#pragma varargck argpos error 1
|
#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 {
|
enum {
|
||||||
BUFSIZE = 8*1024,
|
BUFSIZE = 8*1024,
|
||||||
};
|
};
|
||||||
|
@ -146,16 +158,33 @@ statdir(char *path)
|
||||||
d = dirstat(path);
|
d = dirstat(path);
|
||||||
if(d == nil)
|
if(d == nil)
|
||||||
error("can't stat %s: %r", path);
|
error("can't stat %s: %r", path);
|
||||||
else
|
else {
|
||||||
d->name = strdup(path);
|
d->name = emalloc(strlen(path)+1);
|
||||||
|
strcpy(d->name, path);
|
||||||
|
}
|
||||||
return d;
|
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*
|
Dir*
|
||||||
absdir(Dir *d, char *path)
|
absdir(Dir *d, char *path)
|
||||||
{
|
{
|
||||||
if(d != nil)
|
if(d != nil)
|
||||||
d->name = smprint("%s/%s", path, d->name);
|
d->name = pjoin(path, d->name);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +281,7 @@ diffdir(Dir *ld, Dir *rd, Dir *ad, char *path)
|
||||||
|
|
||||||
od = nil;
|
od = nil;
|
||||||
if(t < 0){
|
if(t < 0){
|
||||||
sp = smprint("%s/%s", path, ld[i].name);
|
sp = pjoin(path, ld[i].name);
|
||||||
if(ap == lp)
|
if(ap == lp)
|
||||||
od = &ld[i];
|
od = &ld[i];
|
||||||
else while(k < o){
|
else while(k < o){
|
||||||
|
@ -270,7 +299,7 @@ diffdir(Dir *ld, Dir *rd, Dir *ad, char *path)
|
||||||
od = nil;
|
od = nil;
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
sp = smprint("%s/%s", path, rd[j].name);
|
sp = pjoin(path, rd[j].name);
|
||||||
if(ap == rp)
|
if(ap == rp)
|
||||||
od = &rd[j];
|
od = &rd[j];
|
||||||
else while(k < o){
|
else while(k < o){
|
||||||
|
@ -310,22 +339,23 @@ diffdir(Dir *ld, Dir *rd, Dir *ad, char *path)
|
||||||
void
|
void
|
||||||
diffgen(Dir *ld, Dir *rd, Dir *ad, char *path)
|
diffgen(Dir *ld, Dir *rd, Dir *ad, char *path)
|
||||||
{
|
{
|
||||||
char *p;
|
|
||||||
|
|
||||||
if(dcmp(ld, rd) == 0)
|
if(dcmp(ld, rd) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = nil;
|
|
||||||
if(ld == nil || rd == nil){
|
if(ld == nil || rd == nil){
|
||||||
/* one side doesnt exit anymore */
|
/* one side doesnt exit anymore */
|
||||||
if(ad != nil){
|
if(ad != nil){
|
||||||
/* existed before, is deletion */
|
/* existed before, is deletion */
|
||||||
if(ld != nil && (ad->qid.type & QTDIR) && (ld->qid.type & QTDIR)){
|
if(ld != nil && (ad->qid.type & QTDIR) && (ld->qid.type & QTDIR)){
|
||||||
/* remote deleted direcotry, remote newer */
|
/* 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)){
|
} else if(rd != nil && (ad->qid.type & QTDIR) && (rd->qid.type & QTDIR)){
|
||||||
/* local deleted direcotry, local newer */
|
/* 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){
|
} else if(dcmp(rd, ad) == 0){
|
||||||
/* local deleted file, local newer */
|
/* local deleted file, local newer */
|
||||||
print("dn\t%s\n", path);
|
print("dn\t%s\n", path);
|
||||||
|
@ -333,11 +363,23 @@ diffgen(Dir *ld, Dir *rd, Dir *ad, char *path)
|
||||||
/* remote deleted file, remote newer */
|
/* remote deleted file, remote newer */
|
||||||
print("nd\t%s\n", path);
|
print("nd\t%s\n", path);
|
||||||
} else if(ld != nil){
|
} 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 */
|
/* local modified, remote deleted, conflict */
|
||||||
print("md!\t%s\n", path);
|
print("md!\t%s\n", path);
|
||||||
|
return;
|
||||||
} else {
|
} 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 */
|
/* remote modified, local deleted, conflict */
|
||||||
print("dm!\t%s\n", path);
|
print("dm!\t%s\n", path);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* didnt exist before, is addition */
|
/* 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)){
|
if((ad->qid.type & QTDIR) && (ld->qid.type & QTDIR) && (rd->qid.type & QTDIR)){
|
||||||
/* all still directories, no problem */
|
/* all still directories, no problem */
|
||||||
} else if(dcmp(rd, ad) == 0){
|
} 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 */
|
/* local modified file, local newer */
|
||||||
print("mn\t%s\n", path);
|
print("mn\t%s\n", path);
|
||||||
} else if(dcmp(ld, ad) == 0){
|
} 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 */
|
/* remote modified file, remote newer */
|
||||||
print("nm\t%s\n", path);
|
print("nm\t%s\n", path);
|
||||||
} else {
|
} else {
|
||||||
/* local and remote modified, conflict */
|
if((ld->qid.type & QTDIR) != (ad->qid.type & QTDIR) &&
|
||||||
print("mm!\t%s\n", path);
|
(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 {
|
} else {
|
||||||
/* didnt exist before, is addition from both */
|
/* didnt exist before, is addition from both */
|
||||||
if((ld->qid.type & QTDIR) && (rd->qid.type & QTDIR)){
|
if((ld->qid.type & QTDIR) && (rd->qid.type & QTDIR)){
|
||||||
/* local and remote added directories, no problem */
|
/* local and remote added directories, no problem */
|
||||||
} else {
|
} else {
|
||||||
/* local and remote added files, conflict */
|
/* local and remote added diverging files, conflict */
|
||||||
print("aa!\t%s\n", path);
|
print("aa!\t%s\n", path);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diffdir(ld, rd, ad, path);
|
diffdir(ld, rd, ad, path);
|
||||||
|
|
||||||
if(p != nil){
|
|
||||||
print("%s", p);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
diff3(char *lp, char *ap, char *rp)
|
diff3(char *lp, char *ap, char *rp)
|
||||||
{
|
{
|
||||||
Dir *ld, *rd, *ad;
|
Dir *ld, *rd, *ad;
|
||||||
char *name;
|
|
||||||
|
|
||||||
rd = ad = nil;
|
ad = nil;
|
||||||
if((ld = statdir(lp)) == nil)
|
ld = statdir(lp);
|
||||||
|
rd = statdir(rp);
|
||||||
|
if(ld == nil && rd == nil)
|
||||||
goto Out;
|
goto Out;
|
||||||
if((rd = statdir(rp)) == nil)
|
else if(strcmp(ap, lp) == 0)
|
||||||
goto Out;
|
|
||||||
|
|
||||||
if(strcmp(ap, lp) == 0)
|
|
||||||
ad = ld;
|
ad = ld;
|
||||||
else if(strcmp(ap, rp) == 0)
|
else if(strcmp(ap, rp) == 0)
|
||||||
ad = rd;
|
ad = rd;
|
||||||
else if((ad = statdir(ap)) == nil)
|
else if((ad = statdir(ap)) != nil){
|
||||||
goto Out;
|
if(ld != nil && samefile(ad, ld)){
|
||||||
else if(samefile(ad, ld)){
|
freedir(ad);
|
||||||
freedir(ad);
|
ad = ld;
|
||||||
ad = ld;
|
}
|
||||||
|
else if(rd != nil && samefile(ad, rd)){
|
||||||
|
freedir(ad);
|
||||||
|
ad = rd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(samefile(ad, rd)){
|
diffgen(ld, rd, ad, "");
|
||||||
freedir(ad);
|
|
||||||
ad = rd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ld->qid.type & QTDIR)
|
|
||||||
name = ".";
|
|
||||||
else {
|
|
||||||
if(name = strrchr(lp, '/'))
|
|
||||||
name++;
|
|
||||||
else
|
|
||||||
name = lp;
|
|
||||||
}
|
|
||||||
diffgen(ld, rd, ad, name);
|
|
||||||
Out:
|
Out:
|
||||||
freedir(ld);
|
freedir(ld);
|
||||||
freedir(rd);
|
freedir(rd);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue