13
13
#include "rerere.h"
14
14
15
15
static const char * const git_stash_helper_usage [] = {
16
+ N_ ("git stash--helper drop [-q|--quiet] [<stash>]" ),
16
17
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>]" ),
17
24
NULL
18
25
};
19
26
@@ -22,6 +29,11 @@ static const char * const git_stash_helper_apply_usage[] = {
22
29
NULL
23
30
};
24
31
32
+ static const char * const git_stash_helper_clear_usage [] = {
33
+ N_ ("git stash--helper clear" ),
34
+ NULL
35
+ };
36
+
25
37
static const char * ref_stash = "refs/stash" ;
26
38
static struct strbuf stash_index_path = STRBUF_INIT ;
27
39
@@ -138,6 +150,32 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
138
150
return !(ret == 0 || ret == 1 );
139
151
}
140
152
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
+
141
179
static int reset_tree (struct object_id * i_tree , int update , int reset )
142
180
{
143
181
int nr_trees = 1 ;
@@ -425,6 +463,81 @@ static int apply_stash(int argc, const char **argv, const char *prefix)
425
463
return ret ;
426
464
}
427
465
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
+
428
541
int cmd_stash__helper (int argc , const char * * argv , const char * prefix )
429
542
{
430
543
pid_t pid = getpid ();
@@ -447,6 +560,10 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
447
560
usage_with_options (git_stash_helper_usage , options );
448
561
if (!strcmp (argv [0 ], "apply" ))
449
562
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 );
450
567
451
568
usage_msg_opt (xstrfmt (_ ("unknown subcommand: %s" ), argv [0 ]),
452
569
git_stash_helper_usage , options );
0 commit comments