Skip to content

Commit

Permalink
stash: convert drop and clear to builtin
Browse files Browse the repository at this point in the history
Add the drop and clear commands to the builtin helper. These two
are each simple, but are being added together as they are quite
related.

We have to unfortunately keep the drop and clear functions in the
shell script as functions are called with parameters internally
that are not valid when the commands are called externally. Once
pop is converted they can both be removed.

Signed-off-by: Joel Teichroeb <joel@teichroeb.net>
Signed-off-by: Paul-Sebastian Ungureanu <ungureanupaulsebastian@gmail.com>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
klusark authored and gitster committed Mar 7, 2019
1 parent 8a0fc8d commit 4e2dd39
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 2 deletions.
117 changes: 117 additions & 0 deletions builtin/stash--helper.c
Expand Up @@ -12,7 +12,14 @@
#include "rerere.h"

static const char * const git_stash_helper_usage[] = {
N_("git stash--helper drop [-q|--quiet] [<stash>]"),
N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
N_("git stash--helper clear"),
NULL
};

static const char * const git_stash_helper_drop_usage[] = {
N_("git stash--helper drop [-q|--quiet] [<stash>]"),
NULL
};

Expand All @@ -21,6 +28,11 @@ static const char * const git_stash_helper_apply_usage[] = {
NULL
};

static const char * const git_stash_helper_clear_usage[] = {
N_("git stash--helper clear"),
NULL
};

static const char *ref_stash = "refs/stash";
static struct strbuf stash_index_path = STRBUF_INIT;

Expand Down Expand Up @@ -136,6 +148,32 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
return !(ret == 0 || ret == 1);
}

static int do_clear_stash(void)
{
struct object_id obj;
if (get_oid(ref_stash, &obj))
return 0;

return delete_ref(NULL, ref_stash, &obj, 0);
}

static int clear_stash(int argc, const char **argv, const char *prefix)
{
struct option options[] = {
OPT_END()
};

argc = parse_options(argc, argv, prefix, options,
git_stash_helper_clear_usage,
PARSE_OPT_STOP_AT_NON_OPTION);

if (argc)
return error(_("git stash clear with parameters is "
"unimplemented"));

return do_clear_stash();
}

static int reset_tree(struct object_id *i_tree, int update, int reset)
{
int nr_trees = 1;
Expand Down Expand Up @@ -423,6 +461,81 @@ static int apply_stash(int argc, const char **argv, const char *prefix)
return ret;
}

static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet)
{
int ret;
struct child_process cp_reflog = CHILD_PROCESS_INIT;
struct child_process cp = CHILD_PROCESS_INIT;

/*
* reflog does not provide a simple function for deleting refs. One will
* need to be added to avoid implementing too much reflog code here
*/

cp_reflog.git_cmd = 1;
argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
"--rewrite", NULL);
argv_array_push(&cp_reflog.args, info->revision.buf);
ret = run_command(&cp_reflog);
if (!ret) {
if (!quiet)
printf_ln(_("Dropped %s (%s)"), info->revision.buf,
oid_to_hex(&info->w_commit));
} else {
return error(_("%s: Could not drop stash entry"),
info->revision.buf);
}

/*
* This could easily be replaced by get_oid, but currently it will throw
* a fatal error when a reflog is empty, which we can not recover from.
*/
cp.git_cmd = 1;
/* Even though --quiet is specified, rev-parse still outputs the hash */
cp.no_stdout = 1;
argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
argv_array_pushf(&cp.args, "%s@{0}", ref_stash);
ret = run_command(&cp);

/* do_clear_stash if we just dropped the last stash entry */
if (ret)
do_clear_stash();

return 0;
}

static void assert_stash_ref(struct stash_info *info)
{
if (!info->is_stash_ref) {
error(_("'%s' is not a stash reference"), info->revision.buf);
free_stash_info(info);
exit(1);
}
}

static int drop_stash(int argc, const char **argv, const char *prefix)
{
int ret;
int quiet = 0;
struct stash_info info;
struct option options[] = {
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
OPT_END()
};

argc = parse_options(argc, argv, prefix, options,
git_stash_helper_drop_usage, 0);

if (get_stash_info(&info, argc, argv))
return -1;

assert_stash_ref(&info);

ret = do_drop_stash(prefix, &info, quiet);
free_stash_info(&info);
return ret;
}

int cmd_stash__helper(int argc, const char **argv, const char *prefix)
{
pid_t pid = getpid();
Expand All @@ -445,6 +558,10 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
usage_with_options(git_stash_helper_usage, options);
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);

usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
git_stash_helper_usage, options);
Expand Down
4 changes: 2 additions & 2 deletions git-stash.sh
Expand Up @@ -670,7 +670,7 @@ apply)
;;
clear)
shift
clear_stash "$@"
git stash--helper clear "$@"
;;
create)
shift
Expand All @@ -682,7 +682,7 @@ store)
;;
drop)
shift
drop_stash "$@"
git stash--helper drop "$@"
;;
pop)
shift
Expand Down

0 comments on commit 4e2dd39

Please sign in to comment.