commit eaef698f325c42c0fd48c56b391b56ce1695b9e7 from: Omar Polo via: Thomas Adam date: Sat Apr 23 20:32:50 2022 UTC got patch: allow to reverse a patch add a flag to got_patch to reverse a patch before applying and the -R flag for `got patch'. ok stsp@ commit - 656c2baa8669bb412dbff580940fa9ccd8bd1f1f commit + eaef698f325c42c0fd48c56b391b56ce1695b9e7 blob - bd6e06c564ce9499b313b1d667097c58c2d16873 blob + b91cfb2cb4963721a9a86be9c2cdb397bc1a9278 --- got/got.1 +++ got/got.1 @@ -1285,7 +1285,7 @@ option) .El .El .Tg pa -.It Cm patch Oo Fl n Oc Oo Fl p Ar strip-count Oc Op Ar patchfile +.It Cm patch Oo Fl n Oc Oo Fl p Ar strip-count Oc Oo Fl R Oc Op Ar patchfile .Dl Pq alias: Cm pa Apply changes from .Ar patchfile @@ -1367,6 +1367,8 @@ and path prefixes generated by .Xr git-diff 1 will be recognized and stripped automatically. +.It Fl R +Reverse the patch before applying it. .El .Tg rv .It Cm revert Oo Fl p Oc Oo Fl F Ar response-script Oc Oo Fl R Oc Ar path ... blob - f6b92557d2eee0e8e2d3f640073484578e59f901 blob + f9c01ed60741e8b0c4fe0cd7b1a5f41d8028199b --- got/got.c +++ got/got.c @@ -7152,8 +7152,8 @@ done: __dead static void usage_patch(void) { - fprintf(stderr, "usage: %s patch [-n] [-p strip-count] [patchfile]\n", - getprogname()); + fprintf(stderr, "usage: %s patch [-n] [-p strip-count] " + "[-R] [patchfile]\n", getprogname()); exit(1); } @@ -7242,10 +7242,10 @@ cmd_patch(int argc, char *argv[]) struct got_repository *repo = NULL; const char *errstr; char *cwd = NULL; - int ch, nop = 0, strip = -1; + int ch, nop = 0, strip = -1, reverse = 0; int patchfd; - while ((ch = getopt(argc, argv, "np:")) != -1) { + while ((ch = getopt(argc, argv, "np:R")) != -1) { switch (ch) { case 'n': nop = 1; @@ -7255,6 +7255,9 @@ cmd_patch(int argc, char *argv[]) if (errstr != NULL) errx(1, "pathname strip count is %s: %s", errstr, optarg); + break; + case 'R': + reverse = 1; break; default: usage_patch(); @@ -7303,7 +7306,7 @@ cmd_patch(int argc, char *argv[]) err(1, "pledge"); #endif - error = got_patch(patchfd, worktree, repo, nop, strip, + error = got_patch(patchfd, worktree, repo, nop, strip, reverse, &patch_progress, NULL, check_cancelled, NULL); done: blob - 62c76b0eb2926a03364ef10e416183cdfa18f398 blob + bc2e95bb4fa535617bc28f76935a78e36dea8a3e --- include/got_patch.h +++ include/got_patch.h @@ -32,4 +32,4 @@ typedef const struct got_error *(*got_patch_progress_c */ const struct got_error * got_patch(int, struct got_worktree *, struct got_repository *, int, int, - got_patch_progress_cb, void *, got_cancel_cb, void *); + int, got_patch_progress_cb, void *, got_cancel_cb, void *); blob - dc6334a1be3f413bfb06cfe4baceb43f78f17d9b blob + a78eeaa56dc3c8cdfaad854cf5af090572edd9ee --- lib/patch.c +++ lib/patch.c @@ -683,12 +683,41 @@ done: free(oldpath); free(newpath); return err; +} + +static void +reverse_patch(struct got_patch *p) +{ + struct got_patch_hunk *h; + size_t i; + long tmp; + + STAILQ_FOREACH(h, &p->head, entries) { + tmp = h->old_from; + h->old_from = h->new_from; + h->new_from = tmp; + + tmp = h->old_lines; + h->old_lines = h->new_lines; + h->new_lines = tmp; + + tmp = h->old_nonl; + h->old_nonl = h->new_nonl; + h->new_nonl = tmp; + + for (i = 0; i < h->len; ++i) { + if (*h->lines[i] == '+') + *h->lines[i] = '-'; + else if (*h->lines[i] == '-') + *h->lines[i] = '+'; + } + } } const struct got_error * got_patch(int fd, struct got_worktree *worktree, struct got_repository *repo, - int nop, int strip, got_patch_progress_cb progress_cb, void *progress_arg, - got_cancel_cb cancel_cb, void *cancel_arg) + int nop, int strip, int reverse, got_patch_progress_cb progress_cb, + void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg) { const struct got_error *err = NULL; struct got_fileindex *fileindex = NULL; @@ -747,6 +776,9 @@ got_patch(int fd, struct got_worktree *worktree, struc if (err || done) break; + if (reverse) + reverse_patch(&p); + err = got_worktree_patch_check_path(p.old, p.new, &oldpath, &newpath, worktree, repo, fileindex); if (err == NULL) blob - 5b848e84d9952da492bc0fefbca5dc76593b0ef5 blob + 43981599f51928fd929e8cc47538da750b875b97 --- regress/cmdline/patch.sh +++ regress/cmdline/patch.sh @@ -1398,7 +1398,51 @@ EOF fi test_done $testroot $ret } + +test_patch_reverse() { + local testroot=`test_init patch_reverse` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + test_done $testroot $ret + return 1 + fi + + cat < $testroot/wt/patch +--- alpha ++++ alpha +@@ -1 +1 @@ +-ALPHA +\ No newline at end of file ++alpha +EOF + (cd $testroot/wt && got patch -R patch) > $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + test_done $testroot $ret + return 1 + fi + + echo "M alpha" > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done $testroot $ret + return 1 + fi + + echo -n ALPHA > $testroot/wt/alpha.expected + cmp -s $testroot/wt/alpha.expected $testroot/wt/alpha + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/wt/alpha.expected $testroot/wt/alpha + fi + test_done $testroot $ret +} + test_parseargs "$@" run_test test_patch_simple_add_file run_test test_patch_simple_rm_file @@ -1423,3 +1467,4 @@ run_test test_patch_strip run_test test_patch_relative_paths run_test test_patch_with_path_prefix run_test test_patch_relpath_with_path_prefix +run_test test_patch_reverse