summaryrefslogtreecommitdiff
path: root/builtin/stash.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/stash.c')
-rw-r--r--builtin/stash.c304
1 files changed, 176 insertions, 128 deletions
diff --git a/builtin/stash.c b/builtin/stash.c
index 30fa101..062be1f 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1,6 +1,12 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
+#include "abspath.h"
#include "config.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hash.h"
+#include "hex.h"
+#include "object-name.h"
#include "parse-options.h"
#include "refs.h"
#include "lockfile.h"
@@ -12,81 +18,108 @@
#include "run-command.h"
#include "dir.h"
#include "entry.h"
+#include "preload-index.h"
+#include "read-cache.h"
#include "rerere.h"
#include "revision.h"
+#include "setup.h"
+#include "sparse-index.h"
#include "log-tree.h"
#include "diffcore.h"
-#include "exec-cmd.h"
#include "reflog.h"
+#include "add-interactive.h"
#define INCLUDE_ALL_FILES 2
+#define BUILTIN_STASH_LIST_USAGE \
+ N_("git stash list [<log-options>]")
+#define BUILTIN_STASH_SHOW_USAGE \
+ N_("git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]")
+#define BUILTIN_STASH_DROP_USAGE \
+ N_("git stash drop [-q | --quiet] [<stash>]")
+#define BUILTIN_STASH_POP_USAGE \
+ N_("git stash pop [--index] [-q | --quiet] [<stash>]")
+#define BUILTIN_STASH_APPLY_USAGE \
+ N_("git stash apply [--index] [-q | --quiet] [<stash>]")
+#define BUILTIN_STASH_BRANCH_USAGE \
+ N_("git stash branch <branchname> [<stash>]")
+#define BUILTIN_STASH_STORE_USAGE \
+ N_("git stash store [(-m | --message) <message>] [-q | --quiet] <commit>")
+#define BUILTIN_STASH_PUSH_USAGE \
+ N_("git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]\n" \
+ " [-u | --include-untracked] [-a | --all] [(-m | --message) <message>]\n" \
+ " [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" \
+ " [--] [<pathspec>...]]")
+#define BUILTIN_STASH_SAVE_USAGE \
+ N_("git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]\n" \
+ " [-u | --include-untracked] [-a | --all] [<message>]")
+#define BUILTIN_STASH_CREATE_USAGE \
+ N_("git stash create [<message>]")
+#define BUILTIN_STASH_CLEAR_USAGE \
+ "git stash clear"
+
static const char * const git_stash_usage[] = {
- N_("git stash list [<options>]"),
- N_("git stash show [<options>] [<stash>]"),
- N_("git stash drop [-q|--quiet] [<stash>]"),
- N_("git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]"),
- N_("git stash branch <branchname> [<stash>]"),
- "git stash clear",
- N_("git stash [push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--quiet]\n"
- " [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
- " [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
- " [--] [<pathspec>...]]"),
- N_("git stash save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--quiet]\n"
- " [-u|--include-untracked] [-a|--all] [<message>]"),
+ BUILTIN_STASH_LIST_USAGE,
+ BUILTIN_STASH_SHOW_USAGE,
+ BUILTIN_STASH_DROP_USAGE,
+ BUILTIN_STASH_POP_USAGE,
+ BUILTIN_STASH_APPLY_USAGE,
+ BUILTIN_STASH_BRANCH_USAGE,
+ BUILTIN_STASH_PUSH_USAGE,
+ BUILTIN_STASH_SAVE_USAGE,
+ BUILTIN_STASH_CLEAR_USAGE,
+ BUILTIN_STASH_CREATE_USAGE,
+ BUILTIN_STASH_STORE_USAGE,
NULL
};
static const char * const git_stash_list_usage[] = {
- N_("git stash list [<options>]"),
+ BUILTIN_STASH_LIST_USAGE,
NULL
};
static const char * const git_stash_show_usage[] = {
- N_("git stash show [<options>] [<stash>]"),
+ BUILTIN_STASH_SHOW_USAGE,
NULL
};
static const char * const git_stash_drop_usage[] = {
- N_("git stash drop [-q|--quiet] [<stash>]"),
+ BUILTIN_STASH_DROP_USAGE,
NULL
};
static const char * const git_stash_pop_usage[] = {
- N_("git stash pop [--index] [-q|--quiet] [<stash>]"),
+ BUILTIN_STASH_POP_USAGE,
NULL
};
static const char * const git_stash_apply_usage[] = {
- N_("git stash apply [--index] [-q|--quiet] [<stash>]"),
+ BUILTIN_STASH_APPLY_USAGE,
NULL
};
static const char * const git_stash_branch_usage[] = {
- N_("git stash branch <branchname> [<stash>]"),
+ BUILTIN_STASH_BRANCH_USAGE,
NULL
};
static const char * const git_stash_clear_usage[] = {
- "git stash clear",
+ BUILTIN_STASH_CLEAR_USAGE,
NULL
};
static const char * const git_stash_store_usage[] = {
- N_("git stash store [-m|--message <message>] [-q|--quiet] <commit>"),
+ BUILTIN_STASH_STORE_USAGE,
NULL
};
static const char * const git_stash_push_usage[] = {
- N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
- " [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
- " [--] [<pathspec>...]]"),
+ BUILTIN_STASH_PUSH_USAGE,
NULL
};
static const char * const git_stash_save_usage[] = {
- N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
- " [-u|--include-untracked] [-a|--all] [<message>]"),
+ BUILTIN_STASH_SAVE_USAGE,
NULL
};
@@ -177,7 +210,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
revision = info->revision.buf;
- if (get_oid(revision, &info->w_commit))
+ if (repo_get_oid(the_repository, revision, &info->w_commit))
return error(_("%s is not a valid reference"), revision);
assert_stash_like(info, revision);
@@ -187,7 +220,8 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
end_of_rev = strchrnul(revision, '@');
strbuf_add(&symbolic, revision, end_of_rev - revision);
- ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref, 0);
+ ret = repo_dwim_ref(the_repository, symbolic.buf, symbolic.len,
+ &dummy, &expanded_ref, 0);
strbuf_release(&symbolic);
switch (ret) {
case 0: /* Not found, but valid ref */
@@ -207,7 +241,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
static int do_clear_stash(void)
{
struct object_id obj;
- if (get_oid(ref_stash, &obj))
+ if (repo_get_oid(the_repository, ref_stash, &obj))
return 0;
return delete_ref(NULL, ref_stash, &obj, 0);
@@ -238,11 +272,11 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
struct tree *tree;
struct lock_file lock_file = LOCK_INIT;
- read_cache_preload(NULL);
- if (refresh_cache(REFRESH_QUIET))
+ repo_read_index_preload(the_repository, NULL, 0);
+ if (refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL))
return -1;
- hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
+ repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
memset(&opts, 0, sizeof(opts));
@@ -250,7 +284,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
if (parse_tree(tree))
return -1;
- init_tree_desc(t, tree->buffer, tree->size);
+ init_tree_desc(t, &tree->object.oid, tree->buffer, tree->size);
opts.head_idx = 1;
opts.src_index = &the_index;
@@ -327,7 +361,7 @@ static int is_path_a_directory(const char *path)
}
static void add_diff_to_buf(struct diff_queue_struct *q,
- struct diff_options *options,
+ struct diff_options *options UNUSED,
void *data)
{
int i;
@@ -403,7 +437,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
* to the index before a merge was run) and the current index
* (reflecting the changes brought in by the merge).
*/
- diff_setup(&diff_opts);
+ repo_diff_setup(the_repository, &diff_opts);
diff_opts.flags.recursive = 1;
diff_opts.detect_rename = 0;
diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
@@ -431,10 +465,10 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
* path, but left it out of the working tree, then clear the
* SKIP_WORKTREE bit and write it to the working tree.
*/
- if (pos >= 0 && ce_skip_worktree(active_cache[pos])) {
+ if (pos >= 0 && ce_skip_worktree(the_index.cache[pos])) {
struct stat st;
- ce = active_cache[pos];
+ ce = the_index.cache[pos];
if (!lstat(ce->name, &st)) {
/* Conflicting path present; relocate it */
struct strbuf new_path = STRBUF_INIT;
@@ -486,7 +520,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR);
if (write_locked_index(&the_index, &lock,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
- die(_("Unable to write index."));
+ die(_("could not write index"));
}
static int do_apply_stash(const char *prefix, struct stash_info *info,
@@ -500,11 +534,13 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
struct tree *head, *merge, *merge_base;
struct lock_file lock = LOCK_INIT;
- read_cache_preload(NULL);
- if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
- return -1;
+ repo_read_index_preload(the_repository, NULL, 0);
+ if (repo_refresh_and_write_index(the_repository, REFRESH_QUIET, 0, 0,
+ NULL, NULL, NULL))
+ return error(_("could not write index"));
- if (write_cache_as_tree(&c_tree, 0, NULL))
+ if (write_index_as_tree(&c_tree, &the_index, get_index_file(), 0,
+ NULL))
return error(_("cannot apply a stash in the middle of a merge"));
if (index) {
@@ -526,14 +562,15 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
return error(_("conflicts in index. "
"Try without --index."));
- discard_cache();
- read_cache();
- if (write_cache_as_tree(&index_tree, 0, NULL))
+ discard_index(&the_index);
+ repo_read_index(the_repository);
+ if (write_index_as_tree(&index_tree, &the_index,
+ get_index_file(), 0, NULL))
return error(_("could not save index tree"));
reset_head();
- discard_cache();
- read_cache();
+ discard_index(&the_index);
+ repo_read_index(the_repository);
}
}
@@ -573,7 +610,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
ret = error(_("could not write index"));
if (ret) {
- rerere(0);
+ repo_rerere(the_repository, 0);
if (index)
fprintf_ln(stderr, _("Index was not unstashed."));
@@ -638,9 +675,12 @@ cleanup:
return ret;
}
-static int reject_reflog_ent(struct object_id *ooid, struct object_id *noid,
- const char *email, timestamp_t timestamp, int tz,
- const char *message, void *cb_data)
+static int reject_reflog_ent(struct object_id *ooid UNUSED,
+ struct object_id *noid UNUSED,
+ const char *email UNUSED,
+ timestamp_t timestamp UNUSED,
+ int tz UNUSED, const char *message UNUSED,
+ void *cb_data UNUSED)
{
return 1;
}
@@ -782,7 +822,7 @@ static int list_stash(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options,
git_stash_list_usage,
- PARSE_OPT_KEEP_UNKNOWN);
+ PARSE_OPT_KEEP_UNKNOWN_OPT);
if (!ref_exists(ref_stash))
return 0;
@@ -800,7 +840,8 @@ static int show_stat = 1;
static int show_patch;
static int show_include_untracked;
-static int git_stash_config(const char *var, const char *value, void *cb)
+static int git_stash_config(const char *var, const char *value,
+ const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "stash.showstat")) {
show_stat = git_config_bool(var, value);
@@ -814,7 +855,7 @@ static int git_stash_config(const char *var, const char *value, void *cb)
show_include_untracked = git_config_bool(var, value);
return 0;
}
- return git_diff_basic_config(var, value, cb);
+ return git_diff_basic_config(var, value, ctx, cb);
}
static void diff_include_untracked(const struct stash_info *info, struct diff_options *diff_opt)
@@ -829,7 +870,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op
tree[i] = parse_tree_indirect(oid[i]);
if (parse_tree(tree[i]) < 0)
die(_("failed to parse tree"));
- init_tree_desc(&tree_desc[i], tree[i]->buffer, tree[i]->size);
+ init_tree_desc(&tree_desc[i], &tree[i]->object.oid,
+ tree[i]->buffer, tree[i]->size);
}
unpack_tree_opt.head_idx = -1;
@@ -870,10 +912,10 @@ static int show_stash(int argc, const char **argv, const char *prefix)
init_diff_ui_defaults();
git_config(git_diff_ui_config, NULL);
- init_revisions(&rev, prefix);
+ repo_init_revisions(the_repository, &rev, prefix);
argc = parse_options(argc, argv, prefix, options, git_stash_show_usage,
- PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
+ PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT |
PARSE_OPT_KEEP_DASHDASH);
strvec_push(&revision_args, argv[0]);
@@ -931,7 +973,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
}
log_tree_diff_flush(&rev);
- ret = diff_result_code(&rev.diffopt, 0);
+ ret = diff_result_code(&rev.diffopt);
cleanup:
strvec_clear(&stash_args);
free_stash_info(&info);
@@ -947,6 +989,12 @@ usage:
static int do_store_stash(const struct object_id *w_commit, const char *stash_msg,
int quiet)
{
+ struct stash_info info;
+ char revision[GIT_MAX_HEXSZ];
+
+ oid_to_hex_r(revision, w_commit);
+ assert_stash_like(&info, revision);
+
if (!stash_msg)
stash_msg = "Created via \"git stash store\".";
@@ -979,7 +1027,7 @@ static int store_stash(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options,
git_stash_store_usage,
- PARSE_OPT_KEEP_UNKNOWN);
+ PARSE_OPT_KEEP_UNKNOWN_OPT);
if (argc != 1) {
if (!quiet)
@@ -1047,19 +1095,18 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked,
*/
static int check_changes_tracked_files(const struct pathspec *ps)
{
- int result;
struct rev_info rev;
struct object_id dummy;
int ret = 0;
/* No initial commit. */
- if (get_oid("HEAD", &dummy))
+ if (repo_get_oid(the_repository, "HEAD", &dummy))
return -1;
- if (read_cache() < 0)
+ if (repo_read_index(the_repository) < 0)
return -1;
- init_revisions(&rev, NULL);
+ repo_init_revisions(the_repository, &rev, NULL);
copy_pathspec(&rev.prune_data, ps);
rev.diffopt.flags.quick = 1;
@@ -1069,14 +1116,14 @@ static int check_changes_tracked_files(const struct pathspec *ps)
add_head_to_pending(&rev);
diff_setup_done(&rev.diffopt);
- result = run_diff_index(&rev, 1);
- if (diff_result_code(&rev.diffopt, result)) {
+ run_diff_index(&rev, DIFF_INDEX_CACHED);
+ if (diff_result_code(&rev.diffopt)) {
ret = 1;
goto done;
}
- result = run_diff_files(&rev, 0);
- if (diff_result_code(&rev.diffopt, result)) {
+ run_diff_files(&rev, 0);
+ if (diff_result_code(&rev.diffopt)) {
ret = 1;
goto done;
}
@@ -1110,7 +1157,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
int ret = 0;
struct strbuf untracked_msg = STRBUF_INIT;
struct child_process cp_upd_index = CHILD_PROCESS_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
cp_upd_index.git_cmd = 1;
strvec_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
@@ -1138,7 +1185,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
}
done:
- discard_index(&istate);
+ release_index(&istate);
strbuf_release(&untracked_msg);
remove_path(stash_index_path.buf);
return ret;
@@ -1149,7 +1196,7 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
{
int ret = 0;
struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
if (write_index_as_tree(&info->w_tree, &istate, the_repository->index_file,
0, NULL)) {
@@ -1172,7 +1219,7 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
}
done:
- discard_index(&istate);
+ release_index(&istate);
return ret;
}
@@ -1182,7 +1229,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
int ret = 0;
struct child_process cp_read_tree = CHILD_PROCESS_INIT;
struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
char *old_index_env = NULL, *old_repo_index_file;
remove_path(stash_index_path.buf);
@@ -1202,7 +1249,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
- ret = run_add_interactive(NULL, "--patch=stash", ps);
+ ret = !!run_add_p(the_repository, ADD_P_STASH, NULL, ps);
the_repository->index_file = old_repo_index_file;
if (old_index_env && *old_index_env)
@@ -1233,7 +1280,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
}
done:
- discard_index(&istate);
+ release_index(&istate);
remove_path(stash_index_path.buf);
return ret;
}
@@ -1244,9 +1291,9 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
struct rev_info rev;
struct child_process cp_upd_index = CHILD_PROCESS_INIT;
struct strbuf diff_output = STRBUF_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
- init_revisions(&rev, NULL);
+ repo_init_revisions(the_repository, &rev, NULL);
copy_pathspec(&rev.prune_data, ps);
set_alternate_index_output(stash_index_path.buf);
@@ -1260,17 +1307,14 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
rev.diffopt.format_callback = add_diff_to_buf;
rev.diffopt.format_callback_data = &diff_output;
- if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
+ if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
ret = -1;
goto done;
}
add_pending_object(&rev, parse_object(the_repository, &info->b_commit),
"");
- if (run_diff_index(&rev, 0)) {
- ret = -1;
- goto done;
- }
+ run_diff_index(&rev, 0);
cp_upd_index.git_cmd = 1;
strvec_pushl(&cp_upd_index.args, "update-index",
@@ -1292,7 +1336,7 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
}
done:
- discard_index(&istate);
+ release_index(&istate);
release_revisions(&rev);
strbuf_release(&diff_output);
remove_path(stash_index_path.buf);
@@ -1318,13 +1362,14 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
prepare_fallback_ident("git stash", "git@stash");
- read_cache_preload(NULL);
- if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0) {
- ret = -1;
+ repo_read_index_preload(the_repository, NULL, 0);
+ if (repo_refresh_and_write_index(the_repository, REFRESH_QUIET, 0, 0,
+ NULL, NULL, NULL) < 0) {
+ ret = error(_("could not write index"));
goto done;
}
- if (get_oid("HEAD", &info->b_commit)) {
+ if (repo_get_oid(the_repository, "HEAD", &info->b_commit)) {
if (!quiet)
fprintf_ln(stderr, _("You do not have "
"the initial commit yet"));
@@ -1342,14 +1387,16 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
branch_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
if (flags & REF_ISSYMREF)
skip_prefix(branch_ref, "refs/heads/", &branch_name);
- head_short_sha1 = find_unique_abbrev(&head_commit->object.oid,
- DEFAULT_ABBREV);
+ head_short_sha1 = repo_find_unique_abbrev(the_repository,
+ &head_commit->object.oid,
+ DEFAULT_ABBREV);
strbuf_addf(&msg, "%s: %s ", branch_name, head_short_sha1);
pp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg);
strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf);
commit_list_insert(head_commit, &parents);
- if (write_cache_as_tree(&info->i_tree, 0, NULL) ||
+ if (write_index_as_tree(&info->i_tree, &the_index, get_index_file(), 0,
+ NULL) ||
commit_tree(commit_tree_label.buf, commit_tree_label.len,
&info->i_tree, parents, &info->i_commit, NULL, NULL)) {
if (!quiet)
@@ -1433,7 +1480,7 @@ done:
return ret;
}
-static int create_stash(int argc, const char **argv, const char *prefix)
+static int create_stash(int argc, const char **argv, const char *prefix UNUSED)
{
int ret;
struct strbuf stash_msg_buf = STRBUF_INIT;
@@ -1487,15 +1534,15 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
goto done;
}
- read_cache_preload(NULL);
+ repo_read_index_preload(the_repository, NULL, 0);
if (!include_untracked && ps->nr) {
int i;
char *ps_matched = xcalloc(ps->nr, 1);
/* TODO: audit for interaction with sparse-index. */
ensure_full_index(&the_index);
- for (i = 0; i < active_nr; i++)
- ce_path_match(&the_index, active_cache[i], ps,
+ for (i = 0; i < the_index.cache_nr; i++)
+ ce_path_match(&the_index, the_index.cache[i], ps,
ps_matched);
if (report_path_error(ps_matched, ps)) {
@@ -1507,8 +1554,9 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
free(ps_matched);
}
- if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) {
- ret = -1;
+ if (repo_refresh_and_write_index(the_repository, REFRESH_QUIET, 0, 0,
+ NULL, NULL, NULL)) {
+ ret = error(_("could not write index"));
goto done;
}
@@ -1564,7 +1612,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
goto done;
}
}
- discard_cache();
+ discard_index(&the_index);
if (ps->nr) {
struct child_process cp_add = CHILD_PROCESS_INIT;
struct child_process cp_diff = CHILD_PROCESS_INIT;
@@ -1660,8 +1708,10 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
}
done:
+ strbuf_release(&patch);
free_stash_info(&info);
strbuf_release(&stash_msg_buf);
+ strbuf_release(&untracked_files);
return ret;
}
@@ -1696,6 +1746,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
OPT_END()
};
+ int ret;
if (argc) {
force_assume = !strcmp(argv[0], "-p");
@@ -1735,8 +1786,15 @@ static int push_stash(int argc, const char **argv, const char *prefix,
die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
}
- return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
- include_untracked, only_staged);
+ ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+ include_untracked, only_staged);
+ clear_pathspec(&ps);
+ return ret;
+}
+
+static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
+{
+ return push_stash(argc, argv, prefix, 0);
}
static int save_stash(int argc, const char **argv, const char *prefix)
@@ -1787,15 +1845,28 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
pid_t pid = getpid();
const char *index_file;
struct strvec args = STRVEC_INIT;
-
+ parse_opt_subcommand_fn *fn = NULL;
struct option options[] = {
+ OPT_SUBCOMMAND("apply", &fn, apply_stash),
+ OPT_SUBCOMMAND("clear", &fn, clear_stash),
+ OPT_SUBCOMMAND("drop", &fn, drop_stash),
+ OPT_SUBCOMMAND("pop", &fn, pop_stash),
+ OPT_SUBCOMMAND("branch", &fn, branch_stash),
+ OPT_SUBCOMMAND("list", &fn, list_stash),
+ OPT_SUBCOMMAND("show", &fn, show_stash),
+ OPT_SUBCOMMAND("store", &fn, store_stash),
+ OPT_SUBCOMMAND("create", &fn, create_stash),
+ OPT_SUBCOMMAND("push", &fn, push_stash_unassumed),
+ OPT_SUBCOMMAND_F("save", &fn, save_stash, PARSE_OPT_NOCOMPLETE),
OPT_END()
};
git_config(git_stash_config, NULL);
argc = parse_options(argc, argv, prefix, options, git_stash_usage,
- PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH);
+ PARSE_OPT_SUBCOMMAND_OPTIONAL |
+ PARSE_OPT_KEEP_UNKNOWN_OPT |
+ PARSE_OPT_KEEP_DASHDASH);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
@@ -1804,33 +1875,10 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file,
(uintmax_t)pid);
- if (!argc)
- return !!push_stash(0, NULL, prefix, 0);
- else if (!strcmp(argv[0], "apply"))
- return !!apply_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "clear"))
- return !!clear_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "drop"))
- return !!drop_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "pop"))
- return !!pop_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "branch"))
- return !!branch_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "list"))
- return !!list_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "show"))
- return !!show_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "store"))
- return !!store_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "create"))
- return !!create_stash(argc, argv, prefix);
- else if (!strcmp(argv[0], "push"))
- return !!push_stash(argc, argv, prefix, 0);
- else if (!strcmp(argv[0], "save"))
- return !!save_stash(argc, argv, prefix);
- else if (*argv[0] != '-')
- usage_msg_optf(_("unknown subcommand: %s"),
- git_stash_usage, options, argv[0]);
+ if (fn)
+ return !!fn(argc, argv, prefix);
+ else if (!argc)
+ return !!push_stash_unassumed(0, NULL, prefix);
/* Assume 'stash push' */
strvec_push(&args, "push");