12
12
#include "rerere.h"
13
13
14
14
static const char * const git_stash_helper_usage [] = {
15
+ N_ ("git stash--helper drop [-q|--quiet] [<stash>]" ),
15
16
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>]" ),
16
23
NULL
17
24
};
18
25
@@ -21,6 +28,11 @@ static const char * const git_stash_helper_apply_usage[] = {
21
28
NULL
22
29
};
23
30
31
+ static const char * const git_stash_helper_clear_usage [] = {
32
+ N_ ("git stash--helper clear" ),
33
+ NULL
34
+ };
35
+
24
36
static const char * ref_stash = "refs/stash" ;
25
37
static struct strbuf stash_index_path = STRBUF_INIT ;
26
38
@@ -136,6 +148,32 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
136
148
return !(ret == 0 || ret == 1 );
137
149
}
138
150
151
+ static int do_clear_stash (void )
152
+ {
153
+ struct object_id obj ;
154
+ if (get_oid (ref_stash , & obj ))
155
+ return 0 ;
156
+
157
+ return delete_ref (NULL , ref_stash , & obj , 0 );
158
+ }
159
+
160
+ static int clear_stash (int argc , const char * * argv , const char * prefix )
161
+ {
162
+ struct option options [] = {
163
+ OPT_END ()
164
+ };
165
+
166
+ argc = parse_options (argc , argv , prefix , options ,
167
+ git_stash_helper_clear_usage ,
168
+ PARSE_OPT_STOP_AT_NON_OPTION );
169
+
170
+ if (argc )
171
+ return error (_ ("git stash clear with parameters is "
172
+ "unimplemented" ));
173
+
174
+ return do_clear_stash ();
175
+ }
176
+
139
177
static int reset_tree (struct object_id * i_tree , int update , int reset )
140
178
{
141
179
int nr_trees = 1 ;
@@ -423,6 +461,81 @@ static int apply_stash(int argc, const char **argv, const char *prefix)
423
461
return ret ;
424
462
}
425
463
464
+ static int do_drop_stash (const char * prefix , struct stash_info * info , int quiet )
465
+ {
466
+ int ret ;
467
+ struct child_process cp_reflog = CHILD_PROCESS_INIT ;
468
+ struct child_process cp = CHILD_PROCESS_INIT ;
469
+
470
+ /*
471
+ * reflog does not provide a simple function for deleting refs. One will
472
+ * need to be added to avoid implementing too much reflog code here
473
+ */
474
+
475
+ cp_reflog .git_cmd = 1 ;
476
+ argv_array_pushl (& cp_reflog .args , "reflog" , "delete" , "--updateref" ,
477
+ "--rewrite" , NULL );
478
+ argv_array_push (& cp_reflog .args , info -> revision .buf );
479
+ ret = run_command (& cp_reflog );
480
+ if (!ret ) {
481
+ if (!quiet )
482
+ printf_ln (_ ("Dropped %s (%s)" ), info -> revision .buf ,
483
+ oid_to_hex (& info -> w_commit ));
484
+ } else {
485
+ return error (_ ("%s: Could not drop stash entry" ),
486
+ info -> revision .buf );
487
+ }
488
+
489
+ /*
490
+ * This could easily be replaced by get_oid, but currently it will throw
491
+ * a fatal error when a reflog is empty, which we can not recover from.
492
+ */
493
+ cp .git_cmd = 1 ;
494
+ /* Even though --quiet is specified, rev-parse still outputs the hash */
495
+ cp .no_stdout = 1 ;
496
+ argv_array_pushl (& cp .args , "rev-parse" , "--verify" , "--quiet" , NULL );
497
+ argv_array_pushf (& cp .args , "%s@{0}" , ref_stash );
498
+ ret = run_command (& cp );
499
+
500
+ /* do_clear_stash if we just dropped the last stash entry */
501
+ if (ret )
502
+ do_clear_stash ();
503
+
504
+ return 0 ;
505
+ }
506
+
507
+ static void assert_stash_ref (struct stash_info * info )
508
+ {
509
+ if (!info -> is_stash_ref ) {
510
+ error (_ ("'%s' is not a stash reference" ), info -> revision .buf );
511
+ free_stash_info (info );
512
+ exit (1 );
513
+ }
514
+ }
515
+
516
+ static int drop_stash (int argc , const char * * argv , const char * prefix )
517
+ {
518
+ int ret ;
519
+ int quiet = 0 ;
520
+ struct stash_info info ;
521
+ struct option options [] = {
522
+ OPT__QUIET (& quiet , N_ ("be quiet, only report errors" )),
523
+ OPT_END ()
524
+ };
525
+
526
+ argc = parse_options (argc , argv , prefix , options ,
527
+ git_stash_helper_drop_usage , 0 );
528
+
529
+ if (get_stash_info (& info , argc , argv ))
530
+ return -1 ;
531
+
532
+ assert_stash_ref (& info );
533
+
534
+ ret = do_drop_stash (prefix , & info , quiet );
535
+ free_stash_info (& info );
536
+ return ret ;
537
+ }
538
+
426
539
int cmd_stash__helper (int argc , const char * * argv , const char * prefix )
427
540
{
428
541
pid_t pid = getpid ();
@@ -445,6 +558,10 @@ int cmd_stash__helper(int argc, const char **argv, const char *prefix)
445
558
usage_with_options (git_stash_helper_usage , options );
446
559
if (!strcmp (argv [0 ], "apply" ))
447
560
return !!apply_stash (argc , argv , prefix );
561
+ else if (!strcmp (argv [0 ], "clear" ))
562
+ return !!clear_stash (argc , argv , prefix );
563
+ else if (!strcmp (argv [0 ], "drop" ))
564
+ return !!drop_stash (argc , argv , prefix );
448
565
449
566
usage_msg_opt (xstrfmt (_ ("unknown subcommand: %s" ), argv [0 ]),
450
567
git_stash_helper_usage , options );
0 commit comments