git.delta.rocks / jrsonnet / refs/commits / ffbc7e982cb4

difftreelog

fix do not require wildcard with callPackage

Yaroslav Bolyukin2024-12-08parent: #3b8059d.patch.diff
in: trunk

6 files changed

modifiedcmds/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);
 
modifiedcrates/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,
 }
modifiedcrates/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(),
 		})))
 	}
modifiedcrates/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};
modifiedcrates/nix-eval/src/value.rsdiffbeforeafterboth
after · crates/nix-eval/src/value.rs
1use 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}
modifiedlib/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