summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2022-08-16 23:50:28 +0000
committerOri Bernstein <ori@eigenstate.org>2022-08-16 23:50:28 +0000
commitd86a7ed412555192e2000a9a34b3372f380ec3d0 (patch)
tree3a6440f1f5731ea8ccd5b11469145ccf21f22f9b
parent3839ad4d3c9b26b8a5d564d1d8f09490799e4cd7 (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/patch3
-rw-r--r--[-rwxr-xr-x]sys/src/cmd/git/import12
-rw-r--r--[-rwxr-xr-x]sys/src/cmd/git/rebase2
-rw-r--r--sys/src/cmd/patch.c67
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;