use tatara_nix::derivation::{BridgeTarget, Derivation};
use crate::set::{PackageLookup, PackageSet, PackageSetError};
pub struct NixpkgsBridge {
pub pkg_set: Option<String>,
pub known_names: Vec<String>,
pub label: String,
}
impl Default for NixpkgsBridge {
fn default() -> Self {
Self {
pkg_set: None,
known_names: vec![],
label: "nixpkgs-bridge".into(),
}
}
}
impl NixpkgsBridge {
pub fn new() -> Self {
Self::default()
}
pub fn with_pkg_set(mut self, expr: impl Into<String>) -> Self {
self.pkg_set = Some(expr.into());
self
}
pub fn with_names(mut self, names: Vec<String>) -> Self {
self.known_names = names;
self
}
pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.label = label.into();
self
}
pub fn derivation(&self, attr_path: impl Into<String>) -> Derivation {
let attr = attr_path.into();
Derivation {
name: attr.clone(),
version: None,
inputs: vec![],
source: Default::default(),
builder: Default::default(),
outputs: Default::default(),
env: vec![],
sandbox: Default::default(),
bridge: Some(BridgeTarget {
attr_path: attr,
pkg_set: self.pkg_set.clone(),
}),
nix_expr: None,
}
}
}
impl PackageSet for NixpkgsBridge {
fn get(&self, name: &str) -> Result<PackageLookup, PackageSetError> {
if self.known_names.is_empty() {
return Ok(Some(self.derivation(name)));
}
if self.known_names.iter().any(|n| n == name) {
Ok(Some(self.derivation(name)))
} else {
Ok(None)
}
}
fn names(&self) -> Vec<String> {
self.known_names.clone()
}
fn label(&self) -> &str {
&self.label
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn open_bridge_resolves_anything() {
let b = NixpkgsBridge::new();
let d = b.get("hello").unwrap().expect("should resolve");
assert_eq!(d.name, "hello");
assert!(d.bridge.is_some());
assert_eq!(d.bridge.as_ref().unwrap().attr_path, "hello");
assert!(d.bridge.as_ref().unwrap().pkg_set.is_none());
}
#[test]
fn closed_bridge_only_resolves_known_names() {
let b = NixpkgsBridge::new().with_names(vec!["hello".into(), "bash".into()]);
assert!(b.get("hello").unwrap().is_some());
assert!(b.get("nonexistent").unwrap().is_none());
assert_eq!(b.names().len(), 2);
}
#[test]
fn custom_pkg_set_carries_through() {
let b = NixpkgsBridge::new().with_pkg_set("import ./release.nix {}");
let d = b.get("mypkg").unwrap().unwrap();
assert_eq!(
d.bridge.as_ref().unwrap().pkg_set.as_deref(),
Some("import ./release.nix {}")
);
}
#[test]
fn derivation_exposes_dotted_attr_path() {
let b = NixpkgsBridge::new();
let d = b.derivation("python3Packages.requests");
assert_eq!(d.name, "python3Packages.requests");
assert_eq!(
d.bridge.as_ref().unwrap().attr_path,
"python3Packages.requests"
);
}
}