ref: d86a7ed412555192e2000a9a34b3372f380ec3d0
parent: 3839ad4d3c9b26b8a5d564d1d8f09490799e4cd7
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Aug 16 19:50:28 EDT 2022
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.
--- a/sys/man/1/patch
+++ b/sys/man/1/patch
@@ -28,6 +28,9 @@
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
--- a/sys/src/cmd/git/import
+++ b/sys/src/cmd/git/import
@@ -76,8 +76,16 @@
# 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 @@
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 ''
--- a/sys/src/cmd/git/rebase
+++ b/sys/src/cmd/git/rebase
@@ -7,8 +7,6 @@
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
--- a/sys/src/cmd/patch.c
+++ b/sys/src/cmd/patch.c
@@ -52,6 +52,7 @@
void (*addold)(Hunk*, char*);
Fchg *changed;
int nchanged;
+int dryrun;
char*
readline(Biobuf *f, int *lnum)
@@ -392,21 +393,22 @@
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 @@
sysfatal("strdup: %r");
changed[nchanged].tmp = tmp;
nchanged++;
- close(fd);
}
void
@@ -429,7 +430,14 @@
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 @@
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 @@
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 @@
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");
}
@@ -615,6 +627,9 @@
ARGBEGIN{
case 'p':
strip = atoi(EARGF(usage()));
+ break;
+ case 'n':
+ dryrun++;
break;
case 'R':
reverse++;