atagen

roundabout

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