atagen

roundabout

public
Star0
Watch0
4e5ca2e2040139a56cdd8bc50993e0f82ceab09a
1
ssh://brewery@pls.lobotomise.me:33/atagen/roundabout.git

Blame: src/config.rs

6f5b84fad3efatagen2026-09-27 03:59 UTC1
use std::{collections::BTreeMap, fs, path::PathBuf};
6f5b84fad3efatagen2026-09-27 03:59 UTC2
6f5b84fad3efatagen2026-09-27 03:59 UTC3
use serde::Deserialize;
6f5b84fad3efatagen2026-09-27 03:59 UTC4
6f5b84fad3efatagen2026-09-27 03:59 UTC5
use crate::{
6f5b84fad3efatagen2026-09-27 03:59 UTC6
    paths,
6f5b84fad3efatagen2026-09-27 03:59 UTC7
    units::{Amount, Bytes, Dur},
6f5b84fad3efatagen2026-09-27 03:59 UTC8
};
6f5b84fad3efatagen2026-09-27 03:59 UTC9
6f5b84fad3efatagen2026-09-27 03:59 UTC10
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC11
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC12
pub struct Config {
6f5b84fad3efatagen2026-09-27 03:59 UTC13
    pub budget: Budget,
6f5b84fad3efatagen2026-09-27 03:59 UTC14
    pub heavy: Heavy,
6f5b84fad3efatagen2026-09-27 03:59 UTC15
    pub sizes: BTreeMap<String, Preset>,
6f5b84fad3efatagen2026-09-27 03:59 UTC16
    pub queue: Queue,
6f5b84fad3efatagen2026-09-27 03:59 UTC17
    pub overrun: Overrun,
6f5b84fad3efatagen2026-09-27 03:59 UTC18
    pub enforce: Enforce,
6f5b84fad3efatagen2026-09-27 03:59 UTC19
    pub artifacts: Artifacts,
6f5b84fad3efatagen2026-09-27 03:59 UTC20
    pub nix: Nix,
6f5b84fad3efatagen2026-09-27 03:59 UTC21
    pub detect: Detect,
6f5b84fad3efatagen2026-09-27 03:59 UTC22
}
6f5b84fad3efatagen2026-09-27 03:59 UTC23
6f5b84fad3efatagen2026-09-27 03:59 UTC24
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC25
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC26
pub struct Budget {
6f5b84fad3efatagen2026-09-27 03:59 UTC27
    pub ram: Amount<Bytes>,
6f5b84fad3efatagen2026-09-27 03:59 UTC28
    pub ram_reserve: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC29
    pub cores: Amount<u32>,
6f5b84fad3efatagen2026-09-27 03:59 UTC30
    pub disk_reserve: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC31
    /// every lease's disk estimate is charged to all of these as well as its
6f5b84fad3efatagen2026-09-27 03:59 UTC32
    /// cwd. pessimistic when they share a fs, which is the point
6f5b84fad3efatagen2026-09-27 03:59 UTC33
    pub disk_paths: Vec<PathBuf>,
6f5b84fad3efatagen2026-09-27 03:59 UTC34
    /// memory psi `some avg10`. only gates heavies
6f5b84fad3efatagen2026-09-27 03:59 UTC35
    pub psi_max: Option<f64>,
6f5b84fad3efatagen2026-09-27 03:59 UTC36
}
6f5b84fad3efatagen2026-09-27 03:59 UTC37
6f5b84fad3efatagen2026-09-27 03:59 UTC38
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC39
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC40
pub struct Heavy {
6f5b84fad3efatagen2026-09-27 03:59 UTC41
    pub ram: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC42
    pub cores: Amount<u32>,
6f5b84fad3efatagen2026-09-27 03:59 UTC43
    pub disk: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC44
}
6f5b84fad3efatagen2026-09-27 03:59 UTC45
6f5b84fad3efatagen2026-09-27 03:59 UTC46
#[derive(Clone, Copy, Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC47
#[serde(deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC48
pub struct Preset {
6f5b84fad3efatagen2026-09-27 03:59 UTC49
    pub ram: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC50
    pub disk: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC51
    pub cores: Amount<u32>,
6f5b84fad3efatagen2026-09-27 03:59 UTC52
    pub time: Dur,
6f5b84fad3efatagen2026-09-27 03:59 UTC53
}
6f5b84fad3efatagen2026-09-27 03:59 UTC54
6f5b84fad3efatagen2026-09-27 03:59 UTC55
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC56
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC57
pub struct Queue {
6f5b84fad3efatagen2026-09-27 03:59 UTC58
    pub linger: Dur,
6f5b84fad3efatagen2026-09-27 03:59 UTC59
    pub backfill_max_time: Dur,
6f5b84fad3efatagen2026-09-27 03:59 UTC60
    pub max_wait: Option<Dur>,
ecc1cf8df0f5atagen2026-09-27 13:36 UTC61
    pub elastic: bool,
ecc1cf8df0f5atagen2026-09-27 13:36 UTC62
    pub intent_ttl: Dur,
6f5b84fad3efatagen2026-09-27 03:59 UTC63
}
6f5b84fad3efatagen2026-09-27 03:59 UTC64
6f5b84fad3efatagen2026-09-27 03:59 UTC65
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC66
#[serde(rename_all = "lowercase")]
6f5b84fad3efatagen2026-09-27 03:59 UTC67
pub enum RamOverrun {
6f5b84fad3efatagen2026-09-27 03:59 UTC68
    Warn,
6f5b84fad3efatagen2026-09-27 03:59 UTC69
    Throttle,
6f5b84fad3efatagen2026-09-27 03:59 UTC70
}
6f5b84fad3efatagen2026-09-27 03:59 UTC71
6f5b84fad3efatagen2026-09-27 03:59 UTC72
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC73
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC74
pub struct Overrun {
6f5b84fad3efatagen2026-09-27 03:59 UTC75
    pub ram: RamOverrun,
6f5b84fad3efatagen2026-09-27 03:59 UTC76
    /// multiple of the ram estimate
6f5b84fad3efatagen2026-09-27 03:59 UTC77
    pub ram_slack: f64,
6f5b84fad3efatagen2026-09-27 03:59 UTC78
    /// multiple of the time estimate
6f5b84fad3efatagen2026-09-27 03:59 UTC79
    pub time_grace: f64,
6f5b84fad3efatagen2026-09-27 03:59 UTC80
    pub remind_every: Dur,
6f5b84fad3efatagen2026-09-27 03:59 UTC81
}
6f5b84fad3efatagen2026-09-27 03:59 UTC82
6f5b84fad3efatagen2026-09-27 03:59 UTC83
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC84
#[serde(rename_all = "lowercase")]
6f5b84fad3efatagen2026-09-27 03:59 UTC85
pub enum Unwrapped {
6f5b84fad3efatagen2026-09-27 03:59 UTC86
    Deny,
6f5b84fad3efatagen2026-09-27 03:59 UTC87
    Wrap,
6f5b84fad3efatagen2026-09-27 03:59 UTC88
    Allow,
6f5b84fad3efatagen2026-09-27 03:59 UTC89
}
6f5b84fad3efatagen2026-09-27 03:59 UTC90
6f5b84fad3efatagen2026-09-27 03:59 UTC91
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC92
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC93
pub struct Enforce {
6f5b84fad3efatagen2026-09-27 03:59 UTC94
    pub unwrapped: Unwrapped,
6f5b84fad3efatagen2026-09-27 03:59 UTC95
    pub default_size: String,
6f5b84fad3efatagen2026-09-27 03:59 UTC96
}
6f5b84fad3efatagen2026-09-27 03:59 UTC97
6f5b84fad3efatagen2026-09-27 03:59 UTC98
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC99
#[serde(rename_all = "lowercase")]
6f5b84fad3efatagen2026-09-27 03:59 UTC100
pub enum OverCap {
6f5b84fad3efatagen2026-09-27 03:59 UTC101
    Warn,
6f5b84fad3efatagen2026-09-27 03:59 UTC102
    Block,
6f5b84fad3efatagen2026-09-27 03:59 UTC103
}
6f5b84fad3efatagen2026-09-27 03:59 UTC104
6f5b84fad3efatagen2026-09-27 03:59 UTC105
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC106
#[serde(rename_all = "lowercase")]
6f5b84fad3efatagen2026-09-27 03:59 UTC107
pub enum StopPolicy {
6f5b84fad3efatagen2026-09-27 03:59 UTC108
    Block,
6f5b84fad3efatagen2026-09-27 03:59 UTC109
    Nudge,
6f5b84fad3efatagen2026-09-27 03:59 UTC110
    Warn,
6f5b84fad3efatagen2026-09-27 03:59 UTC111
    Off,
6f5b84fad3efatagen2026-09-27 03:59 UTC112
}
6f5b84fad3efatagen2026-09-27 03:59 UTC113
6f5b84fad3efatagen2026-09-27 03:59 UTC114
#[derive(Clone, Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC115
#[serde(deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC116
pub struct Rule {
6f5b84fad3efatagen2026-09-27 03:59 UTC117
    /// trailing `*` for a prefix match, that's all the glob you get
6f5b84fad3efatagen2026-09-27 03:59 UTC118
    pub name: String,
6f5b84fad3efatagen2026-09-27 03:59 UTC119
    /// sibling that must exist, so we don't go deleting someone's `build/`
6f5b84fad3efatagen2026-09-27 03:59 UTC120
    /// because it had a suggestive name
6f5b84fad3efatagen2026-09-27 03:59 UTC121
    pub marker: Option<String>,
6f5b84fad3efatagen2026-09-27 03:59 UTC122
    pub clean: Option<Vec<String>>,
6f5b84fad3efatagen2026-09-27 03:59 UTC123
}
6f5b84fad3efatagen2026-09-27 03:59 UTC124
6f5b84fad3efatagen2026-09-27 03:59 UTC125
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC126
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC127
pub struct Artifacts {
6f5b84fad3efatagen2026-09-27 03:59 UTC128
    pub project_cap: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC129
    pub global_cap: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC130
    pub idle_after: Dur,
6f5b84fad3efatagen2026-09-27 03:59 UTC131
    pub size_ttl: Dur,
6f5b84fad3efatagen2026-09-27 03:59 UTC132
    pub over_cap: OverCap,
6f5b84fad3efatagen2026-09-27 03:59 UTC133
    pub stop: StopPolicy,
6f5b84fad3efatagen2026-09-27 03:59 UTC134
    pub rules: Vec<Rule>,
6f5b84fad3efatagen2026-09-27 03:59 UTC135
    pub extra_rules: Vec<Rule>,
6f5b84fad3efatagen2026-09-27 03:59 UTC136
    pub nix_gc: bool,
6f5b84fad3efatagen2026-09-27 03:59 UTC137
    pub nix_min_free: Bytes,
6f5b84fad3efatagen2026-09-27 03:59 UTC138
}
6f5b84fad3efatagen2026-09-27 03:59 UTC139
6f5b84fad3efatagen2026-09-27 03:59 UTC140
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC141
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC142
pub struct Nix {
6f5b84fad3efatagen2026-09-27 03:59 UTC143
    pub inject: bool,
6f5b84fad3efatagen2026-09-27 03:59 UTC144
    pub cores_per_job: u32,
6f5b84fad3efatagen2026-09-27 03:59 UTC145
}
6f5b84fad3efatagen2026-09-27 03:59 UTC146
6f5b84fad3efatagen2026-09-27 03:59 UTC147
#[derive(Debug, Deserialize)]
6f5b84fad3efatagen2026-09-27 03:59 UTC148
#[serde(default, deny_unknown_fields)]
6f5b84fad3efatagen2026-09-27 03:59 UTC149
pub struct Detect {
6f5b84fad3efatagen2026-09-27 03:59 UTC150
    pub commands: Vec<String>,
6f5b84fad3efatagen2026-09-27 03:59 UTC151
    pub extra: Vec<String>,
6f5b84fad3efatagen2026-09-27 03:59 UTC152
}
6f5b84fad3efatagen2026-09-27 03:59 UTC153
6f5b84fad3efatagen2026-09-27 03:59 UTC154
impl Default for Config {
6f5b84fad3efatagen2026-09-27 03:59 UTC155
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC156
        let preset = |ram, disk, cores: &str, time| Preset {
6f5b84fad3efatagen2026-09-27 03:59 UTC157
            ram,
6f5b84fad3efatagen2026-09-27 03:59 UTC158
            disk,
6f5b84fad3efatagen2026-09-27 03:59 UTC159
            cores: cores.parse().unwrap_or(Amount::Abs(1)),
6f5b84fad3efatagen2026-09-27 03:59 UTC160
            time: Dur::secs(time),
6f5b84fad3efatagen2026-09-27 03:59 UTC161
        };
6f5b84fad3efatagen2026-09-27 03:59 UTC162
        let sizes = BTreeMap::from([
6f5b84fad3efatagen2026-09-27 03:59 UTC163
            (
6f5b84fad3efatagen2026-09-27 03:59 UTC164
                "s".into(),
6f5b84fad3efatagen2026-09-27 03:59 UTC165
                preset(Bytes::mib(512), Bytes::mib(256), "1", 60),
6f5b84fad3efatagen2026-09-27 03:59 UTC166
            ),
6f5b84fad3efatagen2026-09-27 03:59 UTC167
            ("m".into(), preset(Bytes::gib(2), Bytes::gib(1), "4", 300)),
6f5b84fad3efatagen2026-09-27 03:59 UTC168
            ("l".into(), preset(Bytes::gib(6), Bytes::gib(5), "50%", 900)),
6f5b84fad3efatagen2026-09-27 03:59 UTC169
            (
6f5b84fad3efatagen2026-09-27 03:59 UTC170
                "xl".into(),
6f5b84fad3efatagen2026-09-27 03:59 UTC171
                preset(Bytes::gib(12), Bytes::gib(20), "100%", 2700),
6f5b84fad3efatagen2026-09-27 03:59 UTC172
            ),
6f5b84fad3efatagen2026-09-27 03:59 UTC173
        ]);
6f5b84fad3efatagen2026-09-27 03:59 UTC174
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC175
            budget: Budget::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC176
            heavy: Heavy::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC177
            sizes,
6f5b84fad3efatagen2026-09-27 03:59 UTC178
            queue: Queue::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC179
            overrun: Overrun::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC180
            enforce: Enforce::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC181
            artifacts: Artifacts::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC182
            nix: Nix::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC183
            detect: Detect::default(),
6f5b84fad3efatagen2026-09-27 03:59 UTC184
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC185
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC186
}
6f5b84fad3efatagen2026-09-27 03:59 UTC187
6f5b84fad3efatagen2026-09-27 03:59 UTC188
impl Default for Budget {
6f5b84fad3efatagen2026-09-27 03:59 UTC189
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC190
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC191
            ram: Amount::Percent(75.0),
6f5b84fad3efatagen2026-09-27 03:59 UTC192
            ram_reserve: Bytes::gib(4),
6f5b84fad3efatagen2026-09-27 03:59 UTC193
            cores: Amount::Percent(100.0),
6f5b84fad3efatagen2026-09-27 03:59 UTC194
            disk_reserve: Bytes::gib(20),
6f5b84fad3efatagen2026-09-27 03:59 UTC195
            disk_paths: vec!["/nix/store".into()],
6f5b84fad3efatagen2026-09-27 03:59 UTC196
            psi_max: Some(40.0),
6f5b84fad3efatagen2026-09-27 03:59 UTC197
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC198
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC199
}
6f5b84fad3efatagen2026-09-27 03:59 UTC200
6f5b84fad3efatagen2026-09-27 03:59 UTC201
impl Default for Heavy {
6f5b84fad3efatagen2026-09-27 03:59 UTC202
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC203
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC204
            ram: Bytes::gib(4),
6f5b84fad3efatagen2026-09-27 03:59 UTC205
            cores: Amount::Percent(50.0),
6f5b84fad3efatagen2026-09-27 03:59 UTC206
            disk: Bytes::gib(5),
6f5b84fad3efatagen2026-09-27 03:59 UTC207
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC208
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC209
}
6f5b84fad3efatagen2026-09-27 03:59 UTC210
6f5b84fad3efatagen2026-09-27 03:59 UTC211
impl Default for Queue {
6f5b84fad3efatagen2026-09-27 03:59 UTC212
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC213
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC214
            linger: Dur::secs(5),
6f5b84fad3efatagen2026-09-27 03:59 UTC215
            backfill_max_time: Dur::secs(120),
6f5b84fad3efatagen2026-09-27 03:59 UTC216
            max_wait: None,
ecc1cf8df0f5atagen2026-09-27 13:36 UTC217
            elastic: true,
ecc1cf8df0f5atagen2026-09-27 13:36 UTC218
            intent_ttl: Dur::secs(1200),
6f5b84fad3efatagen2026-09-27 03:59 UTC219
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC220
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC221
}
6f5b84fad3efatagen2026-09-27 03:59 UTC222
6f5b84fad3efatagen2026-09-27 03:59 UTC223
impl Default for Overrun {
6f5b84fad3efatagen2026-09-27 03:59 UTC224
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC225
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC226
            ram: RamOverrun::Warn,
6f5b84fad3efatagen2026-09-27 03:59 UTC227
            ram_slack: 1.25,
6f5b84fad3efatagen2026-09-27 03:59 UTC228
            time_grace: 1.5,
6f5b84fad3efatagen2026-09-27 03:59 UTC229
            remind_every: Dur::secs(300),
6f5b84fad3efatagen2026-09-27 03:59 UTC230
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC231
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC232
}
6f5b84fad3efatagen2026-09-27 03:59 UTC233
6f5b84fad3efatagen2026-09-27 03:59 UTC234
impl Default for Enforce {
6f5b84fad3efatagen2026-09-27 03:59 UTC235
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC236
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC237
            unwrapped: Unwrapped::Deny,
6f5b84fad3efatagen2026-09-27 03:59 UTC238
            default_size: "m".into(),
6f5b84fad3efatagen2026-09-27 03:59 UTC239
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC240
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC241
}
6f5b84fad3efatagen2026-09-27 03:59 UTC242
6f5b84fad3efatagen2026-09-27 03:59 UTC243
impl Default for Artifacts {
6f5b84fad3efatagen2026-09-27 03:59 UTC244
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC245
        let rule = |name: &str, marker: Option<&str>| Rule {
6f5b84fad3efatagen2026-09-27 03:59 UTC246
            name: name.into(),
6f5b84fad3efatagen2026-09-27 03:59 UTC247
            marker: marker.map(Into::into),
6f5b84fad3efatagen2026-09-27 03:59 UTC248
            clean: None,
6f5b84fad3efatagen2026-09-27 03:59 UTC249
        };
6f5b84fad3efatagen2026-09-27 03:59 UTC250
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC251
            project_cap: Bytes::gib(10),
6f5b84fad3efatagen2026-09-27 03:59 UTC252
            global_cap: Bytes::gib(60),
6f5b84fad3efatagen2026-09-27 03:59 UTC253
            idle_after: Dur::secs(86_400),
6f5b84fad3efatagen2026-09-27 03:59 UTC254
            size_ttl: Dur::secs(600),
6f5b84fad3efatagen2026-09-27 03:59 UTC255
            over_cap: OverCap::Warn,
6f5b84fad3efatagen2026-09-27 03:59 UTC256
            stop: StopPolicy::Nudge,
6f5b84fad3efatagen2026-09-27 03:59 UTC257
            rules: vec![
6f5b84fad3efatagen2026-09-27 03:59 UTC258
                rule("target", Some("Cargo.toml")),
6f5b84fad3efatagen2026-09-27 03:59 UTC259
                rule("result*", None),
6f5b84fad3efatagen2026-09-27 03:59 UTC260
                rule("node_modules", Some("package.json")),
6f5b84fad3efatagen2026-09-27 03:59 UTC261
                rule("zig-out", Some("build.zig")),
6f5b84fad3efatagen2026-09-27 03:59 UTC262
                rule(".zig-cache", Some("build.zig")),
6f5b84fad3efatagen2026-09-27 03:59 UTC263
                rule("_build", Some("dune-project")),
6f5b84fad3efatagen2026-09-27 03:59 UTC264
                rule("dist-newstyle", Some("cabal.project")),
6f5b84fad3efatagen2026-09-27 03:59 UTC265
            ],
6f5b84fad3efatagen2026-09-27 03:59 UTC266
            extra_rules: Vec::new(),
6f5b84fad3efatagen2026-09-27 03:59 UTC267
            nix_gc: false,
6f5b84fad3efatagen2026-09-27 03:59 UTC268
            nix_min_free: Bytes::gib(30),
6f5b84fad3efatagen2026-09-27 03:59 UTC269
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC270
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC271
}
6f5b84fad3efatagen2026-09-27 03:59 UTC272
6f5b84fad3efatagen2026-09-27 03:59 UTC273
impl Default for Nix {
6f5b84fad3efatagen2026-09-27 03:59 UTC274
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC275
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC276
            inject: true,
6f5b84fad3efatagen2026-09-27 03:59 UTC277
            cores_per_job: 4,
6f5b84fad3efatagen2026-09-27 03:59 UTC278
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC279
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC280
}
6f5b84fad3efatagen2026-09-27 03:59 UTC281
6f5b84fad3efatagen2026-09-27 03:59 UTC282
impl Default for Detect {
6f5b84fad3efatagen2026-09-27 03:59 UTC283
    fn default() -> Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC284
        let commands = [
6f5b84fad3efatagen2026-09-27 03:59 UTC285
            "cargo build",
6f5b84fad3efatagen2026-09-27 03:59 UTC286
            "cargo b",
6f5b84fad3efatagen2026-09-27 03:59 UTC287
            "cargo test",
6f5b84fad3efatagen2026-09-27 03:59 UTC288
            "cargo t",
6f5b84fad3efatagen2026-09-27 03:59 UTC289
            "cargo check",
6f5b84fad3efatagen2026-09-27 03:59 UTC290
            "cargo c",
6f5b84fad3efatagen2026-09-27 03:59 UTC291
            "cargo clippy",
6f5b84fad3efatagen2026-09-27 03:59 UTC292
            "cargo run",
6f5b84fad3efatagen2026-09-27 03:59 UTC293
            "cargo r",
6f5b84fad3efatagen2026-09-27 03:59 UTC294
            "cargo nextest",
6f5b84fad3efatagen2026-09-27 03:59 UTC295
            "cargo bench",
6f5b84fad3efatagen2026-09-27 03:59 UTC296
            "cargo install",
6f5b84fad3efatagen2026-09-27 03:59 UTC297
            "cargo doc",
6f5b84fad3efatagen2026-09-27 03:59 UTC298
            "nix build",
6f5b84fad3efatagen2026-09-27 03:59 UTC299
            "nix flake check",
6f5b84fad3efatagen2026-09-27 03:59 UTC300
            "nix develop",
6f5b84fad3efatagen2026-09-27 03:59 UTC301
            "nix run",
6f5b84fad3efatagen2026-09-27 03:59 UTC302
            "nix shell",
6f5b84fad3efatagen2026-09-27 03:59 UTC303
            "nix-build",
6f5b84fad3efatagen2026-09-27 03:59 UTC304
            "nix-shell",
6f5b84fad3efatagen2026-09-27 03:59 UTC305
            "nixos-rebuild",
6f5b84fad3efatagen2026-09-27 03:59 UTC306
            "home-manager switch",
6f5b84fad3efatagen2026-09-27 03:59 UTC307
            "home-manager build",
6f5b84fad3efatagen2026-09-27 03:59 UTC308
            "make",
6f5b84fad3efatagen2026-09-27 03:59 UTC309
            "gmake",
6f5b84fad3efatagen2026-09-27 03:59 UTC310
            "cmake --build",
6f5b84fad3efatagen2026-09-27 03:59 UTC311
            "ninja",
6f5b84fad3efatagen2026-09-27 03:59 UTC312
            "meson compile",
6f5b84fad3efatagen2026-09-27 03:59 UTC313
            "go build",
6f5b84fad3efatagen2026-09-27 03:59 UTC314
            "go test",
6f5b84fad3efatagen2026-09-27 03:59 UTC315
            "zig build",
6f5b84fad3efatagen2026-09-27 03:59 UTC316
            "dune build",
6f5b84fad3efatagen2026-09-27 03:59 UTC317
            "cabal build",
6f5b84fad3efatagen2026-09-27 03:59 UTC318
            "stack build",
6f5b84fad3efatagen2026-09-27 03:59 UTC319
            "npm run build",
6f5b84fad3efatagen2026-09-27 03:59 UTC320
            "npm test",
6f5b84fad3efatagen2026-09-27 03:59 UTC321
            "npm ci",
6f5b84fad3efatagen2026-09-27 03:59 UTC322
            "npm install",
6f5b84fad3efatagen2026-09-27 03:59 UTC323
            "pnpm build",
6f5b84fad3efatagen2026-09-27 03:59 UTC324
            "pnpm install",
6f5b84fad3efatagen2026-09-27 03:59 UTC325
            "yarn build",
6f5b84fad3efatagen2026-09-27 03:59 UTC326
            "bun run build",
6f5b84fad3efatagen2026-09-27 03:59 UTC327
            "docker build",
6f5b84fad3efatagen2026-09-27 03:59 UTC328
            "podman build",
6f5b84fad3efatagen2026-09-27 03:59 UTC329
            "mvn",
6f5b84fad3efatagen2026-09-27 03:59 UTC330
            "gradle",
6f5b84fad3efatagen2026-09-27 03:59 UTC331
            "./gradlew",
6f5b84fad3efatagen2026-09-27 03:59 UTC332
            "bazel build",
6f5b84fad3efatagen2026-09-27 03:59 UTC333
            "bazel test",
6f5b84fad3efatagen2026-09-27 03:59 UTC334
        ];
6f5b84fad3efatagen2026-09-27 03:59 UTC335
        Self {
6f5b84fad3efatagen2026-09-27 03:59 UTC336
            commands: commands.into_iter().map(Into::into).collect(),
6f5b84fad3efatagen2026-09-27 03:59 UTC337
            extra: Vec::new(),
6f5b84fad3efatagen2026-09-27 03:59 UTC338
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC339
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC340
}
6f5b84fad3efatagen2026-09-27 03:59 UTC341
6f5b84fad3efatagen2026-09-27 03:59 UTC342
impl Config {
6f5b84fad3efatagen2026-09-27 03:59 UTC343
    pub fn load() -> Result<Self, String> {
6f5b84fad3efatagen2026-09-27 03:59 UTC344
        let path = paths::config_file();
6f5b84fad3efatagen2026-09-27 03:59 UTC345
        match fs::read_to_string(&path) {
6f5b84fad3efatagen2026-09-27 03:59 UTC346
            Ok(text) => Self::parse(&text).map_err(|e| format!("{}: {e}", path.display())),
6f5b84fad3efatagen2026-09-27 03:59 UTC347
            Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(Self::default()),
6f5b84fad3efatagen2026-09-27 03:59 UTC348
            Err(e) => Err(format!("{}: {e}", path.display())),
6f5b84fad3efatagen2026-09-27 03:59 UTC349
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC350
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC351
6f5b84fad3efatagen2026-09-27 03:59 UTC352
    pub fn parse(text: &str) -> Result<Self, toml::de::Error> {
6f5b84fad3efatagen2026-09-27 03:59 UTC353
        let mut config: Self = toml::from_str(text)?;
6f5b84fad3efatagen2026-09-27 03:59 UTC354
        for (name, preset) in Self::default().sizes {
6f5b84fad3efatagen2026-09-27 03:59 UTC355
            config.sizes.entry(name).or_insert(preset);
6f5b84fad3efatagen2026-09-27 03:59 UTC356
        }
6f5b84fad3efatagen2026-09-27 03:59 UTC357
        Ok(config)
6f5b84fad3efatagen2026-09-27 03:59 UTC358
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC359
6f5b84fad3efatagen2026-09-27 03:59 UTC360
    pub fn preset(&self, name: &str) -> Result<Preset, String> {
6f5b84fad3efatagen2026-09-27 03:59 UTC361
        self.sizes.get(name).copied().ok_or_else(|| {
6f5b84fad3efatagen2026-09-27 03:59 UTC362
            let known: Vec<_> = self.sizes.keys().map(String::as_str).collect();
6f5b84fad3efatagen2026-09-27 03:59 UTC363
            format!(
6f5b84fad3efatagen2026-09-27 03:59 UTC364
                "unknown size '{name}', known sizes are {}",
6f5b84fad3efatagen2026-09-27 03:59 UTC365
                known.join(", ")
6f5b84fad3efatagen2026-09-27 03:59 UTC366
            )
6f5b84fad3efatagen2026-09-27 03:59 UTC367
        })
6f5b84fad3efatagen2026-09-27 03:59 UTC368
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC369
6f5b84fad3efatagen2026-09-27 03:59 UTC370
    pub fn artifact_rules(&self) -> impl Iterator<Item = &Rule> {
6f5b84fad3efatagen2026-09-27 03:59 UTC371
        self.artifacts
6f5b84fad3efatagen2026-09-27 03:59 UTC372
            .rules
6f5b84fad3efatagen2026-09-27 03:59 UTC373
            .iter()
6f5b84fad3efatagen2026-09-27 03:59 UTC374
            .chain(&self.artifacts.extra_rules)
6f5b84fad3efatagen2026-09-27 03:59 UTC375
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC376
6f5b84fad3efatagen2026-09-27 03:59 UTC377
    pub fn detect_patterns(&self) -> impl Iterator<Item = &str> {
6f5b84fad3efatagen2026-09-27 03:59 UTC378
        self.detect
6f5b84fad3efatagen2026-09-27 03:59 UTC379
            .commands
6f5b84fad3efatagen2026-09-27 03:59 UTC380
            .iter()
6f5b84fad3efatagen2026-09-27 03:59 UTC381
            .chain(&self.detect.extra)
6f5b84fad3efatagen2026-09-27 03:59 UTC382
            .map(String::as_str)
6f5b84fad3efatagen2026-09-27 03:59 UTC383
    }
6f5b84fad3efatagen2026-09-27 03:59 UTC384
}