@matheusbsbs / matheus-bagliano / commits / 291d823e36
Fork 0

checkout: "best effort" checkout

When unpack_trees() returned an error while switching branches, we used to stop right there, exiting without writing the index out or switching HEAD. This is Ok when unpack_trees() returned an error because it detected untracked files or locally modified paths that could be overwritten by branch switching, because that error return is done before we start to modify the work tree. But it is undesirable if unpack_trees() already started to update the work tree and a failure is returned because some but not all paths are updated in the work tree, perhaps because a directory that some files need to go in was read-only by mistake, or a file that will be overwritten by branch switching had a mandatory lock on it and we failed to unlink it. This changes the behaviour upon such an error to complete the branch switching; the files updated in the work tree will hopefully be much more consistent with the index and HEAD derived from the switched-to branch. We still issue error messages, and exit the command with non-zero status, so scripted callers need to notice it. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed May 28, 2008 at 15:26 UTC 291d823e364cb51cab67f0786b809fe038b92aa8
1 file changed +18 -4
builtin-checkout.c
+18 -4
@@ -155,6 +155,7 @@ struct checkout_opts {
155 int quiet;
156 int merge;
157 int force;
158 + int writeout_error;
159
160 char *new_branch;
161 int new_branch_log;
@@ -178,9 +179,20 @@ static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
179 opts.dst_index = &the_index;
180 parse_tree(tree);
181 init_tree_desc(&tree_desc, tree->buffer, tree->size);
181 - if (unpack_trees(1, &tree_desc, &opts))
182 + switch (unpack_trees(1, &tree_desc, &opts)) {
183 + case -2:
184 + o->writeout_error = 1;
185 + /*
186 + * We return 0 nevertheless, as the index is all right
187 + * and more importantly we have made best efforts to
188 + * update paths in the work tree, and we cannot revert
189 + * them.
190 + */
191 + case 0:
192 + return 0;
193 + default:
194 return 128;
183 - return 0;
195 + }
196 }
197
198 struct branch_info {
@@ -243,7 +255,8 @@ static int merge_working_tree(struct checkout_opts *opts,
255 tree = parse_tree_indirect(new->commit->object.sha1);
256 init_tree_desc(&trees[1], tree->buffer, tree->size);
257
246 - if (unpack_trees(2, trees, &topts)) {
258 + ret = unpack_trees(2, trees, &topts);
259 + if (ret == -1) {
260 /*
261 * Unpack couldn't do a trivial merge; either
262 * give up or do a real merge, depending on
@@ -478,7 +491,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
491
492 update_refs_for_switch(opts, &old, new);
493
481 - return post_checkout_hook(old.commit, new->commit, 1);
494 + ret = post_checkout_hook(old.commit, new->commit, 1);
495 + return ret || opts->writeout_error;
496 }
497
498 int cmd_checkout(int argc, const char **argv, const char *prefix)