diff options
Diffstat (limited to 'builtin/reset.c')
-rw-r--r-- | builtin/reset.c | 79 |
1 files changed, 64 insertions, 15 deletions
diff --git a/builtin/reset.c b/builtin/reset.c index 11cd0dcb8c..8ae69d6f2b 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -7,6 +7,7 @@ * * Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "config.h" #include "lockfile.h" @@ -25,10 +26,13 @@ #include "submodule.h" #include "submodule-config.h" +#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000) + static const char * const git_reset_usage[] = { N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"), - N_("git reset [-q] [<tree-ish>] [--] <paths>..."), - N_("git reset --patch [<tree-ish>] [--] [<paths>...]"), + N_("git reset [-q] [<tree-ish>] [--] <pathspec>..."), + N_("git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"), + N_("git reset --patch [<tree-ish>] [--] [<pathspec>...]"), NULL }; @@ -42,7 +46,7 @@ static inline int is_merge(void) return !access(git_path_merge_head(the_repository), F_OK); } -static int reset_index(const struct object_id *oid, int reset_type, int quiet) +static int reset_index(const char *ref, const struct object_id *oid, int reset_type, int quiet) { int i, nr = 0; struct tree_desc desc[2]; @@ -56,6 +60,7 @@ static int reset_index(const struct object_id *oid, int reset_type, int quiet) opts.dst_index = &the_index; opts.fn = oneway_merge; opts.merge = 1; + init_checkout_metadata(&opts.meta, ref, oid, NULL); if (!quiet) opts.verbose_update = 1; switch (reset_type) { @@ -76,13 +81,13 @@ static int reset_index(const struct object_id *oid, int reset_type, int quiet) struct object_id head_oid; if (get_oid("HEAD", &head_oid)) return error(_("You do not have a valid HEAD.")); - if (!fill_tree_descriptor(desc + nr, &head_oid)) + if (!fill_tree_descriptor(the_repository, desc + nr, &head_oid)) return error(_("Failed to find tree of HEAD.")); nr++; opts.fn = twoway_merge; } - if (!fill_tree_descriptor(desc + nr, oid)) { + if (!fill_tree_descriptor(the_repository, desc + nr, oid)) { error(_("Failed to find tree of %s."), oid_to_hex(oid)); goto out; } @@ -93,7 +98,7 @@ static int reset_index(const struct object_id *oid, int reset_type, int quiet) if (reset_type == MIXED || reset_type == HARD) { tree = parse_tree_indirect(oid); - prime_cache_tree(&the_index, tree); + prime_cache_tree(the_repository, the_repository->index, tree); } ret = 0; @@ -159,6 +164,7 @@ static int read_from_tree(const struct pathspec *pathspec, opt.format_callback = update_index_from_diff; opt.format_callback_data = &intent_to_add; opt.flags.override_submodule_config = 1; + opt.repo = the_repository; if (do_diff_cache(tree_oid, &opt)) return 1; @@ -280,8 +286,8 @@ static int git_reset_config(const char *var, const char *value, void *cb) int cmd_reset(int argc, const char **argv, const char *prefix) { int reset_type = NONE, update_ref_status = 0, quiet = 0; - int patch_mode = 0, unborn; - const char *rev; + int patch_mode = 0, pathspec_file_nul = 0, unborn; + const char *rev, *pathspec_from_file = NULL; struct object_id oid; struct pathspec pathspec; int intent_to_add = 0; @@ -296,26 +302,43 @@ int cmd_reset(int argc, const char **argv, const char *prefix) N_("reset HEAD, index and working tree"), MERGE), OPT_SET_INT(0, "keep", &reset_type, N_("reset HEAD but keep local changes"), KEEP), - { OPTION_CALLBACK, 0, "recurse-submodules", NULL, + OPT_CALLBACK_F(0, "recurse-submodules", NULL, "reset", "control recursive updating of submodules", - PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater }, + PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater), OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")), OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that removed paths will be added later")), + OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), + OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), OPT_END() }; git_config(git_reset_config, NULL); + git_config_get_bool("reset.quiet", &quiet); argc = parse_options(argc, argv, prefix, options, git_reset_usage, PARSE_OPT_KEEP_DASHDASH); parse_args(&pathspec, argv, prefix, patch_mode, &rev); + if (pathspec_from_file) { + if (patch_mode) + die(_("--pathspec-from-file is incompatible with --patch")); + + if (pathspec.nr) + die(_("--pathspec-from-file is incompatible with pathspec arguments")); + + parse_pathspec_file(&pathspec, 0, + PATHSPEC_PREFER_FULL, + prefix, pathspec_from_file, pathspec_file_nul); + } else if (pathspec_file_nul) { + die(_("--pathspec-file-nul requires --pathspec-from-file")); + } + unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid); if (unborn) { /* reset on unborn branch: treat as reset to empty tree */ oidcpy(&oid, the_hash_algo->empty_tree); - } else if (!pathspec.nr) { + } else if (!pathspec.nr && !patch_mode) { struct commit *commit; if (get_oid_committish(rev, &oid)) die(_("Failed to resolve '%s' as a valid revision."), rev); @@ -336,6 +359,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) if (patch_mode) { if (reset_type != NONE) die(_("--patch is incompatible with --{hard,mixed,soft}")); + trace2_cmd_mode("patch-interactive"); return run_add_interactive(rev, "--patch=reset", &pathspec); } @@ -352,6 +376,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix) if (reset_type == NONE) reset_type = MIXED; /* by default */ + if (pathspec.nr) + trace2_cmd_mode("path"); + else + trace2_cmd_mode(reset_type_names[reset_type]); + if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree())) setup_work_tree(); @@ -375,15 +404,35 @@ int cmd_reset(int argc, const char **argv, const char *prefix) int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN; if (read_from_tree(&pathspec, &oid, intent_to_add)) return 1; - if (get_git_work_tree()) + the_index.updated_skipworktree = 1; + if (!quiet && get_git_work_tree()) { + uint64_t t_begin, t_delta_in_ms; + + t_begin = getnanotime(); refresh_index(&the_index, flags, NULL, NULL, _("Unstaged changes after reset:")); + t_delta_in_ms = (getnanotime() - t_begin) / 1000000; + if (advice_reset_quiet_warning && t_delta_in_ms > REFRESH_INDEX_DELAY_WARNING_IN_MS) { + printf(_("\nIt took %.2f seconds to enumerate unstaged changes after reset. You can\n" + "use '--quiet' to avoid this. Set the config setting reset.quiet to true\n" + "to make this the default.\n"), t_delta_in_ms / 1000.0); + } + } } else { - int err = reset_index(&oid, reset_type, quiet); + struct object_id dummy; + char *ref = NULL; + int err; + + dwim_ref(rev, strlen(rev), &dummy, &ref); + if (ref && !starts_with(ref, "refs/")) + ref = NULL; + + err = reset_index(ref, &oid, reset_type, quiet); if (reset_type == KEEP && !err) - err = reset_index(&oid, MIXED, quiet); + err = reset_index(ref, &oid, MIXED, quiet); if (err) die(_("Could not reset index file to revision '%s'."), rev); + free(ref); } if (write_locked_index(&the_index, &lock, COMMIT_LOCK)) @@ -399,7 +448,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) print_new_head_line(lookup_commit_reference(the_repository, &oid)); } if (!pathspec.nr) - remove_branch_state(); + remove_branch_state(the_repository, 0); return update_ref_status; } |