diff options
author | Ori Bernstein <ori@eigenstate.org> | 2022-08-16 23:50:28 +0000 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2022-08-16 23:50:28 +0000 |
commit | d86a7ed412555192e2000a9a34b3372f380ec3d0 (patch) | |
tree | 3a6440f1f5731ea8ccd5b11469145ccf21f22f9b | |
parent | 3839ad4d3c9b26b8a5d564d1d8f09490799e4cd7 (diff) |
git/rebase: allow rebase without a clean tree
Here, patch grows a dry run option (-n), which allows
git/import to bail out early if it would patch files
that are dirty in tree.
Once git/import refuses to patch dirty files, git/rebase
can skip checking if the whole tree is clean, which is
both convenient and much faster on large trees.
-rw-r--r-- | sys/man/1/patch | 3 | ||||
-rw-r--r--[-rwxr-xr-x] | sys/src/cmd/git/import | 12 | ||||
-rw-r--r--[-rwxr-xr-x] | sys/src/cmd/git/rebase | 2 | ||||
-rw-r--r-- | sys/src/cmd/patch.c | 67 |
4 files changed, 54 insertions, 30 deletions
diff --git a/sys/man/1/patch b/sys/man/1/patch index 9178d0c02..543885ffd 100644 --- a/sys/man/1/patch +++ b/sys/man/1/patch @@ -28,6 +28,9 @@ The following options are supported: Reverse direction of the patch. Additions become removals, and the new and old file names are swapped. .TP +.B -n +Print the files that would be modified by this patch, but do not apply it. +.TP .BI -p \ nstrip Remove the prefix containing .I nstrip diff --git a/sys/src/cmd/git/import b/sys/src/cmd/git/import index 0cc450bf8..102a4fdcd 100755..100644 --- a/sys/src/cmd/git/import +++ b/sys/src/cmd/git/import @@ -76,8 +76,16 @@ fn apply @{ # force re-reading env rc -c ' - echo applying $msg | sed 1q date=`{seconds $date} + files=`$nl{patch -np1 < $diffpath} + if(! git/walk -q $files){ + >[1=2] { + echo patch would clobber files: + git/walk $files + exit clobber + } + } + echo applying $msg | sed 1q if(! files=`$nl{patch -p1 < $diffpath}) die ''patch failed'' for(f in $files){ @@ -111,6 +119,6 @@ for(p in $patches){ if(test -d $p && test -f $p/header && test -f $p/body) {{cat $p/header; echo; cat $p/body} | apply} || die $status if not - apply < $p || die $status + apply < $p } exit '' diff --git a/sys/src/cmd/git/rebase b/sys/src/cmd/git/rebase index 395f3e693..a2aef6c2f 100755..100644 --- a/sys/src/cmd/git/rebase +++ b/sys/src/cmd/git/rebase @@ -7,8 +7,6 @@ flagfmt='a:abort, r:resume, i:interactive'; args='onto' eval `''{aux/getflags $*} || exec aux/usage tmp=_rebase.working -if(! git/walk -q) - die dirty working tree if(~ $#abort 1){ if(! test -f .git/rebase.todo) die no rebase to abort diff --git a/sys/src/cmd/patch.c b/sys/src/cmd/patch.c index 000edb104..8e402bba8 100644 --- a/sys/src/cmd/patch.c +++ b/sys/src/cmd/patch.c @@ -52,6 +52,7 @@ void (*addnew)(Hunk*, char*); void (*addold)(Hunk*, char*); Fchg *changed; int nchanged; +int dryrun; char* readline(Biobuf *f, int *lnum) @@ -392,21 +393,22 @@ blat(char *old, char *new, char *o, usize len) char *tmp; int fd; - if(strcmp(new, "/dev/null") == 0){ - if(len != 0) - sysfatal("diff modifies removed file"); - if(remove(old) == -1) - sysfatal("removeold %s: %r", old); + if(strcmp(new, "/dev/null") == 0 && len != 0){ + sysfatal("diff modifies removed file"); return; } - if(mkpath(new) == -1) - sysfatal("mkpath %s: %r", new); - if((tmp = smprint("%s.tmp%d", new, getpid())) == nil) - sysfatal("smprint: %r"); - if((fd = create(tmp, OWRITE, 0666)) == -1) - sysfatal("open %s: %r", tmp); - if(write(fd, o, len) != len) - sysfatal("write %s: %r", tmp); + tmp = nil; + if(!dryrun){ + if(mkpath(new) == -1) + sysfatal("mkpath %s: %r", new); + if((tmp = smprint("%s.tmp%d", new, getpid())) == nil) + sysfatal("smprint: %r"); + if((fd = create(tmp, OWRITE, 0666)) == -1) + sysfatal("open %s: %r", tmp); + if(write(fd, o, len) != len) + sysfatal("write %s: %r", tmp); + close(fd); + } if((changed = realloc(changed, (nchanged+1)*sizeof(Fchg))) == nil) sysfatal("realloc: %r"); if((changed[nchanged].new = strdup(new)) == nil) @@ -415,7 +417,6 @@ blat(char *old, char *new, char *o, usize len) sysfatal("strdup: %r"); changed[nchanged].tmp = tmp; nchanged++; - close(fd); } void @@ -429,7 +430,14 @@ finish(int ok) if(!ok){ if(remove(c->tmp) == -1) fprint(2, "remove %s: %r\n", c->tmp); - }else{ + goto Free; + } + if(!dryrun){ + if(strcmp(c->new, "/dev/null") == 0){ + if(remove(c->old) == -1) + sysfatal("remove %s: %r", c->old); + goto Print; + } if((fd = open(c->tmp, ORDWR)) == -1) sysfatal("open %s: %r", c->tmp); if(strcmp(c->old, c->new) == 0 && remove(c->old) == -1) @@ -438,11 +446,13 @@ finish(int ok) sysfatal("create %s: %r", c->new); if(close(fd) == -1) sysfatal("close %s: %r", c->tmp); - if(strcmp(c->new, "/dev/null") == 0) - print("%s\n", c->old); - else - print("%s\n", c->new); } +Print: + if(strcmp(c->new, "/dev/null") == 0) + print("%s\n", c->old); + else + print("%s\n", c->new); +Free: free(c->tmp); free(c->old); free(c->new); @@ -560,16 +570,18 @@ apply(Patch *p, char *fname) for(i = 0; i < p->nhunk; i++){ h = &p->hunk[i]; if(curfile == nil || strcmp(curfile, h->newpath) != 0){ - if(slurp(&f, h->oldpath) == -1) + if(!dryrun && slurp(&f, h->oldpath) == -1) sysfatal("slurp %s: %r", h->oldpath); curfile = h->newpath; e = f.buf; } - s = e; - e = search(&f, h, fname); - o = append(o, &osz, s, e); - o = append(o, &osz, h->new, h->new + h->newlen); - e += h->oldlen; + if(!dryrun){ + s = e; + e = search(&f, h, fname); + o = append(o, &osz, s, e); + o = append(o, &osz, h->new, h->new + h->newlen); + e += h->oldlen; + } if(i+1 == p->nhunk || strcmp(curfile, p->hunk[i+1].newpath) != 0){ o = append(o, &osz, e, f.buf + f.len); blat(h->oldpath, h->newpath, o, osz); @@ -601,7 +613,7 @@ freepatch(Patch *p) void usage(void) { - fprint(2, "usage: %s [-R] [-p nstrip] [patch...]\n", argv0); + fprint(2, "usage: %s [-nR] [-p nstrip] [patch...]\n", argv0); exits("usage"); } @@ -616,6 +628,9 @@ main(int argc, char **argv) case 'p': strip = atoi(EARGF(usage())); break; + case 'n': + dryrun++; + break; case 'R': reverse++; break; |