{
memset(state, 0, sizeof(*state));
state->prefix = prefix;
- state->prefix_length = state->prefix ? strlen(state->prefix) : 0;
state->lock_file = lock_file;
state->newfd = -1;
state->apply = 1;
unsigned int recount:1;
unsigned int conflicted_threeway:1;
unsigned int direct_to_threeway:1;
+ unsigned int crlf_in_old:1;
struct fragment *fragments;
char *result;
size_t resultsize;
* Does it begin with "a/$our-prefix" and such? Then this is
* very likely to apply to our directory.
*/
- if (!strncmp(name, state->prefix, state->prefix_length))
+ if (starts_with(name, state->prefix))
val = count_slashes(state->prefix);
else {
cp++;
- if (!strncmp(cp, state->prefix, state->prefix_length))
+ if (starts_with(cp, state->prefix))
val = count_slashes(state->prefix) + 1;
}
}
record_ws_error(state, result, line + 1, len - 2, state->linenr);
}
+/*
+ * Check if the patch has context lines with CRLF or
+ * the patch wants to remove lines with CRLF.
+ */
+static void check_old_for_crlf(struct patch *patch, const char *line, int len)
+{
+ if (len >= 2 && line[len-1] == '\n' && line[len-2] == '\r') {
+ patch->ws_rule |= WS_CR_AT_EOL;
+ patch->crlf_in_old = 1;
+ }
+}
+
+
/*
* Parse a unified diff. Note that this really needs to parse each
* fragment separately, since the only way to know the difference
if (!deleted && !added)
leading++;
trailing++;
+ check_old_for_crlf(patch, line, len);
if (!state->apply_in_reverse &&
state->ws_error_action == correct_ws_error)
check_whitespace(state, line, len, patch->ws_rule);
break;
case '-':
+ if (!state->apply_in_reverse)
+ check_old_for_crlf(patch, line, len);
if (state->apply_in_reverse &&
state->ws_error_action != nowarn_ws_error)
check_whitespace(state, line, len, patch->ws_rule);
trailing = 0;
break;
case '+':
+ if (state->apply_in_reverse)
+ check_old_for_crlf(patch, line, len);
if (!state->apply_in_reverse &&
state->ws_error_action != nowarn_ws_error)
check_whitespace(state, line, len, patch->ws_rule);
int i;
/* Paths outside are not touched regardless of "--include" */
- if (0 < state->prefix_length) {
- int pathlen = strlen(pathname);
- if (pathlen <= state->prefix_length ||
- memcmp(state->prefix, pathname, state->prefix_length))
+ if (state->prefix && *state->prefix) {
+ const char *rest;
+ if (!skip_prefix(pathname, state->prefix, &rest) || !*rest)
return 0;
}
add, pluses, del, minuses);
}
-static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
+static int read_old_data(struct stat *st, struct patch *patch,
+ const char *path, struct strbuf *buf)
{
+ enum safe_crlf safe_crlf = patch->crlf_in_old ?
+ SAFE_CRLF_KEEP_CRLF : SAFE_CRLF_RENORMALIZE;
switch (st->st_mode & S_IFMT) {
case S_IFLNK:
if (strbuf_readlink(buf, path, st->st_size) < 0)
case S_IFREG:
if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
return error(_("unable to open or read %s"), path);
- convert_to_git(&the_index, path, buf->buf, buf->len, buf, 0);
+ /*
+ * "git apply" without "--index/--cached" should never look
+ * at the index; the target file may not have been added to
+ * the index yet, and we may not even be in any Git repository.
+ * Pass NULL to convert_to_git() to stress this; the function
+ * should never look at the index when explicit crlf option
+ * is given.
+ */
+ convert_to_git(NULL, path, buf->buf, buf->len, buf, safe_crlf);
return 0;
default:
return -1;
struct strbuf *buf,
const struct cache_entry *ce,
struct stat *st,
+ struct patch *patch,
const char *name,
unsigned expected_mode)
{
} else if (has_symlink_leading_path(name, strlen(name))) {
return error(_("reading from '%s' beyond a symbolic link"), name);
} else {
- if (read_old_data(st, name, buf))
+ if (read_old_data(st, patch, name, buf))
return error(_("failed to read %s"), name);
}
}
/* We have a patched copy in memory; use that. */
strbuf_add(&buf, previous->result, previous->resultsize);
} else {
- status = load_patch_target(state, &buf, ce, st,
+ status = load_patch_target(state, &buf, ce, st, patch,
patch->old_name, patch->old_mode);
if (status < 0)
return status;
if (verify_index_match(ce, &st))
return error(_("%s: does not match index"), name);
- status = load_patch_target(state, &buf, ce, &st, name, mode);
+ status = load_patch_target(state, &buf, ce, &st, patch, name, mode);
if (status < 0)
return status;
else if (status)