Skip to content

Commit 4d733c4

Browse files
klusarkdscho
authored andcommitted
stash: convert drop and clear to builtin
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 <[email protected]> Signed-off-by: Paul-Sebastian Ungureanu <[email protected]> Signed-off-by: Thomas Gummerer <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent c58e38d commit 4d733c4

File tree

2 files changed

+119
-2
lines changed

2 files changed

+119
-2
lines changed

builtin/stash--helper.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@
1313
#include "rerere.h"
1414

1515
static const char * const git_stash_helper_usage[] = {
16+
N_("git stash--helper drop [-q|--quiet] [<stash>]"),
1617
N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
18+
N_("git stash--helper clear"),
19+
NULL
20+
};
21+
22+
static const char * const git_stash_helper_drop_usage[] = {
23+
N_("git stash--helper drop [-q|--quiet] [<stash>]"),
1724
NULL
1825
};
1926

@@ -22,6 +29,11 @@ static const char * const git_stash_helper_apply_usage[] = {
2229
NULL
2330
};
2431

32+
static const char * const git_stash_helper_clear_usage[] = {
33+
N_("git stash--helper clear"),
34+
NULL
35+
};
36+
2537
static const char *ref_stash = "refs/stash";
2638
static struct strbuf stash_index_path = STRBUF_INIT;
2739

@@ -137,6 +149,32 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
137149
return !(ret == 0 || ret == 1);
138150
}
139151

152+
static int do_clear_stash(void)
153+
{
154+
struct object_id obj;
155+
if (get_oid(ref_stash, &obj))
156+
return 0;
157+
158+
return delete_ref(NULL, ref_stash, &obj, 0);
159+
}
160+
161+
static int clear_stash(int argc, const char **argv, const char *prefix)
162+
{
163+
struct option options[] = {
164+
OPT_END()
165+
};
166+
167+
argc = parse_options(argc, argv, prefix, options,
168+
git_stash_helper_clear_usage,
169+
PARSE_OPT_STOP_AT_NON_OPTION);
170+
171+
if (argc)
172+
return error(_("git stash clear with parameters is "
173+
"unimplemented"));
174+
175+
return do_clear_stash();
176+
}
177+
140178
static int reset_tree(struct object_id *i_tree, int update, int reset)
141179
{
142180
int nr_trees = 1;
@@ -424,6 +462,81 @@ static int apply_stash(int argc, const char **argv, const char *prefix)
424462
return ret;
425463
}
426464

465+
static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet)
466+
{
467+
int ret;
468+
struct child_process cp_reflog = CHILD_PROCESS_INIT;
469+
struct child_process cp = CHILD_PROCESS_INIT;
470+
471+
/*
472+
* reflog does not provide a simple function for deleting refs. One will
473+
* need to be added to avoid implementing too much reflog code here
474+
*/
475+
476+
cp_reflog.git_cmd = 1;
477+
argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
478+
"--rewrite", NULL);
479+
argv_array_push(&cp_reflog.args, info->revision.buf);
480+
ret = run_command(&cp_reflog);
481+
if (!ret) {
482+
if (!quiet)
483+
printf_ln(_("Dropped %s (%s)"), info->revision.buf,
484+
oid_to_hex(&info->w_commit));
485+
} else {
486+
return error(_("%s: Could not drop stash entry"),
487+
info->revision.buf);
488+
}
489+
490+
/*
491+
* This could easily be replaced by get_oid, but currently it will throw
492+
* a fatal error when a reflog is empty, which we can not recover from.
493+
*/
494+
cp.git_cmd = 1;
495+
/* Even though --quiet is specified, rev-parse still outputs the hash */
496+
cp.no_stdout = 1;
497+
argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
498+
argv_array_pushf(&cp.args, "%s@{0}", ref_stash);
499+
ret = run_command(&cp);
500+
501+
/* do_clear_stash if we just dropped the last stash entry */
502+
if (ret)
503+
do_clear_stash();
504+
505+
return 0;
506+
}
507+
508+
static void assert_stash_ref(struct stash_info *info)
509+
{
510+
if (!info->is_stash_ref) {
511+
error(_("'%s' is not a stash reference"), info->revision.buf);
512+
free_stash_info(info);
513+
exit(1);
514+
}
515+
}
516+
517+
static int drop_stash(int argc, const char **argv, const char *prefix)
518+
{
519+
int ret;
520+
int quiet = 0;
521+
struct stash_info info;
522+
struct option options[] = {
523+
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
524+
OPT_END()
525+
};
526+
527+
argc = parse_options(argc, argv, prefix, options,
528+
git_stash_helper_drop_usage, 0);
529+
530+
if (get_stash_info(&info, argc, argv))
531+
return -1;
532+
533+
assert_stash_ref(&info);
534+
535+
ret = do_drop_stash(prefix, &info, quiet);
536+
free_stash_info(&info);
537+
return ret;
538+
}
539+
427540
int cmd_stash__helper(int argc, const char **argv, const char *prefix)
428541
{
429542
pid_t pid = getpid();
@@ -446,6 +559,10 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
446559
usage_with_options(git_stash_helper_usage, options);
447560
if (!strcmp(argv[0], "apply"))
448561
return !!apply_stash(argc, argv, prefix);
562+
else if (!strcmp(argv[0], "clear"))
563+
return !!clear_stash(argc, argv, prefix);
564+
else if (!strcmp(argv[0], "drop"))
565+
return !!drop_stash(argc, argv, prefix);
449566

450567
usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
451568
git_stash_helper_usage, options);

git-stash.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ apply)
670670
;;
671671
clear)
672672
shift
673-
clear_stash "$@"
673+
git stash--helper clear "$@"
674674
;;
675675
create)
676676
shift
@@ -682,7 +682,7 @@ store)
682682
;;
683683
drop)
684684
shift
685-
drop_stash "$@"
685+
git stash--helper drop "$@"
686686
;;
687687
pop)
688688
shift

0 commit comments

Comments
 (0)