@@ -251,7 +251,24 @@ static enum schedule_priority parse_schedule(const char *value)
251
251
return SCHEDULE_NONE ;
252
252
}
253
253
254
+ enum maintenance_task_label {
255
+ TASK_PREFETCH ,
256
+ TASK_LOOSE_OBJECTS ,
257
+ TASK_INCREMENTAL_REPACK ,
258
+ TASK_GC ,
259
+ TASK_COMMIT_GRAPH ,
260
+ TASK_PACK_REFS ,
261
+ TASK_REFLOG_EXPIRE ,
262
+ TASK_WORKTREE_PRUNE ,
263
+ TASK_RERERE_GC ,
264
+
265
+ /* Leave as final value */
266
+ TASK__COUNT
267
+ };
268
+
254
269
struct maintenance_run_opts {
270
+ enum maintenance_task_label * tasks ;
271
+ size_t tasks_nr , tasks_alloc ;
255
272
int auto_flag ;
256
273
int detach ;
257
274
int quiet ;
@@ -261,6 +278,11 @@ struct maintenance_run_opts {
261
278
.detach = -1, \
262
279
}
263
280
281
+ static void maintenance_run_opts_release (struct maintenance_run_opts * opts )
282
+ {
283
+ free (opts -> tasks );
284
+ }
285
+
264
286
static int pack_refs_condition (UNUSED struct gc_config * cfg )
265
287
{
266
288
/*
@@ -1032,6 +1054,7 @@ int cmd_gc(int argc,
1032
1054
}
1033
1055
1034
1056
out :
1057
+ maintenance_run_opts_release (& opts );
1035
1058
gc_config_release (& cfg );
1036
1059
return 0 ;
1037
1060
}
@@ -1524,30 +1547,9 @@ struct maintenance_task {
1524
1547
const char * name ;
1525
1548
maintenance_task_fn * fn ;
1526
1549
maintenance_auto_fn * auto_condition ;
1527
- unsigned enabled :1 ;
1528
-
1529
- enum schedule_priority schedule ;
1530
-
1531
- /* -1 if not selected. */
1532
- int selected_order ;
1533
- };
1534
-
1535
- enum maintenance_task_label {
1536
- TASK_PREFETCH ,
1537
- TASK_LOOSE_OBJECTS ,
1538
- TASK_INCREMENTAL_REPACK ,
1539
- TASK_GC ,
1540
- TASK_COMMIT_GRAPH ,
1541
- TASK_PACK_REFS ,
1542
- TASK_REFLOG_EXPIRE ,
1543
- TASK_WORKTREE_PRUNE ,
1544
- TASK_RERERE_GC ,
1545
-
1546
- /* Leave as final value */
1547
- TASK__COUNT
1548
1550
};
1549
1551
1550
- static struct maintenance_task tasks [] = {
1552
+ static const struct maintenance_task tasks [] = {
1551
1553
[TASK_PREFETCH ] = {
1552
1554
.name = "prefetch" ,
1553
1555
.fn = maintenance_task_prefetch ,
@@ -1566,7 +1568,6 @@ static struct maintenance_task tasks[] = {
1566
1568
.name = "gc" ,
1567
1569
.fn = maintenance_task_gc ,
1568
1570
.auto_condition = need_to_gc ,
1569
- .enabled = 1 ,
1570
1571
},
1571
1572
[TASK_COMMIT_GRAPH ] = {
1572
1573
.name = "commit-graph" ,
@@ -1595,18 +1596,9 @@ static struct maintenance_task tasks[] = {
1595
1596
},
1596
1597
};
1597
1598
1598
- static int compare_tasks_by_selection (const void * a_ , const void * b_ )
1599
- {
1600
- const struct maintenance_task * a = a_ ;
1601
- const struct maintenance_task * b = b_ ;
1602
-
1603
- return b -> selected_order - a -> selected_order ;
1604
- }
1605
-
1606
1599
static int maintenance_run_tasks (struct maintenance_run_opts * opts ,
1607
1600
struct gc_config * cfg )
1608
1601
{
1609
- int i , found_selected = 0 ;
1610
1602
int result = 0 ;
1611
1603
struct lock_file lk ;
1612
1604
struct repository * r = the_repository ;
@@ -1635,95 +1627,120 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts,
1635
1627
trace2_region_leave ("maintenance" , "detach" , the_repository );
1636
1628
}
1637
1629
1638
- for (i = 0 ; !found_selected && i < TASK__COUNT ; i ++ )
1639
- found_selected = tasks [i ].selected_order >= 0 ;
1640
-
1641
- if (found_selected )
1642
- QSORT (tasks , TASK__COUNT , compare_tasks_by_selection );
1643
-
1644
- for (i = 0 ; i < TASK__COUNT ; i ++ ) {
1645
- if (found_selected && tasks [i ].selected_order < 0 )
1646
- continue ;
1647
-
1648
- if (!found_selected && !tasks [i ].enabled )
1649
- continue ;
1650
-
1630
+ for (size_t i = 0 ; i < opts -> tasks_nr ; i ++ ) {
1651
1631
if (opts -> auto_flag &&
1652
- (!tasks [i ].auto_condition ||
1653
- !tasks [i ].auto_condition (cfg )))
1654
- continue ;
1655
-
1656
- if (opts -> schedule && tasks [i ].schedule < opts -> schedule )
1632
+ (!tasks [opts -> tasks [i ]].auto_condition ||
1633
+ !tasks [opts -> tasks [i ]].auto_condition (cfg )))
1657
1634
continue ;
1658
1635
1659
- trace2_region_enter ("maintenance" , tasks [i ].name , r );
1660
- if (tasks [i ].fn (opts , cfg )) {
1661
- error (_ ("task '%s' failed" ), tasks [i ].name );
1636
+ trace2_region_enter ("maintenance" , tasks [opts -> tasks [ i ] ].name , r );
1637
+ if (tasks [opts -> tasks [ i ] ].fn (opts , cfg )) {
1638
+ error (_ ("task '%s' failed" ), tasks [opts -> tasks [ i ] ].name );
1662
1639
result = 1 ;
1663
1640
}
1664
- trace2_region_leave ("maintenance" , tasks [i ].name , r );
1641
+ trace2_region_leave ("maintenance" , tasks [opts -> tasks [ i ] ].name , r );
1665
1642
}
1666
1643
1667
1644
rollback_lock_file (& lk );
1668
1645
return result ;
1669
1646
}
1670
1647
1671
- static void initialize_maintenance_strategy (void )
1648
+ struct maintenance_strategy {
1649
+ struct {
1650
+ int enabled ;
1651
+ enum schedule_priority schedule ;
1652
+ } tasks [TASK__COUNT ];
1653
+ };
1654
+
1655
+ static const struct maintenance_strategy none_strategy = { 0 };
1656
+ static const struct maintenance_strategy default_strategy = {
1657
+ .tasks = {
1658
+ [TASK_GC ].enabled = 1 ,
1659
+ },
1660
+ };
1661
+ static const struct maintenance_strategy incremental_strategy = {
1662
+ .tasks = {
1663
+ [TASK_COMMIT_GRAPH ].enabled = 1 ,
1664
+ [TASK_COMMIT_GRAPH ].schedule = SCHEDULE_HOURLY ,
1665
+ [TASK_PREFETCH ].enabled = 1 ,
1666
+ [TASK_PREFETCH ].schedule = SCHEDULE_HOURLY ,
1667
+ [TASK_INCREMENTAL_REPACK ].enabled = 1 ,
1668
+ [TASK_INCREMENTAL_REPACK ].schedule = SCHEDULE_DAILY ,
1669
+ [TASK_LOOSE_OBJECTS ].enabled = 1 ,
1670
+ [TASK_LOOSE_OBJECTS ].schedule = SCHEDULE_DAILY ,
1671
+ [TASK_PACK_REFS ].enabled = 1 ,
1672
+ [TASK_PACK_REFS ].schedule = SCHEDULE_WEEKLY ,
1673
+ },
1674
+ };
1675
+
1676
+ static void initialize_task_config (struct maintenance_run_opts * opts ,
1677
+ const struct string_list * selected_tasks )
1672
1678
{
1679
+ struct strbuf config_name = STRBUF_INIT ;
1680
+ struct maintenance_strategy strategy ;
1673
1681
const char * config_str ;
1674
1682
1675
- if (git_config_get_string_tmp ("maintenance.strategy" , & config_str ))
1676
- return ;
1683
+ /*
1684
+ * In case the user has asked us to run tasks explicitly we only use
1685
+ * those specified tasks. Specifically, we do _not_ want to consult the
1686
+ * config or maintenance strategy.
1687
+ */
1688
+ if (selected_tasks -> nr ) {
1689
+ for (size_t i = 0 ; i < selected_tasks -> nr ; i ++ ) {
1690
+ enum maintenance_task_label label = (intptr_t )selected_tasks -> items [i ].util ;;
1691
+ ALLOC_GROW (opts -> tasks , opts -> tasks_nr + 1 , opts -> tasks_alloc );
1692
+ opts -> tasks [opts -> tasks_nr ++ ] = label ;
1693
+ }
1677
1694
1678
- if (!strcasecmp (config_str , "incremental" )) {
1679
- tasks [TASK_GC ].schedule = SCHEDULE_NONE ;
1680
- tasks [TASK_COMMIT_GRAPH ].enabled = 1 ;
1681
- tasks [TASK_COMMIT_GRAPH ].schedule = SCHEDULE_HOURLY ;
1682
- tasks [TASK_PREFETCH ].enabled = 1 ;
1683
- tasks [TASK_PREFETCH ].schedule = SCHEDULE_HOURLY ;
1684
- tasks [TASK_INCREMENTAL_REPACK ].enabled = 1 ;
1685
- tasks [TASK_INCREMENTAL_REPACK ].schedule = SCHEDULE_DAILY ;
1686
- tasks [TASK_LOOSE_OBJECTS ].enabled = 1 ;
1687
- tasks [TASK_LOOSE_OBJECTS ].schedule = SCHEDULE_DAILY ;
1688
- tasks [TASK_PACK_REFS ].enabled = 1 ;
1689
- tasks [TASK_PACK_REFS ].schedule = SCHEDULE_WEEKLY ;
1695
+ return ;
1690
1696
}
1691
- }
1692
1697
1693
- static void initialize_task_config (const struct string_list * selected_tasks ,
1694
- int schedule )
1695
- {
1696
- struct strbuf config_name = STRBUF_INIT ;
1698
+ /*
1699
+ * Otherwise, the strategy depends on whether we run as part of a
1700
+ * scheduled job or not:
1701
+ *
1702
+ * - Scheduled maintenance does not perform any housekeeping by
1703
+ * default, but requires the user to pick a maintenance strategy.
1704
+ *
1705
+ * - Unscheduled maintenance uses our default strategy.
1706
+ *
1707
+ * Both of these are affected by the gitconfig though, which may
1708
+ * override specific aspects of our strategy.
1709
+ */
1710
+ if (opts -> schedule ) {
1711
+ strategy = none_strategy ;
1697
1712
1698
- for (size_t i = 0 ; i < TASK__COUNT ; i ++ )
1699
- tasks [i ].selected_order = -1 ;
1700
- for (size_t i = 0 ; i < selected_tasks -> nr ; i ++ ) {
1701
- struct maintenance_task * task = selected_tasks -> items [i ].util ;
1702
- task -> selected_order = i ;
1713
+ if (!git_config_get_string_tmp ("maintenance.strategy" , & config_str )) {
1714
+ if (!strcasecmp (config_str , "incremental" ))
1715
+ strategy = incremental_strategy ;
1716
+ }
1717
+ } else {
1718
+ strategy = default_strategy ;
1703
1719
}
1704
1720
1705
- if (schedule )
1706
- initialize_maintenance_strategy ();
1707
-
1708
1721
for (size_t i = 0 ; i < TASK__COUNT ; i ++ ) {
1709
1722
int config_value ;
1710
- char * config_str ;
1711
1723
1712
1724
strbuf_reset (& config_name );
1713
1725
strbuf_addf (& config_name , "maintenance.%s.enabled" ,
1714
1726
tasks [i ].name );
1715
-
1716
1727
if (!git_config_get_bool (config_name .buf , & config_value ))
1717
- tasks [i ].enabled = config_value ;
1718
-
1719
- strbuf_reset (& config_name );
1720
- strbuf_addf (& config_name , "maintenance.%s.schedule" ,
1721
- tasks [i ].name );
1728
+ strategy .tasks [i ].enabled = config_value ;
1729
+ if (!strategy .tasks [i ].enabled )
1730
+ continue ;
1722
1731
1723
- if (!git_config_get_string (config_name .buf , & config_str )) {
1724
- tasks [i ].schedule = parse_schedule (config_str );
1725
- free (config_str );
1732
+ if (opts -> schedule ) {
1733
+ strbuf_reset (& config_name );
1734
+ strbuf_addf (& config_name , "maintenance.%s.schedule" ,
1735
+ tasks [i ].name );
1736
+ if (!git_config_get_string_tmp (config_name .buf , & config_str ))
1737
+ strategy .tasks [i ].schedule = parse_schedule (config_str );
1738
+ if (strategy .tasks [i ].schedule < opts -> schedule )
1739
+ continue ;
1726
1740
}
1741
+
1742
+ ALLOC_GROW (opts -> tasks , opts -> tasks_nr + 1 , opts -> tasks_alloc );
1743
+ opts -> tasks [opts -> tasks_nr ++ ] = i ;
1727
1744
}
1728
1745
1729
1746
strbuf_release (& config_name );
@@ -1750,7 +1767,7 @@ static int task_option_parse(const struct option *opt,
1750
1767
return 1 ;
1751
1768
}
1752
1769
1753
- string_list_append (selected_tasks , arg )-> util = & tasks [ i ] ;
1770
+ string_list_append (selected_tasks , arg )-> util = ( void * )( intptr_t ) i ;
1754
1771
1755
1772
return 0 ;
1756
1773
}
@@ -1791,7 +1808,7 @@ static int maintenance_run(int argc, const char **argv, const char *prefix,
1791
1808
opts .schedule , "--schedule=" );
1792
1809
1793
1810
gc_config (& cfg );
1794
- initialize_task_config (& selected_tasks , opts . schedule );
1811
+ initialize_task_config (& opts , & selected_tasks );
1795
1812
1796
1813
if (argc != 0 )
1797
1814
usage_with_options (builtin_maintenance_run_usage ,
@@ -1800,6 +1817,7 @@ static int maintenance_run(int argc, const char **argv, const char *prefix,
1800
1817
ret = maintenance_run_tasks (& opts , & cfg );
1801
1818
1802
1819
string_list_clear (& selected_tasks , 0 );
1820
+ maintenance_run_opts_release (& opts );
1803
1821
gc_config_release (& cfg );
1804
1822
return ret ;
1805
1823
}
0 commit comments