]> asedeno.scripts.mit.edu Git - git.git/commitdiff
Merge branch 'jc/checkout'
authorJunio C Hamano <gitster@pobox.com>
Mon, 2 Jun 2008 05:55:33 +0000 (22:55 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 2 Jun 2008 05:55:36 +0000 (22:55 -0700)
* '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

builtin-checkout.c
unpack-trees.c

index 00dc8cafd827aaffeb9f9e1b8cc7addb7fffaa8d..93ea69bfaa083f49a6e808c7317ea1910b29c847 100644 (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;
+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 */
@@ -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)
index 0de5a31c0b68f87491e540fdc1978809fee00240..cba0aca062f201c5cd5f8799f2190d4a6f06e7c7 100644 (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 */