1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Untracked/secret file sync config shape + resolution (#2196).
//!
//! Why: split out of `trusty_tools_config.rs` so that file stays under the
//! 500-SLOC production cap (mirrors how `GithubConfig`/`WatchConfig` stay
//! inline but this section, with its resolver function and tests, pushed the
//! parent over the limit). Kept as a sibling module rather than a separate
//! top-level file so `TrustyToolsConfig`/`ProjectConfig` and this section's
//! types stay conceptually one config surface.
//! What: [`UntrackedSyncConfig`] is the on-disk shape (global `untracked_sync:`
//! section or per-project `projects[].untracked_sync` override);
//! [`DEFAULT_UNTRACKED_SYNC_PATTERNS`] is the built-in `.env*` allowlist;
//! [`resolve_untracked_sync`] turns the three precedence tiers (per-project >
//! global > default) into one concrete [`ResolvedUntrackedSync`] per spawn.
//! Test: `tests` submodule.
use ;
use TrustyToolsConfig;
/// Built-in default allowlist patterns for untracked/secret file sync (#2196).
///
/// Why: the dominant real-world need is `.env` files (`.env`, `.env.local`,
/// per-environment variants like `.env.production`), so an unset config must
/// still sync them — "operator does nothing" stays the north-star default.
/// What: `[".env", ".env.local", ".env.*"]`. `.env.*` is a prefix-glob
/// covering per-environment variants without also matching unrelated names.
/// Test: `tests::resolve_untracked_sync_defaults_when_unset`.
pub const DEFAULT_UNTRACKED_SYNC_PATTERNS: & = &;
/// The `untracked_sync:` section of `~/.trusty-tools/trusty-mpm/config.yaml`
/// (global) or a `projects[].untracked_sync` override (per-project), #2196.
///
/// Why: operators who use a live checkout with `.env`/secret files expect
/// those files to be present in the per-session worktree too (managed
/// sessions never copy uncommitted/untracked files by default). This section
/// lets an operator declare the sync allowlist and toggle declaratively,
/// mirroring the `GithubConfig`/`WatchConfig` optional-section convention so
/// an absent section is fully backward-compatible.
/// What: `patterns` — an allowlist of filename patterns (see
/// [`resolve_untracked_sync`] for resolution precedence and the built-in
/// default); `enabled` — `None`/`Some(true)` syncs, `Some(false)` disables
/// sync entirely for the scope this section applies to.
/// Test: `tests::untracked_sync_config_yaml_round_trip`,
/// `tests::resolve_untracked_sync_project_overrides_global`.
/// The resolved untracked-sync allowlist + enabled flag for one spawn (#2196).
///
/// Why: [`sync_untracked_files`](crate::daemon::managed_routes::inproject::untracked_sync::sync_untracked_files)
/// needs a single concrete `(patterns, enabled)` pair per spawn; bundling the
/// resolution result in one struct keeps the precedence-resolution call site
/// (`lifecycle::reserve_inproject_worktree`) a one-liner.
/// What: `patterns` is never empty (falls back to
/// [`DEFAULT_UNTRACKED_SYNC_PATTERNS`]); `enabled` defaults to `true`.
/// Test: covered by the `resolve_untracked_sync_*` tests below.
/// Resolve the untracked-sync allowlist + enabled flag for a project (#2196).
///
/// Why: an operator may declare patterns/enabled globally, per-project, or
/// not at all — this is the single place that turns those three tiers into
/// one concrete answer, so every call site (currently
/// `lifecycle::reserve_inproject_worktree`) agrees.
/// What: precedence is **per-project `patterns`/`enabled` (matched by
/// `repo_name` against `ProjectConfig::name`) > global
/// `config.untracked_sync` > built-in default** (`enabled = true`,
/// `patterns = `[`DEFAULT_UNTRACKED_SYNC_PATTERNS`]). `patterns` and
/// `enabled` resolve INDEPENDENTLY — e.g. a project may override only
/// `enabled` while inheriting the global `patterns`. `repo_name = None`
/// (no repo identity available) skips the per-project tier entirely.
/// Test: `tests::resolve_untracked_sync_defaults_when_unset`,
/// `tests::resolve_untracked_sync_global_overrides_default`,
/// `tests::resolve_untracked_sync_project_overrides_global`,
/// `tests::resolve_untracked_sync_disabled_by_project`.