1212#include "rerere.h"
1313
1414static const char * const git_stash_helper_usage [] = {
15+ N_ ("git stash--helper drop [-q|--quiet] [<stash>]" ),
1516 N_ ("git stash--helper apply [--index] [-q|--quiet] [<stash>]" ),
17+ N_ ("git stash--helper clear" ),
18+ NULL
19+ };
20+
21+ static const char * const git_stash_helper_drop_usage [] = {
22+ N_ ("git stash--helper drop [-q|--quiet] [<stash>]" ),
1623 NULL
1724};
1825
@@ -21,6 +28,11 @@ static const char * const git_stash_helper_apply_usage[] = {
2128 NULL
2229};
2330
31+ static const char * const git_stash_helper_clear_usage [] = {
32+ N_ ("git stash--helper clear" ),
33+ NULL
34+ };
35+
2436static const char * ref_stash = "refs/stash" ;
2537static struct strbuf stash_index_path = STRBUF_INIT ;
2638
@@ -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+
140178static 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+ free_stash_info (info );
512+ error (_ ("'%s' is not a stash reference" ), info -> revision .buf );
513+ exit (128 );
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+
427540int 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 );
0 commit comments