diff options
Diffstat (limited to 'builtin/checkout.c')
-rw-r--r-- | builtin/checkout.c | 68 |
1 files changed, 27 insertions, 41 deletions
diff --git a/builtin/checkout.c b/builtin/checkout.c index b360943455..fc4f8fd2ea 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1,4 +1,5 @@ #include "builtin.h" +#include "config.h" #include "lockfile.h" #include "parse-options.h" #include "refs.h" @@ -21,31 +22,12 @@ #include "submodule-config.h" #include "submodule.h" -static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; - static const char * const checkout_usage[] = { N_("git checkout [<options>] <branch>"), N_("git checkout [<options>] [<branch>] -- <file>..."), NULL, }; -static int option_parse_recurse_submodules(const struct option *opt, - const char *arg, int unset) -{ - if (unset) { - recurse_submodules = RECURSE_SUBMODULES_OFF; - return 0; - } - if (arg) - recurse_submodules = - parse_update_recurse_submodules_arg(opt->long_name, - arg); - else - recurse_submodules = RECURSE_SUBMODULES_ON; - - return 0; -} - struct checkout_opts { int patch_mode; int quiet; @@ -376,6 +358,8 @@ static int checkout_paths(const struct checkout_opts *opts, state.force = 1; state.refresh_cache = 1; state.istate = &the_index; + + enable_delayed_checkout(&state); for (pos = 0; pos < active_nr; pos++) { struct cache_entry *ce = active_cache[pos]; if (ce->ce_flags & CE_MATCHED) { @@ -390,12 +374,13 @@ static int checkout_paths(const struct checkout_opts *opts, pos = skip_same_name(ce, pos) - 1; } } + errs |= finish_delayed_checkout(&state); if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); read_ref_full("HEAD", 0, rev.hash, NULL); - head = lookup_commit_reference_gently(rev.hash, 1); + head = lookup_commit_reference_gently(&rev, 1); errs |= post_checkout_hook(head, head, 0); return errs; @@ -451,6 +436,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o, * update paths in the work tree, and we cannot revert * them. */ + /* fallthrough */ case 0: return 0; default: @@ -529,10 +515,10 @@ static int merge_working_tree(const struct checkout_opts *opts, setup_standard_excludes(topts.dir); } tree = parse_tree_indirect(old->commit ? - old->commit->object.oid.hash : - EMPTY_TREE_SHA1_BIN); + &old->commit->object.oid : + &empty_tree_oid); init_tree_desc(&trees[0], tree->buffer, tree->size); - tree = parse_tree_indirect(new->commit->object.oid.hash); + tree = parse_tree_indirect(&new->commit->object.oid); init_tree_desc(&trees[1], tree->buffer, tree->size); ret = unpack_trees(2, trees, &topts); @@ -723,7 +709,7 @@ static int add_pending_uninteresting_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data) { - add_pending_sha1(cb_data, refname, oid->hash, UNINTERESTING); + add_pending_oid(cb_data, refname, oid, UNINTERESTING); return 0; } @@ -809,11 +795,16 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new) add_pending_object(&revs, object, oid_to_hex(&object->oid)); for_each_ref(add_pending_uninteresting_ref, &revs); - add_pending_sha1(&revs, "HEAD", new->object.oid.hash, UNINTERESTING); + add_pending_oid(&revs, "HEAD", &new->object.oid, UNINTERESTING); + /* Save pending objects, so they can be cleaned up later. */ refs = revs.pending; revs.leak_pending = 1; + /* + * prepare_revision_walk (together with .leak_pending = 1) makes us + * the sole owner of the list of pending objects. + */ if (prepare_revision_walk(&revs)) die(_("internal error in revision walk")); if (!(old->object.flags & UNINTERESTING)) @@ -821,8 +812,10 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new) else describe_detached_head(_("Previous HEAD position was"), old); + /* Clean up objects used, as they will be reused. */ clear_commit_marks_for_object_array(&refs, ALL_REV_FLAGS); - free(refs.objects); + + object_array_clear(&refs); } static int switch_branches(const struct checkout_opts *opts, @@ -836,7 +829,7 @@ static int switch_branches(const struct checkout_opts *opts, memset(&old, 0, sizeof(old)); old.path = path_to_free = resolve_refdup("HEAD", 0, rev.hash, &flag); if (old.path) - old.commit = lookup_commit_reference_gently(rev.hash, 1); + old.commit = lookup_commit_reference_gently(&rev, 1); if (!(flag & REF_ISSYMREF)) old.path = NULL; @@ -876,7 +869,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb) } if (starts_with(var, "submodule.")) - return parse_submodule_config_option(var, value); + return git_default_submodule_config(var, value, NULL); return git_xmerge_config(var, value, NULL); } @@ -1050,10 +1043,10 @@ static int parse_branchname_arg(int argc, const char **argv, else new->path = NULL; /* not an existing branch */ - new->commit = lookup_commit_reference_gently(rev->hash, 1); + new->commit = lookup_commit_reference_gently(rev, 1); if (!new->commit) { /* not a commit */ - *source_tree = parse_tree_indirect(rev->hash); + *source_tree = parse_tree_indirect(rev); } else { parse_commit_or_die(new->commit); *source_tree = new->commit->tree; @@ -1131,9 +1124,8 @@ static int checkout_branch(struct checkout_opts *opts, if (new->path && !opts->force_detach && !opts->new_branch && !opts->ignore_other_worktrees) { - struct object_id oid; int flag; - char *head_ref = resolve_refdup("HEAD", 0, oid.hash, &flag); + char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag); if (head_ref && (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path))) die_if_checked_out(new->path, 1); @@ -1184,9 +1176,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) N_("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", &recurse_submodules, + { OPTION_CALLBACK, 0, "recurse-submodules", NULL, "checkout", "control recursive updating of submodules", - PARSE_OPT_OPTARG, option_parse_recurse_submodules }, + PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater }, OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")), OPT_END(), }; @@ -1197,7 +1189,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) opts.prefix = prefix; opts.show_progress = -1; - gitmodules_config(); git_config(git_checkout_config, &opts); opts.track = BRANCH_TRACK_UNSPECIFIED; @@ -1217,12 +1208,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) git_xmerge_config("merge.conflictstyle", conflict_style, NULL); } - if (recurse_submodules != RECURSE_SUBMODULES_OFF) { - git_config(submodule_config, NULL); - if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) - set_config_update_recurse_submodules(recurse_submodules); - } - if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1) die(_("-b, -B and --orphan are mutually exclusive")); @@ -1312,6 +1297,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) strbuf_release(&buf); } + UNLEAK(opts); if (opts.patch_mode || opts.pathspec.nr) return checkout_paths(&opts, new.name); else |