diff options
author | Junio C Hamano <gitster@pobox.com> | 2012-05-09 16:50:58 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2012-07-09 14:40:03 -0700 |
commit | 4f4a6cb9882516d75f345772c9bf00b891753f10 (patch) | |
tree | a57560f41782f788828fac856d32cd343d36d2ce /builtin/apply.c | |
parent | 099f3c421a446e2eef3a1bb6aea0e451711ddd88 (diff) | |
download | git-4f4a6cb9882516d75f345772c9bf00b891753f10.tar.gz git-4f4a6cb9882516d75f345772c9bf00b891753f10.tar.xz |
apply: register conflicted stages to the index
Now we have all the necessary logic to fall back on three-way merge when
the patch does not cleanly apply, insert the conflicted entries to the
index as appropriate. This obviously triggers only when the "--index"
option is used.
When we fall back to three-way merge and some of the merges fail, just
like the case where the "--reject" option was specified and we had to
write some "*.rej" files out for unapplicable patches, exit the command
with non-zero status without showing the diffstat and summary. Otherwise
they would make the list of problematic paths scroll off the display.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/apply.c')
-rw-r--r-- | builtin/apply.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/builtin/apply.c b/builtin/apply.c index 24efb3f43..dc52c9475 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -3288,7 +3288,10 @@ static int try_threeway(struct image *image, struct patch *patch, if (status) { patch->conflicted_threeway = 1; - hashcpy(patch->threeway_stage[0], pre_sha1); + if (patch->is_new) + hashclr(patch->threeway_stage[0]); + else + hashcpy(patch->threeway_stage[0], pre_sha1); hashcpy(patch->threeway_stage[1], our_sha1); hashcpy(patch->threeway_stage[2], post_sha1); fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name); @@ -3852,6 +3855,32 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned die_errno(_("unable to write file '%s' mode %o"), path, mode); } +static void add_conflicted_stages_file(struct patch *patch) +{ + int stage, namelen; + unsigned ce_size, mode; + struct cache_entry *ce; + + if (!update_index) + return; + namelen = strlen(patch->new_name); + ce_size = cache_entry_size(namelen); + mode = patch->new_mode ? patch->new_mode : (S_IFREG | 0644); + + remove_file_from_cache(patch->new_name); + for (stage = 1; stage < 4; stage++) { + if (is_null_sha1(patch->threeway_stage[stage - 1])) + continue; + ce = xcalloc(1, ce_size); + memcpy(ce->name, patch->new_name, namelen); + ce->ce_mode = create_ce_mode(mode); + ce->ce_flags = create_ce_flags(namelen, stage); + hashcpy(ce->sha1, patch->threeway_stage[stage - 1]); + if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) + die(_("unable to add cache entry for %s"), patch->new_name); + } +} + static void create_file(struct patch *patch) { char *path = patch->new_name; @@ -3862,7 +3891,11 @@ static void create_file(struct patch *patch) if (!mode) mode = S_IFREG | 0644; create_one_file(path, mode, buf, size); - add_index_file(path, mode, buf, size); + + if (patch->conflicted_threeway) + add_conflicted_stages_file(patch); + else + add_index_file(path, mode, buf, size); } /* phase zero is to remove, phase one is to create */ @@ -3964,6 +3997,7 @@ static int write_out_results(struct patch *list) int phase; int errs = 0; struct patch *l; + struct string_list cpath = STRING_LIST_INIT_DUP; for (phase = 0; phase < 2; phase++) { l = list; @@ -3972,12 +4006,28 @@ static int write_out_results(struct patch *list) errs = 1; else { write_out_one_result(l, phase); - if (phase == 1 && write_out_one_reject(l)) - errs = 1; + if (phase == 1) { + if (write_out_one_reject(l)) + errs = 1; + if (l->conflicted_threeway) { + string_list_append(&cpath, l->new_name); + errs = 1; + } + } } l = l->next; } } + + if (cpath.nr) { + struct string_list_item *item; + + sort_string_list(&cpath); + for_each_string_list_item(item, &cpath) + fprintf(stderr, "U %s\n", item->string); + string_list_clear(&cpath, 0); + } + return errs; } @@ -4100,8 +4150,12 @@ static int apply_patch(int fd, const char *filename, int options) !apply_with_reject) exit(1); - if (apply && write_out_results(list)) - exit(1); + if (apply && write_out_results(list)) { + if (apply_with_reject) + exit(1); + /* with --3way, we still need to write the index out */ + return 1; + } if (fake_ancestor) build_fake_ancestor(list, fake_ancestor); |