unsigned ws_rule;
int lines_added, lines_deleted;
int score;
+ int extension_linenr; /* first line specifying delete/new/rename/copy */
unsigned int is_toplevel_relative:1;
unsigned int inaccurate_eof:1;
unsigned int is_binary:1;
}
if (*name) {
- int len = strlen(*name);
char *another;
if (isnull)
return error(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"),
*name, state->linenr);
another = find_name(state, line, NULL, state->p_value, TERM_TAB);
- if (!another || memcmp(another, *name, len + 1)) {
+ if (!another || strcmp(another, *name)) {
free(another);
return error((side == DIFF_NEW_NAME) ?
_("git apply: bad git-diff - inconsistent new filename on line %d") :
}
free(another);
} else {
- /* expect "/dev/null" */
- if (memcmp("/dev/null", line, 9) || line[9] != '\n')
+ if (!starts_with(line, "/dev/null\n"))
return error(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr);
}
DIFF_NEW_NAME);
}
+static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
+{
+ char *end;
+ *mode = strtoul(line, &end, 8);
+ if (end == line || !isspace(*end))
+ return error(_("invalid mode on line %d: %s"), linenr, line);
+ return 0;
+}
+
static int gitdiff_oldmode(struct apply_state *state,
const char *line,
struct patch *patch)
{
- patch->old_mode = strtoul(line, NULL, 8);
- return 0;
+ return parse_mode_line(line, state->linenr, &patch->old_mode);
}
static int gitdiff_newmode(struct apply_state *state,
const char *line,
struct patch *patch)
{
- patch->new_mode = strtoul(line, NULL, 8);
- return 0;
+ return parse_mode_line(line, state->linenr, &patch->new_mode);
}
static int gitdiff_delete(struct apply_state *state,
memcpy(patch->new_sha1_prefix, line, len);
patch->new_sha1_prefix[len] = 0;
if (*ptr == ' ')
- patch->old_mode = strtoul(ptr+1, NULL, 8);
+ return gitdiff_oldmode(state, ptr + 1, patch);
return 0;
}
}
}
+static int check_header_line(struct apply_state *state, struct patch *patch)
+{
+ int extensions = (patch->is_delete == 1) + (patch->is_new == 1) +
+ (patch->is_rename == 1) + (patch->is_copy == 1);
+ if (extensions > 1)
+ return error(_("inconsistent header lines %d and %d"),
+ patch->extension_linenr, state->linenr);
+ if (extensions && !patch->extension_linenr)
+ patch->extension_linenr = state->linenr;
+ return 0;
+}
+
/* Verify that we recognize the lines following a git header */
static int parse_git_header(struct apply_state *state,
const char *line,
res = p->fn(state, line + oplen, patch);
if (res < 0)
return -1;
+ if (check_header_line(state, patch))
+ return -1;
if (res > 0)
return offset;
break;
patch->old_name = xstrdup(patch->def_name);
patch->new_name = xstrdup(patch->def_name);
}
- if (!patch->is_delete && !patch->new_name) {
+ if ((!patch->new_name && !patch->is_delete) ||
+ (!patch->old_name && !patch->is_new)) {
error(_("git diff header lacks filename information "
"(line %d)"), state->linenr);
return -128;