diff options
Diffstat (limited to 'builtin/checkout.c')
-rw-r--r-- | builtin/checkout.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/builtin/checkout.c b/builtin/checkout.c index acdafc6e4c..ece4eb14bf 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "config.h" #include "checkout.h" @@ -44,6 +45,7 @@ struct checkout_opts { int ignore_skipworktree; int ignore_other_worktrees; int show_progress; + int count_checkout_paths; /* * If new checkout options are added, skip_merge_working_tree * should be updated accordingly. @@ -115,7 +117,8 @@ static int update_some(const struct object_id *oid, struct strbuf *base, static int read_tree_some(struct tree *tree, const struct pathspec *pathspec) { - read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL); + read_tree_recursive(the_repository, tree, "", 0, 0, + pathspec, update_some, NULL); /* update the index with the given tree's info * for all args, expanding wildcards, and exit @@ -165,12 +168,13 @@ static int check_stages(unsigned stages, const struct cache_entry *ce, int pos) } static int checkout_stage(int stage, const struct cache_entry *ce, int pos, - const struct checkout *state) + const struct checkout *state, int *nr_checkouts) { while (pos < active_nr && !strcmp(active_cache[pos]->name, ce->name)) { if (ce_stage(active_cache[pos]) == stage) - return checkout_entry(active_cache[pos], state, NULL); + return checkout_entry(active_cache[pos], state, + NULL, nr_checkouts); pos++; } if (stage == 2) @@ -179,7 +183,7 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos, return error(_("path '%s' does not have their version"), ce->name); } -static int checkout_merged(int pos, const struct checkout *state) +static int checkout_merged(int pos, const struct checkout *state, int *nr_checkouts) { struct cache_entry *ce = active_cache[pos]; const char *path = ce->name; @@ -242,7 +246,7 @@ static int checkout_merged(int pos, const struct checkout *state) ce = make_transient_cache_entry(mode, &oid, path, 2); if (!ce) die(_("make_cache_entry failed for path '%s'"), path); - status = checkout_entry(ce, state, NULL); + status = checkout_entry(ce, state, NULL, nr_checkouts); discard_cache_entry(ce); return status; } @@ -257,6 +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; if (opts->track != BRANCH_TRACK_UNSPECIFIED) die(_("'%s' cannot be used with updating paths"), "--track"); @@ -284,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")); @@ -371,17 +376,36 @@ static int checkout_paths(const struct checkout_opts *opts, struct cache_entry *ce = active_cache[pos]; if (ce->ce_flags & CE_MATCHED) { if (!ce_stage(ce)) { - errs |= checkout_entry(ce, &state, NULL); + errs |= checkout_entry(ce, &state, + NULL, &nr_checkouts); continue; } if (opts->writeout_stage) - errs |= checkout_stage(opts->writeout_stage, ce, pos, &state); + errs |= checkout_stage(opts->writeout_stage, + ce, pos, + &state, &nr_checkouts); else if (opts->merge) - errs |= checkout_merged(pos, &state); + errs |= checkout_merged(pos, &state, + &nr_checkouts); pos = skip_same_name(ce, pos) - 1; } } - errs |= finish_delayed_checkout(&state); + errs |= finish_delayed_checkout(&state, &nr_checkouts); + + if (opts->count_checkout_paths) { + if (opts->source_tree) + fprintf_ln(stderr, Q_("Checked out %d path out of %s", + "Checked out %d paths out of %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", + nr_checkouts), + nr_checkouts); + } if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); @@ -569,6 +593,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; } @@ -670,7 +702,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); @@ -753,7 +785,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts, free(refname); } else - create_branch(opts->new_branch, new_branch_info->name, + create_branch(the_repository, + opts->new_branch, new_branch_info->name, opts->new_branch_force ? 1 : 0, opts->new_branch_force ? 1 : 0, opts->new_branch_log, @@ -811,7 +844,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, delete_reflog(old_branch_info->path); } } - remove_branch_state(); + remove_branch_state(the_repository); strbuf_release(&msg); if (!opts->quiet && (new_branch_info->path || (!opts->force_detach && !strcmp(new_branch_info->name, "HEAD")))) @@ -1064,6 +1097,7 @@ static int parse_branchname_arg(int argc, const char **argv, has_dash_dash = 1; /* case (3) or (1) */ else if (dash_dash_pos >= 2) die(_("only one reference expected, %d given."), dash_dash_pos); + opts->count_checkout_paths = !opts->quiet && !has_dash_dash; if (!strcmp(arg, "-")) arg = "@{-1}"; @@ -1079,9 +1113,12 @@ static int parse_branchname_arg(int argc, const char **argv, */ int recover_with_dwim = dwim_new_local_branch_ok; - if (!has_dash_dash && - (check_filename(opts->prefix, arg) || !no_wildcard(arg))) + int could_be_checkout_paths = !has_dash_dash && + check_filename(opts->prefix, arg); + + if (!has_dash_dash && !no_wildcard(arg)) recover_with_dwim = 0; + /* * Accept "git checkout foo" and "git checkout foo --" * as candidates for dwim. @@ -1094,6 +1131,10 @@ static int parse_branchname_arg(int argc, const char **argv, const char *remote = unique_tracking_name(arg, rev, dwim_remotes_matched); if (remote) { + if (could_be_checkout_paths) + die(_("'%s' could be both a local file and a tracking branch.\n" + "Please use -- (and optionally --no-guess) to disambiguate"), + arg); *new_branch = arg; arg = remote; /* DWIMmed to create local branch, case (3).(b) */ @@ -1228,7 +1269,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) struct checkout_opts opts; struct branch_info new_branch_info; char *conflict_style = NULL; - int dwim_new_local_branch = 1; + int dwim_new_local_branch, no_dwim_new_local_branch = 0; int dwim_remotes_matched = 0; struct option options[] = { OPT__QUIET(&opts.quiet, N_("suppress progress reporting")), @@ -1258,8 +1299,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")), OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree, N_("do not limit pathspecs to sparse entries only")), - OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch, - N_("second guess 'git checkout <no-such-branch>'")), + OPT_BOOL(0, "no-guess", &no_dwim_new_local_branch, + N_("do not second guess 'git checkout <no-such-branch>'")), OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees, N_("do not check if another worktree is holding the given ref")), { OPTION_CALLBACK, 0, "recurse-submodules", NULL, @@ -1282,6 +1323,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, checkout_usage, PARSE_OPT_KEEP_DASHDASH); + dwim_new_local_branch = !no_dwim_new_local_branch; if (opts.show_progress < 0) { if (opts.quiet) opts.show_progress = 0; |