OXYGENHUB

Coverage / crates/hub/src/levels.rs 100.0%

32 of 32 lines run, 7 of 14 functions · run #481 on main · run missed

1
//! The three levels settings live at, site, organisation and repository,
2
//! and how a repository sees the levels above it. Shared by AI assistants
3
//! (§13.4) and Flow variables (§13.2).
4
5
use crate::db::Pool;
6
7
/// Which level a setting belongs to.
8
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9
pub enum Scope {
10
    Site,
11
    Org(i64),
12
    Repo(i64),
13
}
14
15
impl Scope {
162619×
    pub fn kind(self) -> &'static str {
172619×
        match self {
181475×
            Scope::Site => "site",
19177×
            Scope::Org(_) => "org",
20967×
            Scope::Repo(_) => "repo",
21
        }
222619×
    }
23
242619×
    pub fn id(self) -> i64 {
252619×
        match self {
261475×
            Scope::Site => 0,
271144×
            Scope::Org(id) | Scope::Repo(id) => id,
28
        }
292619×
    }
30
}
31
32
/// A level as a settings page addresses it.
33
pub struct At {
34
    pub scope: Scope,
35
    /// The owner name, so a repository finds its organisation.
36
    pub owner: String,
37
    /// What the audit log names.
38
    pub label: String,
39
}
40
41
impl At {
42309×
    pub fn site() -> At {
43309×
        At { scope: Scope::Site, owner: String::new(), label: "site".into() }
44309×
    }
45
4695×
    pub fn org(org: &crate::db::accounts::Organisation) -> At {
4795×
        At { scope: Scope::Org(org.id), owner: org.name.clone(), label: org.name.clone() }
4895×
    }
49
50411×
    pub fn repo(row: &crate::db::repos::RepoRow) -> At {
51411×
        At { scope: Scope::Repo(row.id), owner: row.owner.clone(), label: format!("{}/{}", row.owner, row.name) }
52411×
    }
53
}
54
55
/// The levels above a scope, outermost first: the site, then the
56
/// organisation when the owner is one.
571457×
pub async fn above(pool: &Pool, scope: Scope, owner: &str) -> sqlx::Result<Vec<(Scope, String)>> {
581457×
    let mut out = vec![];
591457×
    match scope {
60385×
        Scope::Site => {}
61124×
        Scope::Org(_) => out.push((Scope::Site, "the site".to_string())),
62
        Scope::Repo(_) => {
63948×
            out.push((Scope::Site, "the site".to_string()));
64948×
            if let Some(org) = crate::db::accounts::org_by_name(pool, owner).await? {
6550×
                out.push((Scope::Org(org.id), format!("the {} organisation", org.name)));
66898×
            }
67
        }
68
    }
691457×
    Ok(out)
701457×
}