commit - 65858f9a993c163be8f4af482e7b400535d61d17
commit + 38d61ead4d6e9ff3f44b8d6e0e7ff3d02ffcec26
blob - 703c22b84de200f2a0ec9fc0f7bdc70dc725ab20
blob + ab334cf0239cc3dcf0653836d82b513a55e0f1b6
--- lib/patch.c
+++ lib/patch.c
imsg_free(&imsg);
return err;
}
+
+static void
+reverse_patch(struct got_patch *p)
+{
+ struct got_patch_hunk *h;
+ size_t i;
+ int 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] = '+';
+ }
+ }
+}
+
/*
* Copy data from orig starting at copypos until pos into tmp.
* If pos is -1, copy until EOF.
apply_patch(int *overlapcnt, struct got_worktree *worktree,
struct got_repository *repo, struct got_fileindex *fileindex,
const char *old, const char *new, struct got_patch *p, int nop,
- struct patch_args *pa, got_cancel_cb cancel_cb, void *cancel_arg)
+ int reverse, struct patch_args *pa,
+ got_cancel_cb cancel_cb, void *cancel_arg)
{
const struct got_error *err = NULL;
struct stat sb;
return err;
else if (err == NULL)
do_merge = 1;
+ else if (reverse)
+ reverse_patch(p);
err = NULL;
}
goto done;
}
+ if (reverse) {
+ char *s;
+ FILE *t;
+
+ s = anclabel;
+ anclabel = newlabel;
+ newlabel = s;
+
+ t = afile;
+ afile = tmpfile;
+ tmpfile = t;
+ }
+
err = got_opentemp_named(&mergepath, &mergefile, template);
if (err)
goto done;
return err;
}
-static void
-reverse_patch(struct got_patch *p)
-{
- struct got_patch_hunk *h;
- size_t i;
- int 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, int reverse, got_patch_progress_cb progress_cb,
if (err || done)
break;
- if (reverse)
+ /* reversal application with merge base is done differently */
+ if (reverse && *p.blob == '\0')
reverse_patch(&p);
err = got_worktree_patch_check_path(p.old, p.new, &oldpath,
&newpath, worktree, repo, fileindex);
if (err == NULL)
err = apply_patch(&overlapcnt, worktree, repo,
- fileindex, oldpath, newpath, &p, nop, &pa,
- cancel_cb, cancel_arg);
+ fileindex, oldpath, newpath, &p, nop, reverse,
+ &pa, cancel_cb, cancel_arg);
if (err != NULL) {
failed = 1;
/* recoverable errors */
blob - 7901777201377549e2dce265cf173b09d716ee4d
blob + 5b3df4e132acb5f7a05acfcdaca7e9d1eb7ee25a
--- regress/cmdline/patch.sh
+++ regress/cmdline/patch.sh
fi
test_done $testroot $ret
}
+
+test_patch_merge_reverse() {
+ local testroot=`test_init patch_merge_simple`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+ jot 10 > $testroot/wt/numbers
+ (cd $testroot/wt && got add numbers && got commit -m +numbers) \
+ > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ local commit_id=`git_show_head $testroot/repo`
+
+ jot 10 | sed s/5/five/g > $testroot/wt/numbers
+ (cd $testroot/wt && got diff > $testroot/wt/patch \
+ && got commit -m 'edit numbers') > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ jot 10 | sed -e s/5/five/g -e s/6/six/g > $testroot/wt/numbers
+ (cd $testroot/wt && got commit -m 'edit numbers again') >/dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ (cd $testroot/wt && got patch -R patch) >/dev/null 2>&1
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "unexpectedly reverted the patch" >&2
+ test_done $testroot 1
+ return 1
+ fi
+
+ cat <<-EOF > $testroot/wt/numbers.expected
+ 1
+ 2
+ 3
+ 4
+ <<<<<<< --- numbers
+ 5
+ 6
+ ||||||| +++ numbers
+ five
+ =======
+ five
+ six
+ >>>>>>> commit $commit_id
+ 7
+ 8
+ 9
+ 10
+EOF
+
+ cmp -s $testroot/wt/numbers $testroot/wt/numbers.expected
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/wt/numbers $testroot/wt/numbers.expected
+ fi
+ test_done $testroot $ret
+}
+
test_parseargs "$@"
run_test test_patch_add_file
run_test test_patch_rm_file
run_test test_patch_merge_gitdiff
run_test test_patch_merge_conflict
run_test test_patch_merge_unknown_blob
+run_test test_patch_merge_reverse