commit - bbf94fd6ae7e0a158d5ad25a7e25c6f422136fcb
commit + 650a3405fbd209dde33ac82b91ac6bceb15104e4
blob - 2ff96da7823c45ecb7b30768597f413f7aef1b9e
blob + 398a62a30ab5ccc3cbc1d92618fb31d5c80dc9bd
--- lib/patch.c
+++ lib/patch.c
return got_error(GOT_ERR_PATCH_MALFORMED);
return apply_hunk(orig, tmp, h, &lineno, 0);
}
+
+ /* When deleting binary files there are no hunks to apply. */
+ if (p->new == NULL && STAILQ_EMPTY(&p->head))
+ return NULL;
if (fstat(fileno(orig), &sb) == -1)
return got_error_from_errno("fstat");
blob - 2629b8eb5ac5bf6ef386a08e8ee437b27ef5fd41
blob + a5ab7432c53352c80a292a19938782c1091de4d0
--- libexec/got-read-patch/got-read-patch.c
+++ libexec/got-read-patch/got-read-patch.c
}
static int
+binary_deleted(const char *line)
+{
+ const char *prefix = "Binary files ";
+ const char *suffix = " and /dev/null differ\n";
+ size_t len, d;
+
+ if (strncmp(line, prefix, strlen(prefix)) != 0)
+ return 0;
+ line += strlen(prefix);
+
+ len = strlen(line);
+ if (len <= strlen(suffix))
+ return 0;
+ d = len - strlen(suffix);
+ return (strcmp(line + d, suffix) == 0);
+}
+
+static const struct got_error *
+binaryfilename(const char *at, char **name)
+{
+ const char *suffix = " and /dev/null differ\n";
+ size_t len, d;
+
+ len = strlen(at);
+ if (len <= strlen(suffix))
+ return NULL;
+
+ d = len - strlen(suffix);
+ if (strcmp(at + d, suffix) != 0)
+ return NULL;
+
+ *name = strndup(at, d);
+ if (*name == NULL)
+ return got_error_from_errno("strndup");
+ return NULL;
+}
+
+static int
filexbit(const char *line)
{
char *m;
break;
} else if (!strncmp(line, "--- ", 4) ||
!strncmp(line, "+++ ", 4) ||
- !strncmp(line, "blob - ", 7)) {
+ !strncmp(line, "blob - ", 7) ||
+ binary_deleted(line)) {
/* rewind to previous line */
if (fseeko(fp, -linelen, SEEK_CUR) == -1)
err = got_error_from_errno("fseeko");
char *line = NULL;
size_t linesize = 0;
ssize_t linelen;
- int create, rename = 0, xbit = 0;
+ int create, delete_binary = 0, rename = 0, xbit = 0;
*done = 0;
*next = 0;
} else if (!git && !strncmp(line, "blob - ", 7)) {
free(blob);
err = blobid(line + 7, &blob, git);
+ } else if (!strncmp(line, "Binary files ", 13)) {
+ delete_binary = 1;
+ free(old);
+ err = binaryfilename(line + 13, &old);
} else if (rename && !strncmp(line, "rename to ", 10)) {
free(new);
err = filename(line + 10, &new);
* line.
*/
if (rename && old != NULL && new != NULL) {
+ *done = 1;
+ err = send_patch(old, new, commitid,
+ blob, xbit, git);
+ break;
+ }
+
+ /*
+ * Diffs that remove binary files have no hunks.
+ */
+ if (delete_binary && old != NULL) {
*done = 1;
err = send_patch(old, new, commitid,
blob, xbit, git);
blob - 9e3d4639d01241422b50bdddf316137ceb10d945
blob + 17d3810a7849186809369d7245dafdba62ab2db7
--- regress/cmdline/patch.sh
+++ regress/cmdline/patch.sh
test_done "$testroot" 0
}
+
+test_patch_remove_binary_file() {
+ local testroot=`test_init patch_remove_binary_file`
+
+ if ! got checkout $testroot/repo $testroot/wt >/dev/null; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ dd if=/dev/zero of=$testroot/wt/x bs=1 count=16 2>/dev/null >&2
+ (cd $testroot/wt && got add x && got commit -m +x) >/dev/null
+
+ (cd $testroot/wt && \
+ got branch demo && \
+ got rm x && \
+ got ci -m -x &&
+ got up -b master) >/dev/null
+
+ echo 'D x' > $testroot/stdout.expected
+ (cd $testroot/wt && got log -c demo -l 1 -p >patch)
+
+ (cd $testroot/wt && got patch <patch) > $testroot/stdout
+ if [ $? -ne 0 ]; then
+ echo 'patch failed' >&2
+ test_done $testroot 1
+ return 1
+ fi
+
+ if ! cmp -s $testroot/stdout.expected $testroot/stdout; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done $testroot 1
+ return 1
+ fi
+
+ # try again using a git produced diff
+ (cd $testroot/wt && got revert x) >/dev/null
+
+ (cd $testroot/repo && git show demo) >$testroot/wt/patch
+
+ (cd $testroot/wt && got patch <patch) > $testroot/stdout
+ if [ $? -ne 0 ]; then
+ echo 'patch failed' >&2
+ test_done $testroot 1
+ return 1
+ fi
+
+ if ! cmp -s $testroot/stdout.expected $testroot/stdout; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done $testroot 1
+ return 1
+ fi
+
+ # try again using a diff(1) style patch
+ (cd $testroot/wt && got revert x) >/dev/null
+
+ echo "Binary files x and /dev/null differ" >$testroot/wt/patch
+ (cd $testroot/wt && got patch <patch) >$testroot/stdout
+ if [ $? -ne 0 ]; then
+ echo 'patch failed' >&2
+ test_done $testroot 1
+ return 1
+ fi
+
+ if ! cmp -s $testroot/stdout.expected $testroot/stdout; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done $testroot 1
+ return 1
+ fi
+
+ test_done $testroot 0
+}
+
test_parseargs "$@"
run_test test_patch_basic
run_test test_patch_dont_apply
run_test test_patch_newfile_xbit_got_diff
run_test test_patch_newfile_xbit_git_diff
run_test test_patch_umask
+run_test test_patch_remove_binary_file