diff options
Diffstat (limited to 'apply.c')
-rw-r--r-- | apply.c | 98 |
1 files changed, 62 insertions, 36 deletions
@@ -223,8 +223,8 @@ struct patch { struct fragment *fragments; char *result; size_t resultsize; - char old_sha1_prefix[41]; - char new_sha1_prefix[41]; + char old_oid_prefix[GIT_MAX_HEXSZ + 1]; + char new_oid_prefix[GIT_MAX_HEXSZ + 1]; struct patch *next; /* three-way fallback result */ @@ -1093,13 +1093,14 @@ static int gitdiff_index(struct apply_state *state, */ const char *ptr, *eol; int len; + const unsigned hexsz = the_hash_algo->hexsz; ptr = strchr(line, '.'); - if (!ptr || ptr[1] != '.' || 40 < ptr - line) + if (!ptr || ptr[1] != '.' || hexsz < ptr - line) return 0; len = ptr - line; - memcpy(patch->old_sha1_prefix, line, len); - patch->old_sha1_prefix[len] = 0; + memcpy(patch->old_oid_prefix, line, len); + patch->old_oid_prefix[len] = 0; line = ptr + 2; ptr = strchr(line, ' '); @@ -1109,10 +1110,10 @@ static int gitdiff_index(struct apply_state *state, ptr = eol; len = ptr - line; - if (40 < len) + if (hexsz < len) return 0; - memcpy(patch->new_sha1_prefix, line, len); - patch->new_sha1_prefix[len] = 0; + memcpy(patch->new_oid_prefix, line, len); + patch->new_oid_prefix[len] = 0; if (*ptr == ' ') return gitdiff_oldmode(state, ptr + 1, patch); return 0; @@ -1747,7 +1748,7 @@ static int parse_fragment(struct apply_state *state, } if (oldlines || newlines) return -1; - if (!deleted && !added) + if (!patch->recount && !deleted && !added) return -1; fragment->leading = leading; @@ -2131,10 +2132,12 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si if (!use_patch(state, patch)) patch->ws_rule = 0; + else if (patch->new_name) + patch->ws_rule = whitespace_rule(state->repo->index, + patch->new_name); else - patch->ws_rule = whitespace_rule(patch->new_name - ? patch->new_name - : patch->old_name); + patch->ws_rule = whitespace_rule(state->repo->index, + patch->old_name); patchsize = parse_single_patch(state, buffer + offset + hdrsize, @@ -2204,7 +2207,7 @@ static void reverse_patches(struct patch *p) SWAP(p->new_mode, p->old_mode); SWAP(p->is_new, p->is_delete); SWAP(p->lines_added, p->lines_deleted); - SWAP(p->old_sha1_prefix, p->new_sha1_prefix); + SWAP(p->old_oid_prefix, p->new_oid_prefix); for (; frag; frag = frag->next) { SWAP(frag->newpos, frag->oldpos); @@ -3142,15 +3145,16 @@ static int apply_binary(struct apply_state *state, { const char *name = patch->old_name ? patch->old_name : patch->new_name; struct object_id oid; + const unsigned hexsz = the_hash_algo->hexsz; /* * For safety, we require patch index line to contain - * full 40-byte textual SHA1 for old and new, at least for now. + * full hex textual object ID for old and new, at least for now. */ - if (strlen(patch->old_sha1_prefix) != 40 || - strlen(patch->new_sha1_prefix) != 40 || - get_oid_hex(patch->old_sha1_prefix, &oid) || - get_oid_hex(patch->new_sha1_prefix, &oid)) + if (strlen(patch->old_oid_prefix) != hexsz || + strlen(patch->new_oid_prefix) != hexsz || + get_oid_hex(patch->old_oid_prefix, &oid) || + get_oid_hex(patch->new_oid_prefix, &oid)) return error(_("cannot apply binary patch to '%s' " "without full index line"), name); @@ -3160,7 +3164,7 @@ static int apply_binary(struct apply_state *state, * applies to. */ hash_object_file(img->buf, img->len, blob_type, &oid); - if (strcmp(oid_to_hex(&oid), patch->old_sha1_prefix)) + if (strcmp(oid_to_hex(&oid), patch->old_oid_prefix)) return error(_("the patch applies to '%s' (%s), " "which does not match the " "current contents."), @@ -3173,7 +3177,7 @@ static int apply_binary(struct apply_state *state, "'%s' but it is not empty"), name); } - get_oid_hex(patch->new_sha1_prefix, &oid); + get_oid_hex(patch->new_oid_prefix, &oid); if (is_null_oid(&oid)) { clear_image(img); return 0; /* deletion patch */ @@ -3189,7 +3193,7 @@ static int apply_binary(struct apply_state *state, if (!result) return error(_("the necessary postimage %s for " "'%s' cannot be read"), - patch->new_sha1_prefix, name); + patch->new_oid_prefix, name); clear_image(img); img->buf = result; img->len = size; @@ -3205,9 +3209,9 @@ static int apply_binary(struct apply_state *state, /* verify that the result matches */ hash_object_file(img->buf, img->len, blob_type, &oid); - if (strcmp(oid_to_hex(&oid), patch->new_sha1_prefix)) + if (strcmp(oid_to_hex(&oid), patch->new_oid_prefix)) return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"), - name, patch->new_sha1_prefix, oid_to_hex(&oid)); + name, patch->new_oid_prefix, oid_to_hex(&oid)); } return 0; @@ -3348,7 +3352,8 @@ static int checkout_target(struct index_state *istate, costate.refresh_cache = 1; costate.istate = istate; - if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st)) + if (checkout_entry(ce, &costate, NULL, NULL) || + lstat(ce->name, st)) return error(_("cannot checkout %s"), ce->name); return 0; } @@ -3467,7 +3472,8 @@ static int load_preimage(struct apply_state *state, return 0; } -static int three_way_merge(struct image *image, +static int three_way_merge(struct apply_state *state, + struct image *image, char *path, const struct object_id *base, const struct object_id *ours, @@ -3483,7 +3489,9 @@ static int three_way_merge(struct image *image, status = ll_merge(&result, path, &base_file, "base", &our_file, "ours", - &their_file, "theirs", NULL); + &their_file, "theirs", + state->repo->index, + NULL); free(base_file.ptr); free(our_file.ptr); free(their_file.ptr); @@ -3563,7 +3571,7 @@ static int try_threeway(struct apply_state *state, /* Preimage the patch was prepared for */ if (patch->is_new) write_object_file("", 0, blob_type, &pre_oid); - else if (get_oid(patch->old_sha1_prefix, &pre_oid) || + else if (get_oid(patch->old_oid_prefix, &pre_oid) || read_blob_object(&buf, &pre_oid, patch->old_mode)) return error(_("repository lacks the necessary blob to fall back on 3-way merge.")); @@ -3595,7 +3603,7 @@ static int try_threeway(struct apply_state *state, clear_image(&tmp_image); /* in-core three-way merge between post and our using pre as base */ - status = three_way_merge(image, patch->new_name, + status = three_way_merge(state, image, patch->new_name, &pre_oid, &our_oid, &post_oid); if (status < 0) { if (state->apply_verbosity > verbosity_silent) @@ -4055,13 +4063,13 @@ static int preimage_oid_in_gitlink_patch(struct patch *p, struct object_id *oid) starts_with(++preimage, heading) && /* does it record full SHA-1? */ !get_oid_hex(preimage + sizeof(heading) - 1, oid) && - preimage[sizeof(heading) + GIT_SHA1_HEXSZ - 1] == '\n' && + preimage[sizeof(heading) + the_hash_algo->hexsz - 1] == '\n' && /* does the abbreviated name on the index line agree with it? */ - starts_with(preimage + sizeof(heading) - 1, p->old_sha1_prefix)) + starts_with(preimage + sizeof(heading) - 1, p->old_oid_prefix)) return 0; /* it all looks fine */ /* we may have full object name on the index line */ - return get_oid_hex(p->old_sha1_prefix, oid); + return get_oid_hex(p->old_oid_prefix, oid); } /* Build an index that contains just the files needed for a 3way merge */ @@ -4090,7 +4098,7 @@ static int build_fake_ancestor(struct apply_state *state, struct patch *list) else return error(_("sha1 information is lacking or " "useless for submodule %s"), name); - } else if (!get_oid_blob(patch->old_sha1_prefix, &oid)) { + } else if (!get_oid_blob(patch->old_oid_prefix, &oid)) { ; /* ok */ } else if (!patch->lines_added && !patch->lines_deleted) { /* mode-only change: update the current */ @@ -4627,7 +4635,7 @@ static int write_out_results(struct apply_state *state, struct patch *list) } string_list_clear(&cpath, 0); - rerere(0); + repo_rerere(state->repo, 0); } return errs; @@ -4765,6 +4773,9 @@ static int apply_option_parse_exclude(const struct option *opt, const char *arg, int unset) { struct apply_state *state = opt->value; + + BUG_ON_OPT_NEG(unset); + add_name_limit(state, arg, 1); return 0; } @@ -4773,6 +4784,9 @@ static int apply_option_parse_include(const struct option *opt, const char *arg, int unset) { struct apply_state *state = opt->value; + + BUG_ON_OPT_NEG(unset); + add_name_limit(state, arg, 0); state->has_include = 1; return 0; @@ -4783,6 +4797,9 @@ static int apply_option_parse_p(const struct option *opt, int unset) { struct apply_state *state = opt->value; + + BUG_ON_OPT_NEG(unset); + state->p_value = atoi(arg); state->p_value_known = 1; return 0; @@ -4792,6 +4809,9 @@ static int apply_option_parse_space_change(const struct option *opt, const char *arg, int unset) { struct apply_state *state = opt->value; + + BUG_ON_OPT_ARG(arg); + if (unset) state->ws_ignore_action = ignore_ws_none; else @@ -4803,9 +4823,12 @@ static int apply_option_parse_whitespace(const struct option *opt, const char *arg, int unset) { struct apply_state *state = opt->value; + + BUG_ON_OPT_NEG(unset); + state->whitespace_option = arg; if (parse_whitespace_option(state, arg)) - exit(1); + return -1; return 0; } @@ -4813,6 +4836,9 @@ static int apply_option_parse_directory(const struct option *opt, const char *arg, int unset) { struct apply_state *state = opt->value; + + BUG_ON_OPT_NEG(unset); + strbuf_reset(&state->root); strbuf_addstr(&state->root, arg); strbuf_complete(&state->root, '/'); @@ -4932,10 +4958,10 @@ int apply_parse_options(int argc, const char **argv, struct option builtin_apply_options[] = { { OPTION_CALLBACK, 0, "exclude", state, N_("path"), N_("don't apply changes matching the given path"), - 0, apply_option_parse_exclude }, + PARSE_OPT_NONEG, apply_option_parse_exclude }, { OPTION_CALLBACK, 0, "include", state, N_("path"), N_("apply changes matching the given path"), - 0, apply_option_parse_include }, + PARSE_OPT_NONEG, apply_option_parse_include }, { OPTION_CALLBACK, 'p', NULL, state, N_("num"), N_("remove <num> leading slashes from traditional diff paths"), 0, apply_option_parse_p }, |