summaryrefslogtreecommitdiffstats
path: root/apply.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-20 05:14:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-20 05:14:39 +0000
commit7260c37aa8c91c8008dcd2442a19c23d1c9040fb (patch)
tree83953428f11212a71a4616e535c1053076f9bb94 /apply.c
parentReleasing progress-linux version 1:2.43.0-1~progress7.99u1. (diff)
downloadgit-7260c37aa8c91c8008dcd2442a19c23d1c9040fb.tar.xz
git-7260c37aa8c91c8008dcd2442a19c23d1c9040fb.zip
Merging upstream version 1:2.45.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'apply.c')
-rw-r--r--apply.c86
1 files changed, 56 insertions, 30 deletions
diff --git a/apply.c b/apply.c
index 3d69fec..901b67e 100644
--- a/apply.c
+++ b/apply.c
@@ -12,7 +12,6 @@
#include "base85.h"
#include "config.h"
#include "object-store-ll.h"
-#include "blob.h"
#include "delta.h"
#include "diff.h"
#include "dir.h"
@@ -78,7 +77,8 @@ static int parse_whitespace_option(struct apply_state *state, const char *option
return 0;
}
/*
- * Please update $__git_whitespacelist in git-completion.bash
+ * Please update $__git_whitespacelist in git-completion.bash,
+ * Documentation/git-apply.txt, and Documentation/git-am.txt
* when you add new options.
*/
return error(_("unrecognized whitespace option '%s'"), option);
@@ -1292,8 +1292,15 @@ static char *git_header_name(int p_value,
return NULL; /* no postimage name */
second = skip_tree_prefix(p_value, name + len + 1,
line_len - (len + 1));
+ /*
+ * If we are at the SP at the end of a directory,
+ * skip_tree_prefix() may return NULL as that makes
+ * it appears as if we have an absolute path.
+ * Keep going to find another SP.
+ */
if (!second)
- return NULL;
+ continue;
+
/*
* Does len bytes starting at "name" and "second"
* (that are separated by one HT or SP we just
@@ -2220,7 +2227,8 @@ static void reverse_patches(struct patch *p)
struct fragment *frag = p->fragments;
SWAP(p->new_name, p->old_name);
- SWAP(p->new_mode, p->old_mode);
+ if (p->new_mode)
+ SWAP(p->new_mode, p->old_mode);
SWAP(p->is_new, p->is_delete);
SWAP(p->lines_added, p->lines_deleted);
SWAP(p->old_oid_prefix, p->new_oid_prefix);
@@ -3704,8 +3712,10 @@ static int apply_data(struct apply_state *state, struct patch *patch,
fprintf(stderr, _("Falling back to direct application...\n"));
/* Note: with --reject, apply_fragments() returns 0 */
- if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0)
+ if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) {
+ clear_image(&image);
return -1;
+ }
}
patch->result = image.buf;
patch->resultsize = image.len;
@@ -3778,8 +3788,17 @@ static int check_preimage(struct apply_state *state,
return error_errno("%s", old_name);
}
- if (!state->cached && !previous)
- st_mode = ce_mode_from_stat(*ce, st->st_mode);
+ if (!state->cached && !previous) {
+ if (*ce && !(*ce)->ce_mode)
+ BUG("ce_mode == 0 for path '%s'", old_name);
+
+ if (trust_executable_bit)
+ st_mode = ce_mode_from_stat(*ce, st->st_mode);
+ else if (*ce)
+ st_mode = (*ce)->ce_mode;
+ else
+ st_mode = patch->old_mode;
+ }
if (patch->is_new < 0)
patch->is_new = 0;
@@ -4431,6 +4450,7 @@ static int create_one_file(struct apply_state *state,
const char *buf,
unsigned long size)
{
+ char *newpath = NULL;
int res;
if (state->cached)
@@ -4492,24 +4512,26 @@ static int create_one_file(struct apply_state *state,
unsigned int nr = getpid();
for (;;) {
- char newpath[PATH_MAX];
- mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
+ newpath = mkpathdup("%s~%u", path, nr);
res = try_create_file(state, newpath, mode, buf, size);
if (res < 0)
- return -1;
+ goto out;
if (!res) {
if (!rename(newpath, path))
- return 0;
+ goto out;
unlink_or_warn(newpath);
break;
}
if (errno != EEXIST)
break;
++nr;
+ FREE_AND_NULL(newpath);
}
}
- return error_errno(_("unable to write file '%s' mode %o"),
- path, mode);
+ res = error_errno(_("unable to write file '%s' mode %o"), path, mode);
+out:
+ free(newpath);
+ return res;
}
static int add_conflicted_stages_file(struct apply_state *state,
@@ -4592,7 +4614,7 @@ static int write_out_one_result(struct apply_state *state,
static int write_out_one_reject(struct apply_state *state, struct patch *patch)
{
FILE *rej;
- char namebuf[PATH_MAX];
+ char *namebuf;
struct fragment *frag;
int fd, cnt = 0;
struct strbuf sb = STRBUF_INIT;
@@ -4625,28 +4647,30 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
say_patch_name(stderr, sb.buf, patch);
strbuf_release(&sb);
- cnt = strlen(patch->new_name);
- if (ARRAY_SIZE(namebuf) <= cnt + 5) {
- cnt = ARRAY_SIZE(namebuf) - 5;
- warning(_("truncating .rej filename to %.*s.rej"),
- cnt - 1, patch->new_name);
- }
- memcpy(namebuf, patch->new_name, cnt);
- memcpy(namebuf + cnt, ".rej", 5);
+ namebuf = xstrfmt("%s.rej", patch->new_name);
fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
if (fd < 0) {
- if (errno != EEXIST)
- return error_errno(_("cannot open %s"), namebuf);
- if (unlink(namebuf))
- return error_errno(_("cannot unlink '%s'"), namebuf);
+ if (errno != EEXIST) {
+ error_errno(_("cannot open %s"), namebuf);
+ goto error;
+ }
+ if (unlink(namebuf)) {
+ error_errno(_("cannot unlink '%s'"), namebuf);
+ goto error;
+ }
fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
- if (fd < 0)
- return error_errno(_("cannot open %s"), namebuf);
+ if (fd < 0) {
+ error_errno(_("cannot open %s"), namebuf);
+ goto error;
+ }
}
rej = fdopen(fd, "w");
- if (!rej)
- return error_errno(_("cannot open %s"), namebuf);
+ if (!rej) {
+ error_errno(_("cannot open %s"), namebuf);
+ close(fd);
+ goto error;
+ }
/* Normal git tools never deal with .rej, so do not pretend
* this is a git patch by saying --git or giving extended
@@ -4670,6 +4694,8 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
fputc('\n', rej);
}
fclose(rej);
+error:
+ free(namebuf);
return -1;
}