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:
Junio C Hamano 2008-06-01 22:55:33 -07:00
commit 8f1b0637c1
2 changed files with 50 additions and 49 deletions

View File

@ -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)

View File

@ -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 */