aboutsummaryrefslogtreecommitdiff
path: root/apply.c
diff options
context:
space:
mode:
authorJialong Wang <jerrywang183@yahoo.com>2026-03-17 12:23:20 -0400
committerJunio C Hamano <gitster@pobox.com>2026-03-17 11:08:24 -0700
commit838c0ba5004b37009d8d2649ed1be7b77770c2f0 (patch)
tree58bff4c7c03a4c5a3af441e85a28f7c908fa3f6c /apply.c
parentc5e15c9a58c0b32ec8be3ae96434834124de175e (diff)
downloadgit-838c0ba5004b37009d8d2649ed1be7b77770c2f0.tar.xz
apply: report input location in header parsing errors
Several header parsing errors in apply.c still report only line numbers. When applying more than one input, that does not tell the user which input the line belongs to. Report the patch input location for these header parsing errors, and update the related tests. While touching parse_git_diff_header(), update the helper state to use the current header line when reporting these errors. Signed-off-by: Jialong Wang <jerrywang183@yahoo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'apply.c')
-rw-r--r--apply.c86
1 files changed, 65 insertions, 21 deletions
diff --git a/apply.c b/apply.c
index b7b0a201b3..700809f3e6 100644
--- a/apply.c
+++ b/apply.c
@@ -42,6 +42,7 @@
struct gitdiff_data {
struct strbuf *root;
+ const char *patch_input_file;
int linenr;
int p_value;
};
@@ -900,7 +901,8 @@ static int parse_traditional_patch(struct apply_state *state,
}
}
if (!name)
- return error(_("unable to find filename in patch at line %d"), state->linenr);
+ return error(_("unable to find filename in patch at %s:%d"),
+ state->patch_input_file, state->linenr);
return 0;
}
@@ -937,20 +939,35 @@ static int gitdiff_verify_name(struct gitdiff_data *state,
if (*name) {
char *another;
- if (isnull)
+ if (isnull) {
+ if (state->patch_input_file)
+ return error(_("git apply: bad git-diff - expected /dev/null, got %s at %s:%d"),
+ *name, state->patch_input_file, state->linenr);
return error(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"),
*name, state->linenr);
+ }
another = find_name(state->root, line, NULL, state->p_value, TERM_TAB);
if (!another || strcmp(another, *name)) {
free(another);
+ if (state->patch_input_file)
+ return error((side == DIFF_NEW_NAME) ?
+ _("git apply: bad git-diff - inconsistent new filename at %s:%d") :
+ _("git apply: bad git-diff - inconsistent old filename at %s:%d"),
+ state->patch_input_file, state->linenr);
return error((side == DIFF_NEW_NAME) ?
- _("git apply: bad git-diff - inconsistent new filename on line %d") :
- _("git apply: bad git-diff - inconsistent old filename on line %d"), state->linenr);
+ _("git apply: bad git-diff - inconsistent new filename on line %d") :
+ _("git apply: bad git-diff - inconsistent old filename on line %d"),
+ state->linenr);
}
free(another);
} else {
- if (!is_dev_null(line))
- return error(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr);
+ if (!is_dev_null(line)) {
+ if (state->patch_input_file)
+ return error(_("git apply: bad git-diff - expected /dev/null at %s:%d"),
+ state->patch_input_file, state->linenr);
+ return error(_("git apply: bad git-diff - expected /dev/null on line %d"),
+ state->linenr);
+ }
}
return 0;
@@ -974,12 +991,19 @@ static int gitdiff_newname(struct gitdiff_data *state,
DIFF_NEW_NAME);
}
-static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
+static int parse_mode_line(const char *line,
+ const char *patch_input_file,
+ int linenr,
+ unsigned int *mode)
{
char *end;
*mode = strtoul(line, &end, 8);
- if (end == line || !isspace(*end))
+ if (end == line || !isspace(*end)) {
+ if (patch_input_file)
+ return error(_("invalid mode at %s:%d: %s"),
+ patch_input_file, linenr, line);
return error(_("invalid mode on line %d: %s"), linenr, line);
+ }
*mode = canon_mode(*mode);
return 0;
}
@@ -988,14 +1012,16 @@ static int gitdiff_oldmode(struct gitdiff_data *state,
const char *line,
struct patch *patch)
{
- return parse_mode_line(line, state->linenr, &patch->old_mode);
+ return parse_mode_line(line, state->patch_input_file, state->linenr,
+ &patch->old_mode);
}
static int gitdiff_newmode(struct gitdiff_data *state,
const char *line,
struct patch *patch)
{
- return parse_mode_line(line, state->linenr, &patch->new_mode);
+ return parse_mode_line(line, state->patch_input_file, state->linenr,
+ &patch->new_mode);
}
static int gitdiff_delete(struct gitdiff_data *state,
@@ -1314,6 +1340,7 @@ static int check_header_line(int linenr, struct patch *patch)
}
int parse_git_diff_header(struct strbuf *root,
+ const char *patch_input_file,
int *linenr,
int p_value,
const char *line,
@@ -1345,6 +1372,7 @@ int parse_git_diff_header(struct strbuf *root,
size -= len;
(*linenr)++;
parse_hdr_state.root = root;
+ parse_hdr_state.patch_input_file = patch_input_file;
parse_hdr_state.linenr = *linenr;
parse_hdr_state.p_value = p_value;
@@ -1382,6 +1410,7 @@ int parse_git_diff_header(struct strbuf *root,
int res;
if (len < oplen || memcmp(p->str, line, oplen))
continue;
+ parse_hdr_state.linenr = *linenr;
res = p->fn(&parse_hdr_state, line + oplen, patch);
if (res < 0)
return -1;
@@ -1396,12 +1425,20 @@ int parse_git_diff_header(struct strbuf *root,
done:
if (!patch->old_name && !patch->new_name) {
if (!patch->def_name) {
- error(Q_("git diff header lacks filename information when removing "
- "%d leading pathname component (line %d)",
- "git diff header lacks filename information when removing "
- "%d leading pathname components (line %d)",
- parse_hdr_state.p_value),
- parse_hdr_state.p_value, *linenr);
+ if (patch_input_file)
+ error(Q_("git diff header lacks filename information when removing "
+ "%d leading pathname component at %s:%d",
+ "git diff header lacks filename information when removing "
+ "%d leading pathname components at %s:%d",
+ parse_hdr_state.p_value),
+ parse_hdr_state.p_value, patch_input_file, *linenr);
+ else
+ error(Q_("git diff header lacks filename information when removing "
+ "%d leading pathname component (line %d)",
+ "git diff header lacks filename information when removing "
+ "%d leading pathname components (line %d)",
+ parse_hdr_state.p_value),
+ parse_hdr_state.p_value, *linenr);
return -128;
}
patch->old_name = xstrdup(patch->def_name);
@@ -1409,8 +1446,12 @@ done:
}
if ((!patch->new_name && !patch->is_delete) ||
(!patch->old_name && !patch->is_new)) {
- error(_("git diff header lacks filename information "
- "(line %d)"), *linenr);
+ if (patch_input_file)
+ error(_("git diff header lacks filename information at %s:%d"),
+ patch_input_file, *linenr);
+ else
+ error(_("git diff header lacks filename information (line %d)"),
+ *linenr);
return -128;
}
patch->is_toplevel_relative = 1;
@@ -1577,8 +1618,9 @@ static int find_header(struct apply_state *state,
struct fragment dummy;
if (parse_fragment_header(line, len, &dummy) < 0)
continue;
- error(_("patch fragment without header at line %d: %.*s"),
- state->linenr, (int)len-1, line);
+ error(_("patch fragment without header at %s:%d: %.*s"),
+ state->patch_input_file, state->linenr,
+ (int)len-1, line);
return -128;
}
@@ -1590,7 +1632,9 @@ static int find_header(struct apply_state *state,
* or mode change, so we handle that specially
*/
if (!memcmp("diff --git ", line, 11)) {
- int git_hdr_len = parse_git_diff_header(&state->root, &state->linenr,
+ int git_hdr_len = parse_git_diff_header(&state->root,
+ state->patch_input_file,
+ &state->linenr,
state->p_value, line, len,
size, patch);
if (git_hdr_len < 0)