commit eaf99875e8a296a7a1128d804339ed1935f8d2a0 from: Omar Polo via: Thomas Adam date: Tue Mar 22 17:53:28 2022 UTC add a dry-run/nop mode for got patch with lots of help from stsp for the manpage bits! commit - 10e55613cb8d8b5d1829a732694d6259647d7821 commit + eaf99875e8a296a7a1128d804339ed1935f8d2a0 blob - 909c1b2c7ed3e00761357cb9ab0aaa679878483b blob + 7cb9fdf4c904187bc1843d43438daa6488dc9351 --- got/got.c +++ got/got.c @@ -7247,7 +7247,7 @@ cmd_patch(int argc, char *argv[]) err(1, "pledge"); #endif - error = got_patch(patchfd, worktree, repo, &print_remove_status, + error = got_patch(patchfd, worktree, repo, nop, &print_remove_status, NULL, &add_progress, NULL, check_cancelled, NULL); done: blob - 448bb17e65d75d8d5ba94bd577f5cde4fef566bf blob + 5f28ffc619f1b4e32ba37ff8e5361c636009ba74 --- include/got_patch.h +++ include/got_patch.h @@ -21,6 +21,6 @@ * The patch file descriptor *must* be seekable. */ const struct got_error * -got_patch(int, struct got_worktree *, struct got_repository *, +got_patch(int, struct got_worktree *, struct got_repository *, int, got_worktree_delete_cb, void *, got_worktree_checkout_cb, void *, got_cancel_cb, void *); blob - 7cc802afd65fee4f4cb23b39ba22943ec3808115 blob + ea8b97c6a17bb7946eb5f67b37c2aefd994bf7cc --- lib/patch.c +++ lib/patch.c @@ -399,6 +399,8 @@ patch_file(struct got_patch *p, const char *path, FILE h = STAILQ_FIRST(&p->head); if (h == NULL || STAILQ_NEXT(h, entries) != NULL) return got_error(GOT_ERR_PATCH_MALFORMED); + if (p->nop) + return NULL; for (i = 0; i < h->len; ++i) { if (fprintf(tmp, "%s", h->lines[i]+1) < 0) return got_error_from_errno("fprintf"); @@ -420,7 +422,8 @@ patch_file(struct got_patch *p, const char *path, FILE err = locate_hunk(orig, h, &pos, &lineno); if (err != NULL) goto done; - err = copy(tmp, orig, copypos, pos); + if (!p->nop) + err = copy(tmp, orig, copypos, pos); if (err != NULL) goto done; copypos = pos; @@ -458,7 +461,15 @@ patch_file(struct got_patch *p, const char *path, FILE } } - if (!feof(orig)) + + if (p->new == NULL) { + struct stat sb; + + if (fstat(fileno(orig), &sb) == -1) + err = got_error_from_errno("fstat"); + else if (sb.st_size != copypos) + err = got_error(GOT_ERR_PATCH_DONT_APPLY); + } else if (!p->nop && !feof(orig)) err = copy(tmp, orig, copypos, -1); done: @@ -602,13 +613,23 @@ apply_patch(struct got_worktree *worktree, struct got_ goto done; } - err = got_opentemp_named(&tmppath, &tmp, template); + if (!p->nop) + err = got_opentemp_named(&tmppath, &tmp, template); if (err) goto done; err = patch_file(p, oldpath, tmp); if (err) goto done; + if (p->nop) + goto done; + + if (p->old != NULL && p->new == NULL) { + err = got_worktree_schedule_delete(worktree, &oldpaths, + 0, NULL, delete_cb, delete_arg, repo, 0, 0); + goto done; + } + if (rename(tmppath, newpath) == -1) { err = got_error_from_errno3("rename", tmppath, newpath); goto done; @@ -642,7 +663,7 @@ done: const struct got_error * got_patch(int fd, struct got_worktree *worktree, struct got_repository *repo, - got_worktree_delete_cb delete_cb, void *delete_arg, + int nop, got_worktree_delete_cb delete_cb, void *delete_arg, got_worktree_checkout_cb add_cb, void *add_arg, got_cancel_cb cancel_cb, void *cancel_arg) { blob - 9a300a816a79b7eacef07263e7bd7cbce706ae25 blob + 41f290c529e09c20b73b0a6752c3351664a9559d --- regress/cmdline/patch.sh +++ regress/cmdline/patch.sh @@ -910,7 +910,60 @@ EOF ret=$? if [ $ret -eq 0 ]; then diff -u $testroot/stderr.expected $testroot/stderr + fi + test_done $testroot $ret +} + +test_patch_nop() { + local testroot=`test_init patch_nop` + + 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 ++cafe alpha +--- beta ++++ /dev/null +@@ -1 +0,0 @@ +-beta +--- gamma/delta ++++ gamma/delta.new +@@ -1 +1 @@ +-delta ++delta updated and renamed! +EOF + + (cd $testroot/wt && got patch -n patch) + ret=$? + if [ $ret -ne 0 ]; then + test_done $testroot $ret + return 1 fi + + # remove the patch to avoid the ? entry + rm $testroot/wt/patch + + (cd $testroot/wt && got status) > $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + test_done $testroot $ret + return 1 + fi + + echo -n > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi test_done $testroot $ret } @@ -928,3 +981,4 @@ run_test test_patch_no_patch run_test test_patch_equals_for_context run_test test_patch_rename run_test test_patch_illegal_status +run_test test_patch_nop