commit - 1996dd729051837a7a27478ca4db7879691b3be9
commit + 37e766f45c2e1cc637f4b0a0be03f125e65f8ebd
blob - 28231bbf9bfed76cccd642d016636c357a469dee
blob + 83e7c1339c1b5f78266924cf2f94e4a9cfcae8da
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
*/
struct got_imsg_patch {
int git;
+ int xbit;
char old[PATH_MAX];
char new[PATH_MAX];
char cid[41];
blob - 1dac0c931a643d7ea49af837d8b4af3d5c7e7f61
blob + 7da6f3ed987765fc1335933affad2032771fd8a6
--- lib/patch.c
+++ lib/patch.c
STAILQ_HEAD(got_patch_hunk_head, got_patch_hunk);
struct got_patch {
+ int xbit;
char *old;
char *new;
char cid[41];
if (*patch.blob != '\0')
strlcpy(p->blob, patch.blob, sizeof(p->blob));
+
+ p->xbit = patch.xbit;
/* automatically set strip=1 for git-style diffs */
if (strip == -1 && patch.git &&
goto done;
}
mode = sb.st_mode;
- }
+ } else if (p->xbit)
+ mode |= (S_IXUSR | S_IXGRP | S_IXOTH);
err = got_opentemp_named(&tmppath, &tmpfile, template);
if (err)
blob - 35166a4635c2ff0fb604cc64b1b8df2669a70358
blob + 2f96f78243ecc7610927ef5df3b037cb40f8b7d2
--- libexec/got-read-patch/got-read-patch.c
+++ libexec/got-read-patch/got-read-patch.c
static const struct got_error *
send_patch(const char *oldname, const char *newname, const char *commitid,
- const char *blob, int git)
+ const char *blob, const int xbit, int git)
{
struct got_imsg_patch p;
if (blob != NULL)
strlcpy(p.blob, blob, sizeof(p.blob));
+ p.xbit = xbit;
p.git = git;
if (imsg_compose(&ibuf, GOT_IMSG_PATCH, 0, 0, -1, &p, sizeof(p)) == -1)
return got_error_from_errno("imsg_compose GOT_IMSG_PATCH");
return NULL;
}
+static int
+filexbit(const char *line)
+{
+ char *m;
+
+ m = strchr(line, '(');
+ if (m && !strncmp(m + 1, "mode ", 5))
+ return strncmp(m + 6, "755", 3) == 0;
+
+ return 0;
+}
+
static const struct got_error *
blobid(const char *line, char **blob, int git)
{
char *line = NULL;
size_t linesize = 0;
ssize_t linelen;
- int create, rename = 0;
+ int create, rename = 0, xbit = 0;
*done = 0;
*next = 0;
} else if (!strncmp(line, "+++ ", 4)) {
free(new);
err = filename(line+4, &new);
+ } else if (!strncmp(line, "blob + ", 7)) {
+ xbit = filexbit(line);
} else if (!git && !strncmp(line, "blob - ", 7)) {
free(blob);
err = blobid(line + 7, &blob, git);
err = filename(line + 10, &new);
} else if (git && !strncmp(line, "similarity index 100%", 21))
rename = 1;
+ else if (git && !strncmp(line, "new file mode 100", 17))
+ xbit = strncmp(line + 17, "755", 3) == 0;
else if (git && !strncmp(line, "index ", 6)) {
free(blob);
err = blobid(line + 6, &blob, git);
if (rename && old != NULL && new != NULL) {
*done = 1;
err = send_patch(old, new, commitid,
- blob, git);
+ blob, xbit, git);
break;
}
err = got_error(GOT_ERR_PATCH_MALFORMED);
else
err = send_patch(old, new, commitid,
- blob, git);
+ blob, xbit, git);
if (err)
break;
blob - 1854b36c0fa1e88ead530f05e4b4011f623a055c
blob + 1bcdb584a653439ff381dc63d0dc88145ee8fa36
--- regress/cmdline/patch.sh
+++ regress/cmdline/patch.sh
ret=$?
if [ $ret -ne 0 ]; then
diff -u $testroot/wt/numbers $testroot/wt/numbers.expected
+ fi
+ test_done $testroot $ret
+}
+
+test_patch_newfile_xbit_got_diff() {
+ local testroot=`test_init patch_newfile_xbit`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ cat <<EOF > $testroot/wt/patch
+blob - /dev/null
+blob + abcdef0123456789abcdef012345678901234567 (mode 755)
+--- /dev/null
++++ xfile
+@@ -0,0 +1,1 @@
++xfile
+EOF
+
+ (cd $testroot/wt && got patch patch) > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
fi
+
+ if [ ! -x $testroot/wt/xfile ]; then
+ echo "failed to set xbit on newfile" >&2
+ test_done $testroot 1
+ return 1
+ fi
+
+ echo xfile > $testroot/wt/xfile.expected
+ cmp -s $testroot/wt/xfile $testroot/wt/xfile.expected
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "fail"
+ diff -u $testroot/wt/xfile $testroot/wt/xfile.expected
+ fi
+
test_done $testroot $ret
}
+test_patch_newfile_xbit_git_diff() {
+ local testroot=`test_init patch_newfile_xbit`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ cat <<EOF > $testroot/wt/patch
+diff --git a/xfile b/xfile
+new file mode 100755
+index 00000000..abcdef01
+--- /dev/null
++++ b/xfile
+@@ -0,0 +1,1 @@
++xfile
+EOF
+
+ (cd $testroot/wt && got patch patch) > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done $testroot $ret
+ return 1
+ fi
+
+ if [ ! -x $testroot/wt/xfile ]; then
+ echo "failed to set xbit on newfile" >&2
+ test_done $testroot 1
+ return 1
+ fi
+
+ echo xfile > $testroot/wt/xfile.expected
+ cmp -s $testroot/wt/xfile $testroot/wt/xfile.expected
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "fail"
+ diff -u $testroot/wt/xfile $testroot/wt/xfile.expected
+ fi
+
+ test_done $testroot $ret
+}
+
test_parseargs "$@"
run_test test_patch_basic
run_test test_patch_dont_apply
run_test test_patch_merge_conflict
run_test test_patch_merge_unknown_blob
run_test test_patch_merge_reverse
+run_test test_patch_newfile_xbit_got_diff
+run_test test_patch_newfile_xbit_git_diff