Skip to content

Commit 280bd44

Browse files
committed
Merge branch 'en/merge-recursive-cleanup'
The merge-recursive machiery is one of the most complex parts of the system that accumulated cruft over time. This large series cleans up the implementation quite a bit. * en/merge-recursive-cleanup: (26 commits) merge-recursive: fix the fix to the diff3 common ancestor label merge-recursive: fix the diff3 common ancestor label for virtual commits merge-recursive: alphabetize include list merge-recursive: add sanity checks for relevant merge_options merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* merge-recursive: split internal fields into a separate struct merge-recursive: avoid losing output and leaking memory holding that output merge-recursive: comment and reorder the merge_options fields merge-recursive: consolidate unnecessary fields in merge_options merge-recursive: move some definitions around to clean up the header merge-recursive: rename merge_options argument to opt in header merge-recursive: rename 'mrtree' to 'result_tree', for clarity merge-recursive: use common name for ancestors/common/base_list merge-recursive: fix some overly long lines cache-tree: share code between functions writing an index as a tree merge-recursive: don't force external callers to do our logging merge-recursive: remove useless parameter in merge_trees() merge-recursive: exit early if index != head Ensure index matches head before invoking merge machinery, round N merge-recursive: remove another implicit dependency on the_repository ...
2 parents 08da649 + b657047 commit 280bd44

12 files changed

+736
-334
lines changed

builtin/am.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
15261526
o.branch1 = "HEAD";
15271527
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
15281528
o.branch2 = their_tree_name;
1529-
o.detect_directory_renames = 0;
1529+
o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE;
15301530

15311531
if (state->quiet)
15321532
o.verbosity = 0;

builtin/checkout.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -709,11 +709,11 @@ static int merge_working_tree(const struct checkout_opts *opts,
709709
* give up or do a real merge, depending on
710710
* whether the merge flag was used.
711711
*/
712-
struct tree *result;
713712
struct tree *work;
714713
struct tree *old_tree;
715714
struct merge_options o;
716715
struct strbuf sb = STRBUF_INIT;
716+
struct strbuf old_commit_shortname = STRBUF_INIT;
717717

718718
if (!opts->merge)
719719
return 1;
@@ -754,27 +754,33 @@ static int merge_working_tree(const struct checkout_opts *opts,
754754
*/
755755
init_merge_options(&o, the_repository);
756756
o.verbosity = 0;
757-
work = write_tree_from_memory(&o);
757+
work = write_in_core_index_as_tree(the_repository);
758758

759759
ret = reset_tree(new_tree,
760760
opts, 1,
761761
writeout_error);
762762
if (ret)
763763
return ret;
764764
o.ancestor = old_branch_info->name;
765+
if (old_branch_info->name == NULL) {
766+
strbuf_add_unique_abbrev(&old_commit_shortname,
767+
&old_branch_info->commit->object.oid,
768+
DEFAULT_ABBREV);
769+
o.ancestor = old_commit_shortname.buf;
770+
}
765771
o.branch1 = new_branch_info->name;
766772
o.branch2 = "local";
767773
ret = merge_trees(&o,
768774
new_tree,
769775
work,
770-
old_tree,
771-
&result);
776+
old_tree);
772777
if (ret < 0)
773778
exit(128);
774779
ret = reset_tree(new_tree,
775780
opts, 0,
776781
writeout_error);
777782
strbuf_release(&o.obuf);
783+
strbuf_release(&old_commit_shortname);
778784
if (ret)
779785
return ret;
780786
}

builtin/merge-recursive.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "cache.h"
12
#include "builtin.h"
23
#include "commit.h"
34
#include "tag.h"
@@ -63,6 +64,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
6364
if (argc - i != 3) /* "--" "<head>" "<remote>" */
6465
die(_("not handling anything other than two heads merge."));
6566

67+
if (repo_read_index_unmerged(the_repository))
68+
die_resolve_conflict("merge");
69+
6670
o.branch1 = argv[++i];
6771
o.branch2 = argv[++i];
6872

builtin/stash.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
427427
return error(_("could not save index tree"));
428428

429429
reset_head();
430+
discard_cache();
431+
read_cache();
430432
}
431433
}
432434

cache-tree.c

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -609,11 +609,66 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat
609609
return it;
610610
}
611611

612+
static int write_index_as_tree_internal(struct object_id *oid,
613+
struct index_state *index_state,
614+
int cache_tree_valid,
615+
int flags,
616+
const char *prefix)
617+
{
618+
if (flags & WRITE_TREE_IGNORE_CACHE_TREE) {
619+
cache_tree_free(&index_state->cache_tree);
620+
cache_tree_valid = 0;
621+
}
622+
623+
if (!index_state->cache_tree)
624+
index_state->cache_tree = cache_tree();
625+
626+
if (!cache_tree_valid && cache_tree_update(index_state, flags) < 0)
627+
return WRITE_TREE_UNMERGED_INDEX;
628+
629+
if (prefix) {
630+
struct cache_tree *subtree;
631+
subtree = cache_tree_find(index_state->cache_tree, prefix);
632+
if (!subtree)
633+
return WRITE_TREE_PREFIX_ERROR;
634+
oidcpy(oid, &subtree->oid);
635+
}
636+
else
637+
oidcpy(oid, &index_state->cache_tree->oid);
638+
639+
return 0;
640+
}
641+
642+
struct tree* write_in_core_index_as_tree(struct repository *repo) {
643+
struct object_id o;
644+
int was_valid, ret;
645+
646+
struct index_state *index_state = repo->index;
647+
was_valid = index_state->cache_tree &&
648+
cache_tree_fully_valid(index_state->cache_tree);
649+
650+
ret = write_index_as_tree_internal(&o, index_state, was_valid, 0, NULL);
651+
if (ret == WRITE_TREE_UNMERGED_INDEX) {
652+
int i;
653+
fprintf(stderr, "BUG: There are unmerged index entries:\n");
654+
for (i = 0; i < index_state->cache_nr; i++) {
655+
const struct cache_entry *ce = index_state->cache[i];
656+
if (ce_stage(ce))
657+
fprintf(stderr, "BUG: %d %.*s\n", ce_stage(ce),
658+
(int)ce_namelen(ce), ce->name);
659+
}
660+
BUG("unmerged index entries when writing inmemory index");
661+
}
662+
663+
return lookup_tree(repo, &index_state->cache_tree->oid);
664+
}
665+
666+
612667
int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
613668
{
614669
int entries, was_valid;
615670
struct lock_file lock_file = LOCK_INIT;
616-
int ret = 0;
671+
int ret;
617672

618673
hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);
619674

@@ -622,18 +677,14 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
622677
ret = WRITE_TREE_UNREADABLE_INDEX;
623678
goto out;
624679
}
625-
if (flags & WRITE_TREE_IGNORE_CACHE_TREE)
626-
cache_tree_free(&index_state->cache_tree);
627680

628-
if (!index_state->cache_tree)
629-
index_state->cache_tree = cache_tree();
681+
was_valid = !(flags & WRITE_TREE_IGNORE_CACHE_TREE) &&
682+
index_state->cache_tree &&
683+
cache_tree_fully_valid(index_state->cache_tree);
630684

631-
was_valid = cache_tree_fully_valid(index_state->cache_tree);
632-
if (!was_valid) {
633-
if (cache_tree_update(index_state, flags) < 0) {
634-
ret = WRITE_TREE_UNMERGED_INDEX;
635-
goto out;
636-
}
685+
ret = write_index_as_tree_internal(oid, index_state, was_valid, flags,
686+
prefix);
687+
if (!ret && !was_valid) {
637688
write_locked_index(index_state, &lock_file, COMMIT_LOCK);
638689
/* Not being able to write is fine -- we are only interested
639690
* in updating the cache-tree part, and if the next caller
@@ -643,18 +694,6 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
643694
*/
644695
}
645696

646-
if (prefix) {
647-
struct cache_tree *subtree;
648-
subtree = cache_tree_find(index_state->cache_tree, prefix);
649-
if (!subtree) {
650-
ret = WRITE_TREE_PREFIX_ERROR;
651-
goto out;
652-
}
653-
oidcpy(oid, &subtree->oid);
654-
}
655-
else
656-
oidcpy(oid, &index_state->cache_tree->oid);
657-
658697
out:
659698
rollback_lock_file(&lock_file);
660699
return ret;

cache-tree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ int cache_tree_fully_valid(struct cache_tree *);
3434
int cache_tree_update(struct index_state *, int);
3535
void cache_tree_verify(struct repository *, struct index_state *);
3636

37-
/* bitmasks to write_cache_as_tree flags */
37+
/* bitmasks to write_index_as_tree flags */
3838
#define WRITE_TREE_MISSING_OK 1
3939
#define WRITE_TREE_IGNORE_CACHE_TREE 2
4040
#define WRITE_TREE_DRY_RUN 4
@@ -46,6 +46,7 @@ void cache_tree_verify(struct repository *, struct index_state *);
4646
#define WRITE_TREE_UNMERGED_INDEX (-2)
4747
#define WRITE_TREE_PREFIX_ERROR (-3)
4848

49+
struct tree* write_in_core_index_as_tree(struct repository *repo);
4950
int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
5051
void prime_cache_tree(struct repository *, struct index_state *, struct tree *);
5152

0 commit comments

Comments
 (0)