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,99 @@ 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 strvec worktrees = STRVEC_INIT ;
354
+ struct strbuf reason = STRBUF_INIT ;
355
+ timestamp_t expiry_date ;
356
+ int should_prune = 0 ;
357
+ int limit = 1 ;
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
+ get_worktree_names (the_repository , & worktrees ) < 0 )
367
+ goto out ;
368
+
369
+ for (size_t i = 0 ; i < worktrees .nr ; i ++ ) {
370
+ char * wtpath ;
371
+
372
+ strbuf_reset (& reason );
373
+ if (should_prune_worktree (worktrees .v [i ], & reason , & wtpath , expiry_date )) {
374
+ limit -- ;
375
+
376
+ if (!limit ) {
377
+ should_prune = 1 ;
378
+ goto out ;
379
+ }
380
+ }
381
+ free (wtpath );
382
+ }
383
+
384
+ out :
385
+ strvec_clear (& worktrees );
386
+ strbuf_release (& reason );
387
+ return should_prune ;
388
+ }
389
+
390
+ static int maintenance_task_rerere_gc (struct maintenance_run_opts * opts UNUSED ,
391
+ struct gc_config * cfg UNUSED )
392
+ {
393
+ struct child_process rerere_cmd = CHILD_PROCESS_INIT ;
394
+ rerere_cmd .git_cmd = 1 ;
395
+ strvec_pushl (& rerere_cmd .args , "rerere" , "gc" , NULL );
396
+ return run_command (& rerere_cmd );
397
+ }
398
+
399
+ static int rerere_gc_condition (struct gc_config * cfg UNUSED )
400
+ {
401
+ struct strbuf path = STRBUF_INIT ;
402
+ struct string_list prunable_dirs = STRING_LIST_INIT_DUP ;
403
+ struct rerere_id * prunable_entries = NULL ;
404
+ size_t prunable_entries_nr ;
405
+ int should_gc = 0 ;
406
+ int limit = 20 ;
407
+
408
+ git_config_get_int ("maintenance.rerere-gc.auto" , & limit );
409
+ if (limit <= 0 ) {
410
+ should_gc = limit < 0 ;
411
+ goto out ;
412
+ }
413
+
414
+ /* Skip garbage collecting the rerere cache in case rerere is disabled. */
415
+ repo_git_path_replace (the_repository , & path , "rr-cache" );
416
+ if (!is_directory (path .buf ))
417
+ goto out ;
418
+
419
+ if (rerere_collect_stale_entries (the_repository , & prunable_dirs ,
420
+ & prunable_entries , & prunable_entries_nr ) < 0 )
421
+ goto out ;
422
+
423
+ should_gc = prunable_entries_nr >= limit ;
424
+
425
+ out :
426
+ string_list_clear (& prunable_dirs , 0 );
427
+ free (prunable_entries );
428
+ strbuf_release (& path );
429
+ return should_gc ;
430
+ }
431
+
342
432
static int too_many_loose_objects (struct gc_config * cfg )
343
433
{
344
434
/*
@@ -728,9 +818,9 @@ static void gc_before_repack(struct maintenance_run_opts *opts,
728
818
}
729
819
730
820
int cmd_gc (int argc ,
731
- const char * * argv ,
732
- const char * prefix ,
733
- struct repository * repo UNUSED )
821
+ const char * * argv ,
822
+ const char * prefix ,
823
+ struct repository * repo UNUSED )
734
824
{
735
825
int aggressive = 0 ;
736
826
int quiet = 0 ;
@@ -740,7 +830,6 @@ struct repository *repo UNUSED)
740
830
int daemonized = 0 ;
741
831
int keep_largest_pack = -1 ;
742
832
timestamp_t dummy ;
743
- struct child_process rerere_cmd = CHILD_PROCESS_INIT ;
744
833
struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT ;
745
834
struct gc_config cfg = GC_CONFIG_INIT ;
746
835
const char * prune_expire_sentinel = "sentinel" ;
@@ -779,9 +868,6 @@ struct repository *repo UNUSED)
779
868
builtin_gc_usage , builtin_gc_options );
780
869
781
870
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
871
786
872
gc_config (& cfg );
787
873
@@ -907,34 +993,27 @@ struct repository *repo UNUSED)
907
993
if (cfg .prune_expire ) {
908
994
struct child_process prune_cmd = CHILD_PROCESS_INIT ;
909
995
996
+ strvec_pushl (& prune_cmd .args , "prune" , "--expire" , NULL );
910
997
/* run `git prune` even if using cruft packs */
911
- strvec_push (& prune , cfg .prune_expire );
998
+ strvec_push (& prune_cmd . args , cfg .prune_expire );
912
999
if (quiet )
913
- strvec_push (& prune , "--no-progress" );
1000
+ strvec_push (& prune_cmd . args , "--no-progress" );
914
1001
if (repo_has_promisor_remote (the_repository ))
915
- strvec_push (& prune ,
1002
+ strvec_push (& prune_cmd . args ,
916
1003
"--exclude-promisor-objects" );
917
1004
prune_cmd .git_cmd = 1 ;
918
- strvec_pushv ( & prune_cmd . args , prune . v );
1005
+
919
1006
if (run_command (& prune_cmd ))
920
- die (FAILED_RUN , prune .v [0 ]);
1007
+ die (FAILED_RUN , prune_cmd . args .v [0 ]);
921
1008
}
922
1009
}
923
1010
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
- }
1011
+ if (cfg .prune_worktrees_expire &&
1012
+ maintenance_task_worktree_prune (& opts , & cfg ))
1013
+ die (FAILED_RUN , "worktree" );
933
1014
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 ]);
1015
+ if (maintenance_task_rerere_gc (& opts , & cfg ))
1016
+ die (FAILED_RUN , "rerere" );
938
1017
939
1018
report_garbage = report_pack_garbage ;
940
1019
reprepare_packed_git (the_repository );
@@ -1467,6 +1546,8 @@ enum maintenance_task_label {
1467
1546
TASK_COMMIT_GRAPH ,
1468
1547
TASK_PACK_REFS ,
1469
1548
TASK_REFLOG_EXPIRE ,
1549
+ TASK_WORKTREE_PRUNE ,
1550
+ TASK_RERERE_GC ,
1470
1551
1471
1552
/* Leave as final value */
1472
1553
TASK__COUNT
@@ -1508,6 +1589,16 @@ static struct maintenance_task tasks[] = {
1508
1589
maintenance_task_reflog_expire ,
1509
1590
reflog_expire_condition ,
1510
1591
},
1592
+ [TASK_WORKTREE_PRUNE ] = {
1593
+ "worktree-prune" ,
1594
+ maintenance_task_worktree_prune ,
1595
+ worktree_prune_condition ,
1596
+ },
1597
+ [TASK_RERERE_GC ] = {
1598
+ "rerere-gc" ,
1599
+ maintenance_task_rerere_gc ,
1600
+ rerere_gc_condition ,
1601
+ },
1511
1602
};
1512
1603
1513
1604
static int compare_tasks_by_selection (const void * a_ , const void * b_ )
0 commit comments