Merge branch 'jc/checkout'
* 'jc/checkout': checkout: "best effort" checkout unpack_trees(): allow callers to differentiate worktree errors from merge errors checkout: consolidate reset_{to_new,clean_to_new}() checkout: make reset_clean_to_new() not die by itself
This commit is contained in:
commit
8f1b0637c1
@ -151,57 +151,50 @@ static void describe_detached_head(char *msg, struct commit *commit)
|
||||
strbuf_release(&sb);
|
||||
}
|
||||
|
||||
static int reset_to_new(struct tree *tree, int quiet)
|
||||
{
|
||||
struct unpack_trees_options opts;
|
||||
struct tree_desc tree_desc;
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.head_idx = -1;
|
||||
opts.update = 1;
|
||||
opts.reset = 1;
|
||||
opts.merge = 1;
|
||||
opts.fn = oneway_merge;
|
||||
opts.verbose_update = !quiet;
|
||||
opts.src_index = &the_index;
|
||||
opts.dst_index = &the_index;
|
||||
parse_tree(tree);
|
||||
init_tree_desc(&tree_desc, tree->buffer, tree->size);
|
||||
if (unpack_trees(1, &tree_desc, &opts))
|
||||
return 128;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reset_clean_to_new(struct tree *tree, int quiet)
|
||||
{
|
||||
struct unpack_trees_options opts;
|
||||
struct tree_desc tree_desc;
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.head_idx = -1;
|
||||
opts.skip_unmerged = 1;
|
||||
opts.reset = 1;
|
||||
opts.merge = 1;
|
||||
opts.fn = oneway_merge;
|
||||
opts.verbose_update = !quiet;
|
||||
opts.src_index = &the_index;
|
||||
opts.dst_index = &the_index;
|
||||
parse_tree(tree);
|
||||
init_tree_desc(&tree_desc, tree->buffer, tree->size);
|
||||
if (unpack_trees(1, &tree_desc, &opts))
|
||||
exit(128);
|
||||
}
|
||||
|
||||
struct checkout_opts {
|
||||
int quiet;
|
||||
int merge;
|
||||
int force;
|
||||
int writeout_error;
|
||||
|
||||
char *new_branch;
|
||||
int new_branch_log;
|
||||
enum branch_track track;
|
||||
};
|
||||
|
||||
static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
|
||||
{
|
||||
struct unpack_trees_options opts;
|
||||
struct tree_desc tree_desc;
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.head_idx = -1;
|
||||
opts.update = worktree;
|
||||
opts.skip_unmerged = !worktree;
|
||||
opts.reset = 1;
|
||||
opts.merge = 1;
|
||||
opts.fn = oneway_merge;
|
||||
opts.verbose_update = !o->quiet;
|
||||
opts.src_index = &the_index;
|
||||
opts.dst_index = &the_index;
|
||||
parse_tree(tree);
|
||||
init_tree_desc(&tree_desc, tree->buffer, tree->size);
|
||||
switch (unpack_trees(1, &tree_desc, &opts)) {
|
||||
case -2:
|
||||
o->writeout_error = 1;
|
||||
/*
|
||||
* We return 0 nevertheless, as the index is all right
|
||||
* and more importantly we have made best efforts to
|
||||
* update paths in the work tree, and we cannot revert
|
||||
* them.
|
||||
*/
|
||||
case 0:
|
||||
return 0;
|
||||
default:
|
||||
return 128;
|
||||
}
|
||||
}
|
||||
|
||||
struct branch_info {
|
||||
const char *name; /* The short name used */
|
||||
const char *path; /* The full name of a real branch */
|
||||
@ -226,7 +219,7 @@ static int merge_working_tree(struct checkout_opts *opts,
|
||||
read_cache();
|
||||
|
||||
if (opts->force) {
|
||||
ret = reset_to_new(new->commit->tree, opts->quiet);
|
||||
ret = reset_tree(new->commit->tree, opts, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
@ -262,7 +255,8 @@ static int merge_working_tree(struct checkout_opts *opts,
|
||||
tree = parse_tree_indirect(new->commit->object.sha1);
|
||||
init_tree_desc(&trees[1], tree->buffer, tree->size);
|
||||
|
||||
if (unpack_trees(2, trees, &topts)) {
|
||||
ret = unpack_trees(2, trees, &topts);
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* Unpack couldn't do a trivial merge; either
|
||||
* give up or do a real merge, depending on
|
||||
@ -290,12 +284,14 @@ static int merge_working_tree(struct checkout_opts *opts,
|
||||
add_files_to_cache(NULL, NULL, 0);
|
||||
work = write_tree_from_memory();
|
||||
|
||||
ret = reset_to_new(new->commit->tree, opts->quiet);
|
||||
ret = reset_tree(new->commit->tree, opts, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
merge_trees(new->commit->tree, work, old->commit->tree,
|
||||
new->name, "local", &result);
|
||||
reset_clean_to_new(new->commit->tree, opts->quiet);
|
||||
ret = reset_tree(new->commit->tree, opts, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,7 +491,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
|
||||
|
||||
update_refs_for_switch(opts, &old, new);
|
||||
|
||||
return post_checkout_hook(old.commit, new->commit, 1);
|
||||
ret = post_checkout_hook(old.commit, new->commit, 1);
|
||||
return ret || opts->writeout_error;
|
||||
}
|
||||
|
||||
int cmd_checkout(int argc, const char **argv, const char *prefix)
|
||||
|
@ -358,8 +358,13 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* N-way merge "len" trees. Returns 0 on success, -1 on failure to manipulate the
|
||||
* resulting index, -2 on failure to reflect the changes to the work tree.
|
||||
*/
|
||||
int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o)
|
||||
{
|
||||
int ret;
|
||||
static struct cache_entry *dfc;
|
||||
|
||||
if (len > MAX_UNPACK_TREES)
|
||||
@ -404,11 +409,10 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
|
||||
return unpack_failed(o, "Merge requires file-level merging");
|
||||
|
||||
o->src_index = NULL;
|
||||
if (check_updates(o))
|
||||
return -1;
|
||||
ret = check_updates(o) ? (-2) : 0;
|
||||
if (o->dst_index)
|
||||
*o->dst_index = o->result;
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Here come the merge functions */
|
||||
|
Loading…
Reference in New Issue
Block a user