1313#include "rerere.h"
1414
1515static 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+
2537static const char * ref_stash = "refs/stash" ;
2638static struct strbuf stash_index_path = STRBUF_INIT ;
2739
@@ -138,6 +150,32 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
138150 return !(ret == 0 || ret == 1 );
139151}
140152
153+ static int do_clear_stash (void )
154+ {
155+ struct object_id obj ;
156+ if (get_oid (ref_stash , & obj ))
157+ return 0 ;
158+
159+ return delete_ref (NULL , ref_stash , & obj , 0 );
160+ }
161+
162+ static int clear_stash (int argc , const char * * argv , const char * prefix )
163+ {
164+ struct option options [] = {
165+ OPT_END ()
166+ };
167+
168+ argc = parse_options (argc , argv , prefix , options ,
169+ git_stash_helper_clear_usage ,
170+ PARSE_OPT_STOP_AT_NON_OPTION );
171+
172+ if (argc )
173+ return error (_ ("git stash clear with parameters is "
174+ "unimplemented" ));
175+
176+ return do_clear_stash ();
177+ }
178+
141179static int reset_tree (struct object_id * i_tree , int update , int reset )
142180{
143181 int nr_trees = 1 ;
@@ -425,6 +463,81 @@ static int apply_stash(int argc, const char **argv, const char *prefix)
425463 return ret ;
426464}
427465
466+ static int do_drop_stash (const char * prefix , struct stash_info * info , int quiet )
467+ {
468+ int ret ;
469+ struct child_process cp_reflog = CHILD_PROCESS_INIT ;
470+ struct child_process cp = CHILD_PROCESS_INIT ;
471+
472+ /*
473+ * reflog does not provide a simple function for deleting refs. One will
474+ * need to be added to avoid implementing too much reflog code here
475+ */
476+
477+ cp_reflog .git_cmd = 1 ;
478+ argv_array_pushl (& cp_reflog .args , "reflog" , "delete" , "--updateref" ,
479+ "--rewrite" , NULL );
480+ argv_array_push (& cp_reflog .args , info -> revision .buf );
481+ ret = run_command (& cp_reflog );
482+ if (!ret ) {
483+ if (!quiet )
484+ printf_ln (_ ("Dropped %s (%s)" ), info -> revision .buf ,
485+ oid_to_hex (& info -> w_commit ));
486+ } else {
487+ return error (_ ("%s: Could not drop stash entry" ),
488+ info -> revision .buf );
489+ }
490+
491+ /*
492+ * This could easily be replaced by get_oid, but currently it will throw
493+ * a fatal error when a reflog is empty, which we can not recover from.
494+ */
495+ cp .git_cmd = 1 ;
496+ /* Even though --quiet is specified, rev-parse still outputs the hash */
497+ cp .no_stdout = 1 ;
498+ argv_array_pushl (& cp .args , "rev-parse" , "--verify" , "--quiet" , NULL );
499+ argv_array_pushf (& cp .args , "%s@{0}" , ref_stash );
500+ ret = run_command (& cp );
501+
502+ /* do_clear_stash if we just dropped the last stash entry */
503+ if (ret )
504+ do_clear_stash ();
505+
506+ return 0 ;
507+ }
508+
509+ static void assert_stash_ref (struct stash_info * info )
510+ {
511+ if (!info -> is_stash_ref ) {
512+ free_stash_info (info );
513+ error (_ ("'%s' is not a stash reference" ), info -> revision .buf );
514+ exit (128 );
515+ }
516+ }
517+
518+ static int drop_stash (int argc , const char * * argv , const char * prefix )
519+ {
520+ int ret ;
521+ int quiet = 0 ;
522+ struct stash_info info ;
523+ struct option options [] = {
524+ OPT__QUIET (& quiet , N_ ("be quiet, only report errors" )),
525+ OPT_END ()
526+ };
527+
528+ argc = parse_options (argc , argv , prefix , options ,
529+ git_stash_helper_drop_usage , 0 );
530+
531+ if (get_stash_info (& info , argc , argv ))
532+ return -1 ;
533+
534+ assert_stash_ref (& info );
535+
536+ ret = do_drop_stash (prefix , & info , quiet );
537+ free_stash_info (& info );
538+ return ret ;
539+ }
540+
428541int cmd_stash__helper (int argc , const char * * argv , const char * prefix )
429542{
430543 pid_t pid = getpid ();
@@ -447,6 +560,10 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
447560 usage_with_options (git_stash_helper_usage , options );
448561 if (!strcmp (argv [0 ], "apply" ))
449562 return !!apply_stash (argc , argv , prefix );
563+ else if (!strcmp (argv [0 ], "clear" ))
564+ return !!clear_stash (argc , argv , prefix );
565+ else if (!strcmp (argv [0 ], "drop" ))
566+ return !!drop_stash (argc , argv , prefix );
450567
451568 usage_msg_opt (xstrfmt (_ ("unknown subcommand: %s" ), argv [0 ]),
452569 git_stash_helper_usage , options );
0 commit comments