commit 25a880e1b423b178bccafb2f9d92dff53fc82261 from: Omar Polo via: Thomas Adam date: Sun Jul 03 22:07:55 2022 UTC got patch: don't loose the x bit when merging with diff3 This fixes a regression introduced with the diff3 merge: files merged this way have their permissions resetted after patch. The issue is due the fact that patch_file looks at a temporary files and not at the original "old file". Reported by and ok stsp@ commit - 762e07b8b32b19661fd3c2f50953dff2bd131359 commit + 25a880e1b423b178bccafb2f9d92dff53fc82261 blob - 368fbd370037258b78a059ae9f5d3bd0bb804b9b blob + 551b4f9956dd41cf8aa9e0682162b8288e5e553c --- lib/patch.c +++ lib/patch.c @@ -466,7 +466,7 @@ apply_hunk(FILE *tmp, struct got_patch_hunk *h, int *l } static const struct got_error * -patch_file(struct got_patch *p, FILE *orig, FILE *tmp, mode_t *mode) +patch_file(struct got_patch *p, FILE *orig, FILE *tmp) { const struct got_error *err = NULL; struct got_patch_hunk *h; @@ -486,7 +486,6 @@ patch_file(struct got_patch *p, FILE *orig, FILE *tmp, if (fstat(fileno(orig), &sb) == -1) return got_error_from_errno("fstat"); - *mode = sb.st_mode; copypos = 0; STAILQ_FOREACH(h, &p->head, entries) { @@ -648,6 +647,7 @@ apply_patch(int *overlapcnt, struct got_worktree *work struct patch_args *pa, got_cancel_cb cancel_cb, void *cancel_arg) { const struct got_error *err = NULL; + struct stat sb; int do_merge = 0, file_renamed = 0; char *oldlabel = NULL, *newlabel = NULL, *anclabel = NULL; char *oldpath = NULL, *newpath = NULL; @@ -695,9 +695,16 @@ apply_patch(int *overlapcnt, struct got_worktree *work goto done; } - if (p->old != NULL && (oldfile = fopen(oldpath, "r")) == NULL) { - err = got_error_from_errno2("open", oldpath); - goto done; + if (p->old != NULL) { + if ((oldfile = fopen(oldpath, "r")) == NULL) { + err = got_error_from_errno2("open", oldpath); + goto done; + } + if (fstat(fileno(oldfile), &sb) == -1) { + err = got_error_from_errno2("fstat", oldpath); + goto done; + } + mode = sb.st_mode; } err = got_opentemp_named(&tmppath, &tmpfile, template); @@ -705,7 +712,7 @@ apply_patch(int *overlapcnt, struct got_worktree *work goto done; outpath = tmppath; outfd = fileno(tmpfile); - err = patch_file(p, afile != NULL ? afile : oldfile, tmpfile, &mode); + err = patch_file(p, afile != NULL ? afile : oldfile, tmpfile); if (err) goto done; blob - a7ff83ea9847a8fa722fdbfda0cfc471da1d050d blob + c16e62c4b053ddda85d0a0c0b1761790032b168c --- regress/cmdline/patch.sh +++ regress/cmdline/patch.sh @@ -1458,6 +1458,7 @@ test_patch_merge_simple() { fi jot 10 > $testroot/wt/numbers + chmod +x $testroot/wt/numbers (cd $testroot/wt && got add numbers && got commit -m +numbers) \ > /dev/null ret=$? @@ -1507,7 +1508,15 @@ test_patch_merge_simple() { ret=$? if [ $ret -ne 0 ]; then diff -u $testroot/wt/numbers $testroot/wt/numbers.expected + test_done $testroot $ret + return 1 fi + + test -x $testroot/wt/numbers + ret=$? + if [ $ret -ne 0 ]; then + echo "numbers lost the executable bit" >&2 + fi test_done $testroot $ret }