16
16
#include "builtin.h"
17
17
#include "abspath.h"
18
18
#include "date.h"
19
+ #include "dir.h"
19
20
#include "environment.h"
20
21
#include "hex.h"
21
22
#include "config.h"
33
34
#include "pack-objects.h"
34
35
#include "path.h"
35
36
#include "reflog.h"
37
+ #include "rerere.h"
36
38
#include "blob.h"
37
39
#include "tree.h"
38
40
#include "promisor-remote.h"
43
45
#include "hook.h"
44
46
#include "setup.h"
45
47
#include "trace2.h"
48
+ #include "worktree.h"
46
49
47
50
#define FAILED_RUN "failed to run %s"
48
51
@@ -52,15 +55,9 @@ static const char * const builtin_gc_usage[] = {
52
55
};
53
56
54
57
static timestamp_t gc_log_expire_time ;
55
-
56
58
static struct strvec repack = STRVEC_INIT ;
57
- static struct strvec prune = STRVEC_INIT ;
58
- static struct strvec prune_worktrees = STRVEC_INIT ;
59
- static struct strvec rerere = STRVEC_INIT ;
60
-
61
59
static struct tempfile * pidfile ;
62
60
static struct lock_file log_lock ;
63
-
64
61
static struct string_list pack_garbage = STRING_LIST_INIT_DUP ;
65
62
66
63
static void clean_pack_garbage (void )
@@ -339,6 +336,94 @@ static int maintenance_task_reflog_expire(struct maintenance_run_opts *opts UNUS
339
336
return run_command (& cmd );
340
337
}
341
338
339
+ static int maintenance_task_worktree_prune (struct maintenance_run_opts * opts UNUSED ,
340
+ struct gc_config * cfg )
341
+ {
342
+ struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT ;
343
+
344
+ prune_worktrees_cmd .git_cmd = 1 ;
345
+ strvec_pushl (& prune_worktrees_cmd .args , "worktree" , "prune" , "--expire" , NULL );
346
+ strvec_push (& prune_worktrees_cmd .args , cfg -> prune_worktrees_expire );
347
+
348
+ return run_command (& prune_worktrees_cmd );
349
+ }
350
+
351
+ static int worktree_prune_condition (struct gc_config * cfg )
352
+ {
353
+ struct strbuf buf = STRBUF_INIT ;
354
+ int should_prune = 0 , limit = 1 ;
355
+ timestamp_t expiry_date ;
356
+ struct dirent * d ;
357
+ DIR * dir = NULL ;
358
+
359
+ git_config_get_int ("maintenance.worktree-prune.auto" , & limit );
360
+ if (limit <= 0 ) {
361
+ should_prune = limit < 0 ;
362
+ goto out ;
363
+ }
364
+
365
+ if (parse_expiry_date (cfg -> prune_worktrees_expire , & expiry_date ))
366
+ goto out ;
367
+
368
+ dir = opendir (repo_git_path_replace (the_repository , & buf , "worktrees" ));
369
+ if (!dir )
370
+ goto out ;
371
+
372
+ while (limit && (d = readdir_skip_dot_and_dotdot (dir ))) {
373
+ char * wtpath ;
374
+ strbuf_reset (& buf );
375
+ if (should_prune_worktree (d -> d_name , & buf , & wtpath , expiry_date ))
376
+ limit -- ;
377
+ free (wtpath );
378
+ }
379
+
380
+ should_prune = !limit ;
381
+
382
+ out :
383
+ if (dir )
384
+ closedir (dir );
385
+ strbuf_release (& buf );
386
+ return should_prune ;
387
+ }
388
+
389
+ static int maintenance_task_rerere_gc (struct maintenance_run_opts * opts UNUSED ,
390
+ struct gc_config * cfg UNUSED )
391
+ {
392
+ struct child_process rerere_cmd = CHILD_PROCESS_INIT ;
393
+ rerere_cmd .git_cmd = 1 ;
394
+ strvec_pushl (& rerere_cmd .args , "rerere" , "gc" , NULL );
395
+ return run_command (& rerere_cmd );
396
+ }
397
+
398
+ static int rerere_gc_condition (struct gc_config * cfg UNUSED )
399
+ {
400
+ struct strbuf path = STRBUF_INIT ;
401
+ int should_gc = 0 , limit = 1 ;
402
+ DIR * dir = NULL ;
403
+
404
+ git_config_get_int ("maintenance.rerere-gc.auto" , & limit );
405
+ if (limit <= 0 ) {
406
+ should_gc = limit < 0 ;
407
+ goto out ;
408
+ }
409
+
410
+ /*
411
+ * We skip garbage collection in case we either have no "rr-cache"
412
+ * directory or when it doesn't contain at least one entry.
413
+ */
414
+ repo_git_path_replace (the_repository , & path , "rr-cache" );
415
+ dir = opendir (path .buf );
416
+ if (!dir )
417
+ goto out ;
418
+ should_gc = !!readdir_skip_dot_and_dotdot (dir );
419
+
420
+ out :
421
+ strbuf_release (& path );
422
+ if (dir )
423
+ closedir (dir );
424
+ return should_gc ;
425
+ }
426
+
342
427
static int too_many_loose_objects (struct gc_config * cfg )
343
428
{
344
429
/*
@@ -728,9 +813,9 @@ static void gc_before_repack(struct maintenance_run_opts *opts,
728
813
}
729
814
730
815
int cmd_gc (int argc ,
731
- const char * * argv ,
732
- const char * prefix ,
733
- struct repository * repo UNUSED )
816
+ const char * * argv ,
817
+ const char * prefix ,
818
+ struct repository * repo UNUSED )
734
819
{
735
820
int aggressive = 0 ;
736
821
int quiet = 0 ;
@@ -740,7 +825,6 @@ struct repository *repo UNUSED)
740
825
int daemonized = 0 ;
741
826
int keep_largest_pack = -1 ;
742
827
timestamp_t dummy ;
743
- struct child_process rerere_cmd = CHILD_PROCESS_INIT ;
744
828
struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT ;
745
829
struct gc_config cfg = GC_CONFIG_INIT ;
746
830
const char * prune_expire_sentinel = "sentinel" ;
@@ -779,9 +863,6 @@ struct repository *repo UNUSED)
779
863
builtin_gc_usage , builtin_gc_options );
780
864
781
865
strvec_pushl (& repack , "repack" , "-d" , "-l" , NULL );
782
- strvec_pushl (& prune , "prune" , "--expire" , NULL );
783
- strvec_pushl (& prune_worktrees , "worktree" , "prune" , "--expire" , NULL );
784
- strvec_pushl (& rerere , "rerere" , "gc" , NULL );
785
866
786
867
gc_config (& cfg );
787
868
@@ -907,34 +988,27 @@ struct repository *repo UNUSED)
907
988
if (cfg .prune_expire ) {
908
989
struct child_process prune_cmd = CHILD_PROCESS_INIT ;
909
990
991
+ strvec_pushl (& prune_cmd .args , "prune" , "--expire" , NULL );
910
992
/* run `git prune` even if using cruft packs */
911
- strvec_push (& prune , cfg .prune_expire );
993
+ strvec_push (& prune_cmd . args , cfg .prune_expire );
912
994
if (quiet )
913
- strvec_push (& prune , "--no-progress" );
995
+ strvec_push (& prune_cmd . args , "--no-progress" );
914
996
if (repo_has_promisor_remote (the_repository ))
915
- strvec_push (& prune ,
997
+ strvec_push (& prune_cmd . args ,
916
998
"--exclude-promisor-objects" );
917
999
prune_cmd .git_cmd = 1 ;
918
- strvec_pushv ( & prune_cmd . args , prune . v );
1000
+
919
1001
if (run_command (& prune_cmd ))
920
- die (FAILED_RUN , prune .v [0 ]);
1002
+ die (FAILED_RUN , prune_cmd . args .v [0 ]);
921
1003
}
922
1004
}
923
1005
924
- if (cfg .prune_worktrees_expire ) {
925
- struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT ;
926
-
927
- strvec_push (& prune_worktrees , cfg .prune_worktrees_expire );
928
- prune_worktrees_cmd .git_cmd = 1 ;
929
- strvec_pushv (& prune_worktrees_cmd .args , prune_worktrees .v );
930
- if (run_command (& prune_worktrees_cmd ))
931
- die (FAILED_RUN , prune_worktrees .v [0 ]);
932
- }
1006
+ if (cfg .prune_worktrees_expire &&
1007
+ maintenance_task_worktree_prune (& opts , & cfg ))
1008
+ die (FAILED_RUN , "worktree" );
933
1009
934
- rerere_cmd .git_cmd = 1 ;
935
- strvec_pushv (& rerere_cmd .args , rerere .v );
936
- if (run_command (& rerere_cmd ))
937
- die (FAILED_RUN , rerere .v [0 ]);
1010
+ if (maintenance_task_rerere_gc (& opts , & cfg ))
1011
+ die (FAILED_RUN , "rerere" );
938
1012
939
1013
report_garbage = report_pack_garbage ;
940
1014
reprepare_packed_git (the_repository );
@@ -1467,6 +1541,8 @@ enum maintenance_task_label {
1467
1541
TASK_COMMIT_GRAPH ,
1468
1542
TASK_PACK_REFS ,
1469
1543
TASK_REFLOG_EXPIRE ,
1544
+ TASK_WORKTREE_PRUNE ,
1545
+ TASK_RERERE_GC ,
1470
1546
1471
1547
/* Leave as final value */
1472
1548
TASK__COUNT
@@ -1508,6 +1584,16 @@ static struct maintenance_task tasks[] = {
1508
1584
maintenance_task_reflog_expire ,
1509
1585
reflog_expire_condition ,
1510
1586
},
1587
+ [TASK_WORKTREE_PRUNE ] = {
1588
+ "worktree-prune" ,
1589
+ maintenance_task_worktree_prune ,
1590
+ worktree_prune_condition ,
1591
+ },
1592
+ [TASK_RERERE_GC ] = {
1593
+ "rerere-gc" ,
1594
+ maintenance_task_rerere_gc ,
1595
+ rerere_gc_condition ,
1596
+ },
1511
1597
};
1512
1598
1513
1599
static int compare_tasks_by_selection (const void * a_ , const void * b_ )
0 commit comments