summaryrefslogtreecommitdiff
path: root/apply.c
diff options
context:
space:
mode:
Diffstat (limited to 'apply.c')
-rw-r--r--apply.c114
1 files changed, 78 insertions, 36 deletions
diff --git a/apply.c b/apply.c
index 8bbe6ed224..c9fb45247d 100644
--- a/apply.c
+++ b/apply.c
@@ -14,7 +14,7 @@
#include "abspath.h"
#include "base85.h"
#include "config.h"
-#include "object-store.h"
+#include "odb.h"
#include "delta.h"
#include "diff.h"
#include "dir.h"
@@ -48,9 +48,9 @@ struct gitdiff_data {
static void git_apply_config(void)
{
- git_config_get_string("apply.whitespace", &apply_default_whitespace);
- git_config_get_string("apply.ignorewhitespace", &apply_default_ignorewhitespace);
- git_config(git_xmerge_config, NULL);
+ repo_config_get_string(the_repository, "apply.whitespace", &apply_default_whitespace);
+ repo_config_get_string(the_repository, "apply.ignorewhitespace", &apply_default_ignorewhitespace);
+ repo_config(the_repository, git_xmerge_config, NULL);
}
static int parse_whitespace_option(struct apply_state *state, const char *option)
@@ -1640,6 +1640,14 @@ static void record_ws_error(struct apply_state *state,
state->squelch_whitespace_errors < state->whitespace_error)
return;
+ /*
+ * line[len] for an incomplete line points at the "\n" at the end
+ * of patch input line, so "%.*s" would drop the last letter on line;
+ * compensate for it.
+ */
+ if (result & WS_INCOMPLETE_LINE)
+ len++;
+
err = whitespace_error_string(result);
if (state->apply_verbosity > verbosity_silent)
fprintf(stderr, "%s:%d: %s.\n%.*s\n",
@@ -1671,6 +1679,35 @@ static void check_old_for_crlf(struct patch *patch, const char *line, int len)
/*
+ * Just saw a single line in a fragment. If it is a part of this hunk
+ * that is a context " ", an added "+", or a removed "-" line, it may
+ * be followed by "\\ No newline..." to signal that the last "\n" on
+ * this line needs to be dropped. Depending on locale settings when
+ * the patch was produced we don't know what this line would exactly
+ * say. The only thing we do know is that it begins with "\ ".
+ * Checking for 12 is just for sanity check; "\ No newline..." would
+ * be at least that long in any l10n.
+ *
+ * Return 0 if the line we saw is not followed by "\ No newline...",
+ * or length of that line. The caller will use it to skip over the
+ * "\ No newline..." line.
+ */
+static int adjust_incomplete(const char *line, int len,
+ unsigned long size)
+{
+ int nextlen;
+
+ if (*line != '\n' && *line != ' ' && *line != '+' && *line != '-')
+ return 0;
+ if (size - len < 12 || memcmp(line + len, "\\ ", 2))
+ return 0;
+ nextlen = linelen(line + len, size - len);
+ if (nextlen < 12)
+ return 0;
+ return nextlen;
+}
+
+/*
* Parse a unified diff. Note that this really needs to parse each
* fragment separately, since the only way to know the difference
* between a "---" that is part of a patch, and a "---" that starts
@@ -1684,6 +1721,7 @@ static int parse_fragment(struct apply_state *state,
{
int added, deleted;
int len = linelen(line, size), offset;
+ int skip_len = 0;
unsigned long oldlines, newlines;
unsigned long leading, trailing;
@@ -1710,6 +1748,22 @@ static int parse_fragment(struct apply_state *state,
len = linelen(line, size);
if (!len || line[len-1] != '\n')
return -1;
+
+ /*
+ * For an incomplete line, skip_len counts the bytes
+ * on "\\ No newline..." marker line that comes next
+ * to the current line.
+ *
+ * Reduce "len" to drop the newline at the end of
+ * line[], but add one to "skip_len", which will be
+ * added back to "len" for the next iteration, to
+ * compensate.
+ */
+ skip_len = adjust_incomplete(line, len, size);
+ if (skip_len) {
+ len--;
+ skip_len++;
+ }
switch (*line) {
default:
return -1;
@@ -1745,19 +1799,12 @@ static int parse_fragment(struct apply_state *state,
newlines--;
trailing = 0;
break;
+ }
- /*
- * We allow "\ No newline at end of file". Depending
- * on locale settings when the patch was produced we
- * don't know what this line looks like. The only
- * thing we do know is that it begins with "\ ".
- * Checking for 12 is just for sanity check -- any
- * l10n of "\ No newline..." is at least that long.
- */
- case '\\':
- if (len < 12 || memcmp(line, "\\ ", 2))
- return -1;
- break;
+ /* eat the "\\ No newline..." as well, if exists */
+ if (skip_len) {
+ len += skip_len;
+ state->linenr++;
}
}
if (oldlines || newlines)
@@ -1768,14 +1815,6 @@ static int parse_fragment(struct apply_state *state,
fragment->leading = leading;
fragment->trailing = trailing;
- /*
- * If a fragment ends with an incomplete line, we failed to include
- * it in the above loop because we hit oldlines == newlines == 0
- * before seeing it.
- */
- if (12 < size && !memcmp(line, "\\ ", 2))
- offset += linelen(line, size);
-
patch->lines_added += added;
patch->lines_deleted += deleted;
@@ -3204,14 +3243,14 @@ static int apply_binary(struct apply_state *state,
return 0; /* deletion patch */
}
- if (has_object(the_repository, &oid, 0)) {
+ if (odb_has_object(the_repository->objects, &oid, 0)) {
/* We already have the postimage */
enum object_type type;
unsigned long size;
char *result;
- result = repo_read_object_file(the_repository, &oid, &type,
- &size);
+ result = odb_read_object(the_repository->objects, &oid,
+ &type, &size);
if (!result)
return error(_("the necessary postimage %s for "
"'%s' cannot be read"),
@@ -3273,8 +3312,8 @@ static int read_blob_object(struct strbuf *buf, const struct object_id *oid, uns
unsigned long sz;
char *result;
- result = repo_read_object_file(the_repository, oid, &type,
- &sz);
+ result = odb_read_object(the_repository->objects, oid,
+ &type, &sz);
if (!result)
return -1;
/* XXX read_sha1_file NUL-terminates */
@@ -3503,7 +3542,7 @@ static int resolve_to(struct image *image, const struct object_id *result_id)
image_clear(image);
- data = repo_read_object_file(the_repository, result_id, &type, &size);
+ data = odb_read_object(the_repository->objects, result_id, &type, &size);
if (!data || type != OBJ_BLOB)
die("unable to read blob object %s", oid_to_hex(result_id));
strbuf_attach(&image->buf, data, size, size + 1);
@@ -3621,7 +3660,7 @@ static int try_threeway(struct apply_state *state,
/* Preimage the patch was prepared for */
if (patch->is_new)
- write_object_file("", 0, OBJ_BLOB, &pre_oid);
+ odb_write_object(the_repository->objects, "", 0, OBJ_BLOB, &pre_oid);
else if (repo_get_oid(the_repository, patch->old_oid_prefix, &pre_oid) ||
read_blob_object(&buf, &pre_oid, patch->old_mode))
return error(_("repository lacks the necessary blob to perform 3-way merge."));
@@ -3637,7 +3676,8 @@ static int try_threeway(struct apply_state *state,
return -1;
}
/* post_oid is theirs */
- write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &post_oid);
+ odb_write_object(the_repository->objects, tmp_image.buf.buf,
+ tmp_image.buf.len, OBJ_BLOB, &post_oid);
image_clear(&tmp_image);
/* our_oid is ours */
@@ -3650,7 +3690,8 @@ static int try_threeway(struct apply_state *state,
return error(_("cannot read the current contents of '%s'"),
patch->old_name);
}
- write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &our_oid);
+ odb_write_object(the_repository->objects, tmp_image.buf.buf,
+ tmp_image.buf.len, OBJ_BLOB, &our_oid);
image_clear(&tmp_image);
/* in-core three-way merge between post and our using pre as base */
@@ -4360,7 +4401,8 @@ static int add_index_file(struct apply_state *state,
}
fill_stat_cache_info(state->repo->index, ce, &st);
}
- if (write_object_file(buf, size, OBJ_BLOB, &ce->oid) < 0) {
+ if (odb_write_object(the_repository->objects, buf, size,
+ OBJ_BLOB, &ce->oid) < 0) {
discard_cache_entry(ce);
return error(_("unable to create backing store "
"for newly created file %s"), path);
@@ -4565,7 +4607,7 @@ static int create_file(struct apply_state *state, struct patch *patch)
if (patch->conflicted_threeway)
return add_conflicted_stages_file(state, patch);
- else if (state->update_index)
+ else if (state->check_index || (state->ita_only && patch->is_new > 0))
return add_index_file(state, path, mode, buf, size);
return 0;
}
@@ -4833,7 +4875,7 @@ static int apply_patch(struct apply_state *state,
LOCK_DIE_ON_ERROR);
}
- if (state->check_index && read_apply_cache(state) < 0) {
+ if ((state->check_index || state->update_index) && read_apply_cache(state) < 0) {
error(_("unable to read index file"));
res = -128;
goto end;