diff --git a/builtin-checkout.c b/builtin-checkout.c
index 00dc8cafd827aaffeb9f9e1b8cc7addb7fffaa8d..93ea69bfaa083f49a6e808c7317ea1910b29c847 100644 (file)
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
strbuf_release(&sb);
}
-static int reset_to_new(struct tree *tree, int quiet)
-{
- struct unpack_trees_options opts;
- struct tree_desc tree_desc;
+struct checkout_opts {
+ int quiet;
+ int merge;
+ int force;
+ int writeout_error;
- 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;
-}
+ char *new_branch;
+ int new_branch_log;
+ enum branch_track track;
+};
-static void reset_clean_to_new(struct tree *tree, int quiet)
+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.skip_unmerged = 1;
+ opts.update = worktree;
+ opts.skip_unmerged = !worktree;
opts.reset = 1;
opts.merge = 1;
opts.fn = oneway_merge;
- opts.verbose_update = !quiet;
+ 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);
- if (unpack_trees(1, &tree_desc, &opts))
- exit(128);
+ 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 checkout_opts {
- int quiet;
- int merge;
- int force;
-
- char *new_branch;
- int new_branch_log;
- enum branch_track track;
-};
-
struct branch_info {
const char *name; /* The short name used */
const char *path; /* The full name of a real branch */
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 {
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
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;
}
}
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)