aboutsummaryrefslogtreecommitdiffstats
path: root/builtin/stash.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/stash.c')
-rw-r--r--builtin/stash.c131
1 files changed, 70 insertions, 61 deletions
diff --git a/builtin/stash.c b/builtin/stash.c
index 3fe549f7d3..30fa101460 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -117,6 +117,10 @@ struct stash_info {
int has_u;
};
+#define STASH_INFO_INIT { \
+ .revision = STRBUF_INIT, \
+}
+
static void free_stash_info(struct stash_info *info)
{
strbuf_release(&info->revision);
@@ -158,10 +162,8 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
if (argc == 1)
commit = argv[0];
- strbuf_init(&info->revision, 0);
if (!commit) {
if (!ref_exists(ref_stash)) {
- free_stash_info(info);
fprintf_ln(stderr, _("No stash entries found."));
return -1;
}
@@ -175,11 +177,8 @@ 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)) {
- error(_("%s is not a valid reference"), revision);
- free_stash_info(info);
- return -1;
- }
+ if (get_oid(revision, &info->w_commit))
+ return error(_("%s is not a valid reference"), revision);
assert_stash_like(info, revision);
@@ -198,7 +197,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
info->is_stash_ref = !strcmp(expanded_ref, ref_stash);
break;
default: /* Invalid or ambiguous */
- free_stash_info(info);
+ break;
}
free(expanded_ref);
@@ -357,7 +356,7 @@ static int restore_untracked(struct object_id *u_tree)
cp.git_cmd = 1;
strvec_push(&cp.args, "read-tree");
strvec_push(&cp.args, oid_to_hex(u_tree));
- strvec_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
+ strvec_pushf(&cp.env, "GIT_INDEX_FILE=%s",
stash_index_path.buf);
if (run_command(&cp)) {
remove_path(stash_index_path.buf);
@@ -367,7 +366,7 @@ static int restore_untracked(struct object_id *u_tree)
child_process_init(&cp);
cp.git_cmd = 1;
strvec_pushl(&cp.args, "checkout-index", "--all", NULL);
- strvec_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
+ strvec_pushf(&cp.env, "GIT_INDEX_FILE=%s",
stash_index_path.buf);
res = run_command(&cp);
@@ -603,9 +602,9 @@ restore_untracked:
*/
cp.git_cmd = 1;
cp.dir = prefix;
- strvec_pushf(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT"=%s",
+ strvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT"=%s",
absolute_path(get_git_work_tree()));
- strvec_pushf(&cp.env_array, GIT_DIR_ENVIRONMENT"=%s",
+ strvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT"=%s",
absolute_path(get_git_dir()));
strvec_push(&cp.args, "status");
run_command(&cp);
@@ -616,10 +615,10 @@ restore_untracked:
static int apply_stash(int argc, const char **argv, const char *prefix)
{
- int ret;
+ int ret = -1;
int quiet = 0;
int index = 0;
- struct stash_info info;
+ struct stash_info info = STASH_INFO_INIT;
struct option options[] = {
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
OPT_BOOL(0, "index", &index,
@@ -631,9 +630,10 @@ static int apply_stash(int argc, const char **argv, const char *prefix)
git_stash_apply_usage, 0);
if (get_stash_info(&info, argc, argv))
- return -1;
+ goto cleanup;
ret = do_apply_stash(prefix, &info, index, quiet);
+cleanup:
free_stash_info(&info);
return ret;
}
@@ -669,20 +669,25 @@ static int do_drop_stash(struct stash_info *info, int quiet)
return 0;
}
-static void assert_stash_ref(struct stash_info *info)
+static int get_stash_info_assert(struct stash_info *info, int argc,
+ const char **argv)
{
- if (!info->is_stash_ref) {
- error(_("'%s' is not a stash reference"), info->revision.buf);
- free_stash_info(info);
- exit(1);
- }
+ int ret = get_stash_info(info, argc, argv);
+
+ if (ret < 0)
+ return ret;
+
+ if (!info->is_stash_ref)
+ return error(_("'%s' is not a stash reference"), info->revision.buf);
+
+ return 0;
}
static int drop_stash(int argc, const char **argv, const char *prefix)
{
- int ret;
+ int ret = -1;
int quiet = 0;
- struct stash_info info;
+ struct stash_info info = STASH_INFO_INIT;
struct option options[] = {
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
OPT_END()
@@ -691,22 +696,21 @@ static int drop_stash(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options,
git_stash_drop_usage, 0);
- if (get_stash_info(&info, argc, argv))
- return -1;
-
- assert_stash_ref(&info);
+ if (get_stash_info_assert(&info, argc, argv))
+ goto cleanup;
ret = do_drop_stash(&info, quiet);
+cleanup:
free_stash_info(&info);
return ret;
}
static int pop_stash(int argc, const char **argv, const char *prefix)
{
- int ret;
+ int ret = -1;
int index = 0;
int quiet = 0;
- struct stash_info info;
+ struct stash_info info = STASH_INFO_INIT;
struct option options[] = {
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
OPT_BOOL(0, "index", &index,
@@ -717,25 +721,25 @@ static int pop_stash(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options,
git_stash_pop_usage, 0);
- if (get_stash_info(&info, argc, argv))
- return -1;
+ if (get_stash_info_assert(&info, argc, argv))
+ goto cleanup;
- assert_stash_ref(&info);
if ((ret = do_apply_stash(prefix, &info, index, quiet)))
printf_ln(_("The stash entry is kept in case "
"you need it again."));
else
ret = do_drop_stash(&info, quiet);
+cleanup:
free_stash_info(&info);
return ret;
}
static int branch_stash(int argc, const char **argv, const char *prefix)
{
- int ret;
+ int ret = -1;
const char *branch = NULL;
- struct stash_info info;
+ struct stash_info info = STASH_INFO_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
struct option options[] = {
OPT_END()
@@ -752,7 +756,7 @@ static int branch_stash(int argc, const char **argv, const char *prefix)
branch = argv[0];
if (get_stash_info(&info, argc - 1, argv + 1))
- return -1;
+ goto cleanup;
cp.git_cmd = 1;
strvec_pushl(&cp.args, "checkout", "-b", NULL);
@@ -764,8 +768,8 @@ static int branch_stash(int argc, const char **argv, const char *prefix)
if (!ret && info.is_stash_ref)
ret = do_drop_stash(&info, 0);
+cleanup:
free_stash_info(&info);
-
return ret;
}
@@ -843,8 +847,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op
static int show_stash(int argc, const char **argv, const char *prefix)
{
int i;
- int ret = 0;
- struct stash_info info;
+ int ret = -1;
+ struct stash_info info = STASH_INFO_INIT;
struct rev_info rev;
struct strvec stash_args = STRVEC_INIT;
struct strvec revision_args = STRVEC_INIT;
@@ -862,6 +866,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)
UNTRACKED_ONLY, PARSE_OPT_NONEG),
OPT_END()
};
+ int do_usage = 0;
init_diff_ui_defaults();
git_config(git_diff_ui_config, NULL);
@@ -879,10 +884,8 @@ static int show_stash(int argc, const char **argv, const char *prefix)
strvec_push(&revision_args, argv[i]);
}
- ret = get_stash_info(&info, stash_args.nr, stash_args.v);
- strvec_clear(&stash_args);
- if (ret)
- return -1;
+ if (get_stash_info(&info, stash_args.nr, stash_args.v))
+ goto cleanup;
/*
* The config settings are applied only if there are not passed
@@ -896,16 +899,14 @@ static int show_stash(int argc, const char **argv, const char *prefix)
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
if (!show_stat && !show_patch) {
- free_stash_info(&info);
- return 0;
+ ret = 0;
+ goto cleanup;
}
}
argc = setup_revisions(revision_args.nr, revision_args.v, &rev, NULL);
- if (argc > 1) {
- free_stash_info(&info);
- usage_with_options(git_stash_show_usage, options);
- }
+ if (argc > 1)
+ goto usage;
if (!rev.diffopt.output_format) {
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
diff_setup_done(&rev.diffopt);
@@ -930,8 +931,17 @@ static int show_stash(int argc, const char **argv, const char *prefix)
}
log_tree_diff_flush(&rev);
+ ret = diff_result_code(&rev.diffopt, 0);
+cleanup:
+ strvec_clear(&stash_args);
free_stash_info(&info);
- return diff_result_code(&rev.diffopt, 0);
+ release_revisions(&rev);
+ if (do_usage)
+ usage_with_options(git_stash_show_usage, options);
+ return ret;
+usage:
+ do_usage = 1;
+ goto cleanup;
}
static int do_store_stash(const struct object_id *w_commit, const char *stash_msg,
@@ -1065,7 +1075,6 @@ static int check_changes_tracked_files(const struct pathspec *ps)
goto done;
}
- object_array_clear(&rev.pending);
result = run_diff_files(&rev, 0);
if (diff_result_code(&rev.diffopt, result)) {
ret = 1;
@@ -1073,7 +1082,7 @@ static int check_changes_tracked_files(const struct pathspec *ps)
}
done:
- clear_pathspec(&rev.prune_data);
+ release_revisions(&rev);
return ret;
}
@@ -1106,7 +1115,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
cp_upd_index.git_cmd = 1;
strvec_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
"--remove", "--stdin", NULL);
- strvec_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
+ strvec_pushf(&cp_upd_index.env, "GIT_INDEX_FILE=%s",
stash_index_path.buf);
strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf);
@@ -1180,7 +1189,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
cp_read_tree.git_cmd = 1;
strvec_pushl(&cp_read_tree.args, "read-tree", "HEAD", NULL);
- strvec_pushf(&cp_read_tree.env_array, "GIT_INDEX_FILE=%s",
+ strvec_pushf(&cp_read_tree.env, "GIT_INDEX_FILE=%s",
stash_index_path.buf);
if (run_command(&cp_read_tree)) {
ret = -1;
@@ -1267,7 +1276,7 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
strvec_pushl(&cp_upd_index.args, "update-index",
"--ignore-skip-worktree-entries",
"-z", "--add", "--remove", "--stdin", NULL);
- strvec_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
+ strvec_pushf(&cp_upd_index.env, "GIT_INDEX_FILE=%s",
stash_index_path.buf);
if (pipe_command(&cp_upd_index, diff_output.buf, diff_output.len,
@@ -1284,9 +1293,7 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
done:
discard_index(&istate);
- UNLEAK(rev);
- object_array_clear(&rev.pending);
- clear_pathspec(&rev.prune_data);
+ release_revisions(&rev);
strbuf_release(&diff_output);
remove_path(stash_index_path.buf);
return ret;
@@ -1428,9 +1435,9 @@ done:
static int create_stash(int argc, const char **argv, const char *prefix)
{
- int ret = 0;
+ int ret;
struct strbuf stash_msg_buf = STRBUF_INIT;
- struct stash_info info;
+ struct stash_info info = STASH_INFO_INIT;
struct pathspec ps;
/* Starting with argv[1], since argv[0] is "create" */
@@ -1445,6 +1452,7 @@ static int create_stash(int argc, const char **argv, const char *prefix)
if (!ret)
printf_ln("%s", oid_to_hex(&info.w_commit));
+ free_stash_info(&info);
strbuf_release(&stash_msg_buf);
return ret;
}
@@ -1453,7 +1461,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
int keep_index, int patch_mode, int include_untracked, int only_staged)
{
int ret = 0;
- struct stash_info info;
+ struct stash_info info = STASH_INFO_INIT;
struct strbuf patch = STRBUF_INIT;
struct strbuf stash_msg_buf = STRBUF_INIT;
struct strbuf untracked_files = STRBUF_INIT;
@@ -1543,7 +1551,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
cp.git_cmd = 1;
if (startup_info->original_cwd) {
cp.dir = startup_info->original_cwd;
- strvec_pushf(&cp.env_array, "%s=%s",
+ strvec_pushf(&cp.env, "%s=%s",
GIT_WORK_TREE_ENVIRONMENT,
the_repository->worktree);
}
@@ -1652,6 +1660,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
}
done:
+ free_stash_info(&info);
strbuf_release(&stash_msg_buf);
return ret;
}