difftreelog
fix do not require wildcard with callPackage
in: trunk
6 files changed
cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -265,13 +265,14 @@
let generator = nix_go!(secret.generator);
let on: Option<String> = nix_go_json!(default_generator.impureOn);
+ let nixpkgs = &config.nixpkgs;
+
let host = if let Some(on) = &on {
config.host(on).await?
} else {
config.local_host()
};
let on_pkgs = host.pkgs().await?;
- let call_package = nix_go!(on_pkgs.callPackage);
let mk_secret_generators = nix_go!(on_pkgs.mkSecretGenerators);
let mut recipients = Vec::new();
@@ -280,8 +281,11 @@
recipients.push(key);
}
let generators = nix_go!(mk_secret_generators(Obj { recipients }));
+ let pkgs_and_generators = nix_go!(on_pkgs + generators);
+
+ let call_package = nix_go!(nixpkgs.lib.callPackageWith(pkgs_and_generators));
- let generator = nix_go!(call_package(generator)(generators));
+ let generator = nix_go!(call_package(generator)(Obj {}));
let generator = generator.build_maybe_batch(batch).await?;
let generator = generator
@@ -353,8 +357,8 @@
bail!("generator should be lambda, got {gen_ty}");
}
}
+ let nixpkgs = &config.nixpkgs;
let default_pkgs = &config.default_pkgs;
- let default_call_package = nix_go!(default_pkgs.callPackage);
let default_mk_secret_generators = nix_go!(default_pkgs.mkSecretGenerators);
// Generators provide additional information in passthru, to access
// passthru we should call generator, but information about where this generator is supposed to build
@@ -367,7 +371,10 @@
let generators = nix_go!(default_mk_secret_generators(Obj {
recipients: <Vec<String>>::new(),
}));
- let default_generator = nix_go!(default_call_package(generator)(generators));
+ let pkgs_and_generators = nix_go!(default_pkgs + generators);
+
+ let call_package = nix_go!(nixpkgs.lib.callPackageWith(pkgs_and_generators));
+ let default_generator = nix_go!(call_package(generator)(Obj {}));
let kind: GeneratorKind = nix_go_json!(default_generator.generatorKind);
crates/fleet-base/src/host.rsdiffbeforeafterboth--- a/crates/fleet-base/src/host.rs
+++ b/crates/fleet-base/src/host.rs
@@ -34,6 +34,7 @@
/// import nixpkgs {system = local};
pub default_pkgs: Value,
+ pub nixpkgs: Value,
pub nix_session: NixSession,
}
crates/fleet-base/src/opts.rsdiffbeforeafterboth--- a/crates/fleet-base/src/opts.rs
+++ b/crates/fleet-base/src/opts.rs
@@ -225,6 +225,7 @@
nix_args,
config_field,
default_pkgs,
+ nixpkgs,
localhost: self.localhost.to_owned(),
})))
}
crates/nix-eval/src/macros.rsdiffbeforeafterboth--- a/crates/nix-eval/src/macros.rs
+++ b/crates/nix-eval/src/macros.rs
@@ -231,6 +231,9 @@
(@o($o:ident) | $($var:tt)*) => {
$o.push(Index::Pipe($crate::nix_expr_inner!($($var)+)));
};
+ (@o($o:ident) + $($var:tt)*) => {
+ $o.push(Index::Merge($crate::nix_expr_inner!($($var)+)));
+ };
(@o($o:ident)) => {};
($field:ident $($tt:tt)+) => {{
use $crate::{nix_go, Index};
crates/nix-eval/src/value.rsdiffbeforeafterboth1use std::{collections::HashMap, fmt, path::PathBuf, sync::Arc};23use better_command::NixHandler;4use serde::{de::DeserializeOwned, Serialize};56use crate::{macros::NixExprBuilder, nix_go, Error, NixBuildBatch, NixSession, Result};78#[derive(Clone)]9pub enum Index {10 Var(String),11 String(String),12 #[allow(dead_code)]13 Apply(String),14 #[allow(dead_code)]15 Expr(NixExprBuilder),16 ExprApply(NixExprBuilder),17 Pipe(NixExprBuilder),18 Merge(NixExprBuilder),19}20impl Index {21 pub fn var(v: impl AsRef<str>) -> Self {22 let v = v.as_ref();23 assert!(24 !(v.contains('.') | v.contains(' ')),25 "bad variable name: {v}"26 );27 Self::Var(v.to_owned())28 }29 pub fn attr(v: impl AsRef<str>) -> Self {30 Self::String(v.as_ref().to_owned())31 }32 #[allow(dead_code)]33 pub fn apply(v: impl Serialize) -> Self {34 let serialized = nixlike::serialize(v).expect("invalid value for apply");35 Self::Apply(serialized.trim_end().to_owned())36 }37}38impl fmt::Display for Index {39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {40 match self {41 Index::Var(v) => {42 write!(f, "{v}")43 }44 Index::String(k) => {45 let v = nixlike::format_identifier(k.as_str());46 write!(f, ".{v}")47 }48 Index::Apply(_) => {49 write!(f, "<apply>(...)")50 }51 Index::Expr(e) => {52 write!(f, "[{}]", e.out)53 }54 Index::ExprApply(_) => {55 write!(f, "<apply>(...)")56 }57 Index::Pipe(e) => {58 write!(f, "<map>({})", e.out)59 }60 Index::Merge(e) => {61 write!(f, "//({})", e.out)62 }63 }64 }65}66impl fmt::Debug for Index {67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {68 write!(f, "{self}")69 }70}71struct PathDisplay<'i>(&'i [Index]);72impl fmt::Display for PathDisplay<'_> {73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {74 for i in self.0 {75 write!(f, "{i}")?;76 }77 Ok(())78 }79}80struct ValueInner {81 full_path: Option<Vec<Index>>,82 session: NixSession,83 value: Option<u32>,84}85#[derive(Clone)]86pub struct Value(Arc<ValueInner>);87impl Value {88 fn root(session: NixSession) -> Self {89 Self(Arc::new(ValueInner {90 full_path: Some(vec![]),91 session,92 value: None,93 }))94 }95 async fn new(session: NixSession, query: &str) -> Result<Self> {96 let vid = session.0.lock().await.execute_assign(query).await?;97 Ok(Self(Arc::new(ValueInner {98 full_path: None,99 session,100 value: Some(vid),101 })))102 }103 /// Get a top-level binding.104 ///105 /// In flake repl session, every output is exposed as top-level binding.106 pub async fn binding(session: NixSession, field: &str) -> Result<Self> {107 Self::root(session).select([Index::var(field)]).await108 }109 pub async fn select<'a>(&self, name: impl IntoIterator<Item = Index>) -> Result<Self> {110 let mut used_fields = Vec::new();111 let mut name = name.into_iter();112113 let mut full_path = self.0.full_path.clone();114 let mut query = if let Some(id) = self.0.value {115 format!("sess_field_{id}")116 } else {117 let first = name.next();118 if let Some(Index::Var(i)) = first {119 if let Some(full_path) = &mut full_path {120 full_path.push(Index::Var(i.clone()));121 }122 i.clone()123 } else {124 panic!("first path item should be variable, got {first:?}")125 }126 };127 for v in name {128 if let Some(full_path) = &mut full_path {129 full_path.push(v.clone());130 }131 match v {132 Index::Var(_) => panic!("var item may only be first"),133 Index::String(s) => {134 let escaped =135 nixlike::serialize(s).expect("strings are always serialized successfully");136 query.push('.');137 query.push_str(escaped.trim());138 }139 Index::Apply(a) => {140 // In cases like `a {}.b` first `{}.b` will be evaluated, so `a {}` should be encased in `()`141 query = format!("({query} {a})");142 }143 Index::Expr(e) => {144 let index = Value::new(self.0.session.clone(), &e.out).await?;145 used_fields.push(index.clone());146 query.push('.');147 let index = format!("${{sess_field_{}}}", index.0.value.expect("value"));148 query.push_str(&index);149 }150 Index::ExprApply(e) => {151 let index = Value::new(self.0.session.clone(), &e.out).await?;152 used_fields.push(index.clone());153 query.push(' ');154 let index = format!("sess_field_{}", index.0.value.expect("value"));155 query.push_str(&index);156 query = format!("({query})");157 }158 Index::Pipe(v) => {159 let index = Value::new(self.0.session.clone(), &v.out).await?;160 used_fields.push(index.clone());161 let index = format!("sess_field_{}", index.0.value.expect("value"));162 query = format!("({index} {query})");163 }164 Index::Merge(v) => {165 let index = Value::new(self.0.session.clone(), &v.out).await?;166 used_fields.push(index.clone());167 let index = format!("sess_field_{}", index.0.value.expect("value"));168 query = format!("({query} // {index})");169 }170 }171 }172173 let vid = self174 .0175 .session176 .0177 .lock()178 .await179 .execute_assign(&query)180 .await181 .map_err(|e| e.context(self.attribute()))?;182 Ok(Self(Arc::new(ValueInner {183 full_path,184 session: self.0.session.clone(),185 value: Some(vid),186 })))187 }188 pub async fn as_json<V: DeserializeOwned>(&self) -> Result<V> {189 let id = self.0.value.expect("can't serialize root field");190 let query = format!("sess_field_{id}");191 self.0192 .session193 .0194 .lock()195 .await196 .execute_expression_to_json(&query)197 .await198 .map_err(|e| e.context(self.attribute()))199 }200 #[allow(dead_code)]201 pub async fn has_field(&self, name: &str) -> Result<bool> {202 let id = self.0.value.expect("can't list root fields");203 let key = nixlike::escape_string(name);204 let query = format!("sess_field_{id} ? {key}");205 self.0206 .session207 .0208 .lock()209 .await210 .execute_expression_to_json(&query)211 .await212 .map_err(|e| e.context(self.attribute()))213 }214 pub async fn list_fields(&self) -> Result<Vec<String>> {215 let id = self.0.value.expect("can't list root fields");216 let query = format!("builtins.attrNames sess_field_{id}");217 self.0218 .session219 .0220 .lock()221 .await222 .execute_expression_to_json(&query)223 .await224 .map_err(|e| e.context(self.attribute()))225 }226 pub async fn type_of(&self) -> Result<String> {227 let id = self.0.value.expect("can't list root fields");228 let query = format!("builtins.typeOf sess_field_{id}");229 self.0230 .session231 .0232 .lock()233 .await234 .execute_expression_to_json(&query)235 .await236 .map_err(|e| e.context(self.attribute()))237 }238 #[allow(dead_code)]239 pub async fn import(&self) -> Result<Self> {240 let import = Self::new(self.0.session.clone(), "import").await?;241 Ok(nix_go!(self | import))242 }243 pub async fn build_maybe_batch(244 &self,245 batch: Option<NixBuildBatch>,246 ) -> Result<HashMap<String, PathBuf>> {247 if let Some(batch) = batch {248 batch.submit(self.clone()).await249 } else {250 self.build().await251 }252 }253 pub async fn build(&self) -> Result<HashMap<String, PathBuf>> {254 let id = self.0.value.expect("can't use build on not-value");255 let query = format!(":b sess_field_{id}");256 let vid = self257 .0258 .session259 .0260 .lock()261 .await262 .execute_expression_raw(&query, &mut NixHandler::default())263 .await?;264 if vid.is_empty() {265 return Err(Error::BuildFailed {266 attribute: self.attribute(),267 error: "build produced no output".to_owned(),268 });269 }270 let Some(vid) = vid.strip_prefix("This derivation produced the following outputs:\n")271 else {272 return Err(Error::BuildFailed {273 attribute: self.attribute(),274 error: format!("failed to parse output: {vid}"),275 });276 };277 let outputs = vid278 .split('\n')279 .filter(|v| !v.is_empty())280 .map(|v| v.split_once(" -> ").expect("unexpected build output"))281 .map(|(a, b)| (a.trim_start().to_owned(), PathBuf::from(b)))282 .collect();283 Ok(outputs)284 }285 /// Weakly convert string-like types (derivation/path/string) to string286 pub async fn to_string_weak(&self) -> Result<String> {287 let id = self.0.value.expect("can't use build on not-value");288 let query = format!("\"${{sess_field_{id}}}\"");289 let vid: String = self290 .0291 .session292 .0293 .lock()294 .await295 .execute_expression_to_json(&query)296 .await?;297 Ok(vid)298 }299300 fn attribute(&self) -> String {301 if let Some(full_path) = &self.0.full_path {302 PathDisplay(full_path).to_string()303 } else {304 "<root>".to_owned()305 }306 }307308 pub(crate) fn session(&self) -> NixSession {309 self.0.session.clone()310 }311312 pub(crate) fn session_field_id(&self) -> u32 {313 self.0.value.expect("not root")314 }315}316impl Drop for ValueInner {317 fn drop(&mut self) {318 if let Some(id) = self.value {319 if let Ok(mut lock) = self.session.0.try_lock() {320 lock.free_list.push(id)321 }322 // Leaked323 }324 }325}lib/default.nixdiffbeforeafterboth--- a/lib/default.nix
+++ b/lib/default.nix
@@ -46,7 +46,6 @@
mkPassword = {size ? 32}: {
coreutils,
mkSecretGenerator,
- ...
}:
mkSecretGenerator {
script = ''
@@ -58,7 +57,7 @@
mkEd25519 = {
noEmbedPublic ? false,
encoding ? null,
- }: {mkSecretGenerator, ...}:
+ }: {mkSecretGenerator}:
mkSecretGenerator {
script = ''
mkdir $out
@@ -68,7 +67,7 @@
'';
};
- mkX25519 = {encoding ? null}: {mkSecretGenerator, ...}:
+ mkX25519 = {encoding ? null}: {mkSecretGenerator}:
mkSecretGenerator {
script = ''
mkdir $out
@@ -80,7 +79,6 @@
mkRsa = {size ? 4096}: {
openssl,
mkSecretGenerator,
- ...
}:
mkSecretGenerator {
script = ''
@@ -98,7 +96,7 @@
count ? 32,
encoding,
noNuls ? false,
- }: {mkSecretGenerator, ...}:
+ }: {mkSecretGenerator}:
mkSecretGenerator {
script = ''
mkdir $out