1535
1536
typedef int (*maintenance_task_fn)(struct maintenance_run_opts *opts,
1537
struct gc_config *cfg);
1538
-
1539
-/*
1540
- * An auto condition function returns 1 if the task should run
1541
- * and 0 if the task should NOT run. See needs_to_gc() for an
1542
- * example.
1543
- */
1538
typedef int (*maintenance_auto_fn)(struct gc_config *cfg);
1539
1540
struct maintenance_task {
1541
const char *name;
1548
- maintenance_task_fn fn;
1542
+
1543
+ /*
1544
+ * Work that will be executed before detaching. This should not include
1545
+ * tasks that may run for an extended amount of time as it does cause
1546
+ * auto-maintenance to block until foreground tasks have been run.
1547
+ */
1548
+ maintenance_task_fn foreground;
1549
+
1550
+ /*
1551
+ * Work that will be executed after detaching. When not detaching the
1552
+ * work will be run in the foreground, as well.
1553
+ */
1554
+ maintenance_task_fn background;
1555
+
1556
+ /*
1557
+ * An auto condition function returns 1 if the task should run and 0 if
1558
+ * the task should NOT run. See needs_to_gc() for an example.
1559
+ */
1560
maintenance_auto_fn auto_condition;
1561
};
1562
1563
static const struct maintenance_task tasks[] = {
1564
[TASK_PREFETCH] = {
1565
.name = "prefetch",
1555
- .fn = maintenance_task_prefetch,
1566
+ .background = maintenance_task_prefetch,
1567
},
1568
[TASK_LOOSE_OBJECTS] = {
1569
.name = "loose-objects",
1559
- .fn = maintenance_task_loose_objects,
1570
+ .background = maintenance_task_loose_objects,
1571
.auto_condition = loose_object_auto_condition,
1572
},
1573
[TASK_INCREMENTAL_REPACK] = {
1574
.name = "incremental-repack",
1564
- .fn = maintenance_task_incremental_repack,
1575
+ .background = maintenance_task_incremental_repack,
1576
.auto_condition = incremental_repack_auto_condition,
1577
},
1578
[TASK_GC] = {
1579
.name = "gc",
1569
- .fn = maintenance_task_gc,
1580
+ .background = maintenance_task_gc,
1581
.auto_condition = need_to_gc,
1582
},
1583
[TASK_COMMIT_GRAPH] = {
1584
.name = "commit-graph",
1574
- .fn = maintenance_task_commit_graph,
1585
+ .background = maintenance_task_commit_graph,
1586
.auto_condition = should_write_commit_graph,
1587
},
1588
[TASK_PACK_REFS] = {
1589
.name = "pack-refs",
1579
- .fn = maintenance_task_pack_refs,
1590
+ .background = maintenance_task_pack_refs,
1591
.auto_condition = pack_refs_condition,
1592
},
1593
[TASK_REFLOG_EXPIRE] = {
1594
.name = "reflog-expire",
1584
- .fn = maintenance_task_reflog_expire,
1595
+ .background = maintenance_task_reflog_expire,
1596
.auto_condition = reflog_expire_condition,
1597
},
1598
[TASK_WORKTREE_PRUNE] = {
1599
.name = "worktree-prune",
1589
- .fn = maintenance_task_worktree_prune,
1600
+ .background = maintenance_task_worktree_prune,
1601
.auto_condition = worktree_prune_condition,
1602
},
1603
[TASK_RERERE_GC] = {
1604
.name = "rerere-gc",
1594
- .fn = maintenance_task_rerere_gc,
1605
+ .background = maintenance_task_rerere_gc,
1606
.auto_condition = rerere_gc_condition,
1607
},
1608
};
1609
1610
+enum task_phase {
1611
+ TASK_PHASE_FOREGROUND,
1612
+ TASK_PHASE_BACKGROUND,
1613
+};
1614
+
1615
static int maybe_run_task(const struct maintenance_task *task,
1616
struct repository *repo,
1617
struct maintenance_run_opts *opts,
1602
- struct gc_config *cfg)
1618
+ struct gc_config *cfg,
1619
+ enum task_phase phase)
1620
{
1621
+ int foreground = (phase == TASK_PHASE_FOREGROUND);
1622
+ maintenance_task_fn fn = foreground ? task->foreground : task->background;
1623
+ const char *region = foreground ? "maintenance foreground" : "maintenance";
1624
int ret = 0;
1625
1626
+ if (!fn)
1627
+ return 0;
1628
if (opts->auto_flag &&
1629
(!task->auto_condition || !task->auto_condition(cfg)))
1630
return 0;
1631
1610
- trace2_region_enter("maintenance", task->name, repo);
1611
- if (task->fn(opts, cfg)) {
1632
+ trace2_region_enter(region, task->name, repo);
1633
+ if (fn(opts, cfg)) {
1634
error(_("task '%s' failed"), task->name);
1635
ret = 1;
1636
}
1615
- trace2_region_leave("maintenance", task->name, repo);
1637
+ trace2_region_leave(region, task->name, repo);
1638
1639
return ret;
1640
}
1663
}
1664
free(lock_path);
1665
1666
+ for (size_t i = 0; i < opts->tasks_nr; i++)
1667
+ if (maybe_run_task(&tasks[opts->tasks[i]], r, opts, cfg,
1668
+ TASK_PHASE_FOREGROUND))
1669
+ result = 1;
1670
+
1671
/* Failure to daemonize is ok, we'll continue in foreground. */
1672
if (opts->detach > 0) {
1673
trace2_region_enter("maintenance", "detach", the_repository);
1676
}
1677
1678
for (size_t i = 0; i < opts->tasks_nr; i++)
1652
- if (maybe_run_task(&tasks[opts->tasks[i]], r, opts, cfg))
1679
+ if (maybe_run_task(&tasks[opts->tasks[i]], r, opts, cfg,
1680
+ TASK_PHASE_BACKGROUND))
1681
result = 1;
1682
1683
rollback_lock_file(&lk);