worktree: fix worktree add race
[gitweb.git] / builtin / checkout.c
index 6fadf412e830ba4aeaa8d2940fd9a7aab9bd8fa5..24b8593b938b67baf4a662f2463efdd35562873a 100644 (file)
@@ -1,3 +1,4 @@
+#define USE_THE_INDEX_COMPATIBILITY_MACROS
 #include "builtin.h"
 #include "config.h"
 #include "checkout.h"
@@ -260,7 +261,7 @@ static int checkout_paths(const struct checkout_opts *opts,
        struct commit *head;
        int errs = 0;
        struct lock_file lock_file = LOCK_INIT;
-       int nr_checkouts = 0;
+       int nr_checkouts = 0, nr_unmerged = 0;
 
        if (opts->track != BRANCH_TRACK_UNSPECIFIED)
                die(_("'%s' cannot be used with updating paths"), "--track");
@@ -288,7 +289,7 @@ static int checkout_paths(const struct checkout_opts *opts,
                return run_add_interactive(revision, "--patch=checkout",
                                           &opts->pathspec);
 
-       hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
+       repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
        if (read_cache_preload(&opts->pathspec) < 0)
                return error(_("index file corrupt"));
 
@@ -385,23 +386,28 @@ static int checkout_paths(const struct checkout_opts *opts,
                                                       &state, &nr_checkouts);
                        else if (opts->merge)
                                errs |= checkout_merged(pos, &state,
-                                                       &nr_checkouts);
+                                                       &nr_unmerged);
                        pos = skip_same_name(ce, pos) - 1;
                }
        }
        errs |= finish_delayed_checkout(&state, &nr_checkouts);
 
        if (opts->count_checkout_paths) {
+               if (nr_unmerged)
+                       fprintf_ln(stderr, Q_("Recreated %d merge conflict",
+                                             "Recreated %d merge conflicts",
+                                             nr_unmerged),
+                                  nr_unmerged);
                if (opts->source_tree)
-                       fprintf_ln(stderr, Q_("Checked out %d path out of %s",
-                                             "Checked out %d paths out of %s",
+                       fprintf_ln(stderr, Q_("Updated %d path from %s",
+                                             "Updated %d paths from %s",
                                              nr_checkouts),
                                   nr_checkouts,
                                   find_unique_abbrev(&opts->source_tree->object.oid,
                                                      DEFAULT_ABBREV));
-               else
-                       fprintf_ln(stderr, Q_("Checked out %d path out of the index",
-                                             "Checked out %d paths out of the index",
+               else if (!nr_unmerged || nr_checkouts)
+                       fprintf_ln(stderr, Q_("Updated %d path from the index",
+                                             "Updated %d paths from the index",
                                              nr_checkouts),
                                   nr_checkouts);
        }
@@ -592,6 +598,14 @@ static int skip_merge_working_tree(const struct checkout_opts *opts,
         * Remaining variables are not checkout options but used to track state
         */
 
+        /*
+         * Do the merge if this is the initial checkout. We cannot use
+         * is_cache_unborn() here because the index hasn't been loaded yet
+         * so cache_nr and timestamp.sec are always zero.
+         */
+       if (!file_exists(get_index_file()))
+               return 0;
+
        return 1;
 }
 
@@ -693,7 +707,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
                         * a pain; plumb in an option to set
                         * o.renormalize?
                         */
-                       init_merge_options(&o);
+                       init_merge_options(&o, the_repository);
                        o.verbosity = 0;
                        work = write_tree_from_memory(&o);