Skip to content

Commit

Permalink
Merge branch 'en/merge-recursive-cleanup'
Browse files Browse the repository at this point in the history
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
  ...
  • Loading branch information
gitster committed Oct 15, 2019
2 parents 08da649 + b657047 commit 280bd44
Show file tree
Hide file tree
Showing 12 changed files with 736 additions and 334 deletions.
2 changes: 1 addition & 1 deletion builtin/am.c
Original file line number Diff line number Diff line change
Expand Up @@ -1526,7 +1526,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
o.branch1 = "HEAD";
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
o.branch2 = their_tree_name;
o.detect_directory_renames = 0;
o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE;

if (state->quiet)
o.verbosity = 0;
Expand Down
14 changes: 10 additions & 4 deletions builtin/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,11 +709,11 @@ static int merge_working_tree(const struct checkout_opts *opts,
* give up or do a real merge, depending on
* whether the merge flag was used.
*/
struct tree *result;
struct tree *work;
struct tree *old_tree;
struct merge_options o;
struct strbuf sb = STRBUF_INIT;
struct strbuf old_commit_shortname = STRBUF_INIT;

if (!opts->merge)
return 1;
Expand Down Expand Up @@ -754,27 +754,33 @@ static int merge_working_tree(const struct checkout_opts *opts,
*/
init_merge_options(&o, the_repository);
o.verbosity = 0;
work = write_tree_from_memory(&o);
work = write_in_core_index_as_tree(the_repository);

ret = reset_tree(new_tree,
opts, 1,
writeout_error);
if (ret)
return ret;
o.ancestor = old_branch_info->name;
if (old_branch_info->name == NULL) {
strbuf_add_unique_abbrev(&old_commit_shortname,
&old_branch_info->commit->object.oid,
DEFAULT_ABBREV);
o.ancestor = old_commit_shortname.buf;
}
o.branch1 = new_branch_info->name;
o.branch2 = "local";
ret = merge_trees(&o,
new_tree,
work,
old_tree,
&result);
old_tree);
if (ret < 0)
exit(128);
ret = reset_tree(new_tree,
opts, 0,
writeout_error);
strbuf_release(&o.obuf);
strbuf_release(&old_commit_shortname);
if (ret)
return ret;
}
Expand Down
4 changes: 4 additions & 0 deletions builtin/merge-recursive.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "cache.h"
#include "builtin.h"
#include "commit.h"
#include "tag.h"
Expand Down Expand Up @@ -63,6 +64,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
if (argc - i != 3) /* "--" "<head>" "<remote>" */
die(_("not handling anything other than two heads merge."));

if (repo_read_index_unmerged(the_repository))
die_resolve_conflict("merge");

o.branch1 = argv[++i];
o.branch2 = argv[++i];

Expand Down
2 changes: 2 additions & 0 deletions builtin/stash.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
return error(_("could not save index tree"));

reset_head();
discard_cache();
read_cache();
}
}

Expand Down
85 changes: 62 additions & 23 deletions cache-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,11 +609,66 @@ static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *pat
return it;
}

static int write_index_as_tree_internal(struct object_id *oid,
struct index_state *index_state,
int cache_tree_valid,
int flags,
const char *prefix)
{
if (flags & WRITE_TREE_IGNORE_CACHE_TREE) {
cache_tree_free(&index_state->cache_tree);
cache_tree_valid = 0;
}

if (!index_state->cache_tree)
index_state->cache_tree = cache_tree();

if (!cache_tree_valid && cache_tree_update(index_state, flags) < 0)
return WRITE_TREE_UNMERGED_INDEX;

if (prefix) {
struct cache_tree *subtree;
subtree = cache_tree_find(index_state->cache_tree, prefix);
if (!subtree)
return WRITE_TREE_PREFIX_ERROR;
oidcpy(oid, &subtree->oid);
}
else
oidcpy(oid, &index_state->cache_tree->oid);

return 0;
}

struct tree* write_in_core_index_as_tree(struct repository *repo) {
struct object_id o;
int was_valid, ret;

struct index_state *index_state = repo->index;
was_valid = index_state->cache_tree &&
cache_tree_fully_valid(index_state->cache_tree);

ret = write_index_as_tree_internal(&o, index_state, was_valid, 0, NULL);
if (ret == WRITE_TREE_UNMERGED_INDEX) {
int i;
fprintf(stderr, "BUG: There are unmerged index entries:\n");
for (i = 0; i < index_state->cache_nr; i++) {
const struct cache_entry *ce = index_state->cache[i];
if (ce_stage(ce))
fprintf(stderr, "BUG: %d %.*s\n", ce_stage(ce),
(int)ce_namelen(ce), ce->name);
}
BUG("unmerged index entries when writing inmemory index");
}

return lookup_tree(repo, &index_state->cache_tree->oid);
}


int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix)
{
int entries, was_valid;
struct lock_file lock_file = LOCK_INIT;
int ret = 0;
int ret;

hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);

Expand All @@ -622,18 +677,14 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
ret = WRITE_TREE_UNREADABLE_INDEX;
goto out;
}
if (flags & WRITE_TREE_IGNORE_CACHE_TREE)
cache_tree_free(&index_state->cache_tree);

if (!index_state->cache_tree)
index_state->cache_tree = cache_tree();
was_valid = !(flags & WRITE_TREE_IGNORE_CACHE_TREE) &&
index_state->cache_tree &&
cache_tree_fully_valid(index_state->cache_tree);

was_valid = cache_tree_fully_valid(index_state->cache_tree);
if (!was_valid) {
if (cache_tree_update(index_state, flags) < 0) {
ret = WRITE_TREE_UNMERGED_INDEX;
goto out;
}
ret = write_index_as_tree_internal(oid, index_state, was_valid, flags,
prefix);
if (!ret && !was_valid) {
write_locked_index(index_state, &lock_file, COMMIT_LOCK);
/* Not being able to write is fine -- we are only interested
* in updating the cache-tree part, and if the next caller
Expand All @@ -643,18 +694,6 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
*/
}

if (prefix) {
struct cache_tree *subtree;
subtree = cache_tree_find(index_state->cache_tree, prefix);
if (!subtree) {
ret = WRITE_TREE_PREFIX_ERROR;
goto out;
}
oidcpy(oid, &subtree->oid);
}
else
oidcpy(oid, &index_state->cache_tree->oid);

out:
rollback_lock_file(&lock_file);
return ret;
Expand Down
3 changes: 2 additions & 1 deletion cache-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int cache_tree_fully_valid(struct cache_tree *);
int cache_tree_update(struct index_state *, int);
void cache_tree_verify(struct repository *, struct index_state *);

/* bitmasks to write_cache_as_tree flags */
/* bitmasks to write_index_as_tree flags */
#define WRITE_TREE_MISSING_OK 1
#define WRITE_TREE_IGNORE_CACHE_TREE 2
#define WRITE_TREE_DRY_RUN 4
Expand All @@ -46,6 +46,7 @@ void cache_tree_verify(struct repository *, struct index_state *);
#define WRITE_TREE_UNMERGED_INDEX (-2)
#define WRITE_TREE_PREFIX_ERROR (-3)

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

Expand Down
Loading

0 comments on commit 280bd44

Please sign in to comment.