forked from DGNum/colmena
nix/assets: Make assets a flake
Groundwork to make flake evaluation pure. `pure-eval` works when the git workspace is clean.
This commit is contained in:
parent
a98d1f8963
commit
271d9ae576
5 changed files with 62 additions and 21 deletions
|
@ -11,8 +11,10 @@ use std::os::unix::fs::OpenOptionsExt;
|
||||||
|
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
use super::HivePath;
|
use super::{Flake, HivePath};
|
||||||
|
use crate::error::ColmenaResult;
|
||||||
|
|
||||||
|
const FLAKE_NIX: &[u8] = include_bytes!("flake.nix");
|
||||||
const EVAL_NIX: &[u8] = include_bytes!("eval.nix");
|
const EVAL_NIX: &[u8] = include_bytes!("eval.nix");
|
||||||
const OPTIONS_NIX: &[u8] = include_bytes!("options.nix");
|
const OPTIONS_NIX: &[u8] = include_bytes!("options.nix");
|
||||||
const MODULES_NIX: &[u8] = include_bytes!("modules.nix");
|
const MODULES_NIX: &[u8] = include_bytes!("modules.nix");
|
||||||
|
@ -22,17 +24,37 @@ const MODULES_NIX: &[u8] = include_bytes!("modules.nix");
|
||||||
pub(super) struct Assets {
|
pub(super) struct Assets {
|
||||||
/// Temporary directory holding the files.
|
/// Temporary directory holding the files.
|
||||||
temp_dir: TempDir,
|
temp_dir: TempDir,
|
||||||
|
|
||||||
|
/// Locked Flake URI of the assets flake.
|
||||||
|
assets_flake_uri: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assets {
|
impl Assets {
|
||||||
pub fn new() -> Self {
|
pub async fn new(flake: bool) -> ColmenaResult<Self> {
|
||||||
let temp_dir = TempDir::new().unwrap();
|
let temp_dir = TempDir::new().unwrap();
|
||||||
|
|
||||||
create_file(&temp_dir, "eval.nix", false, EVAL_NIX);
|
create_file(&temp_dir, "eval.nix", false, EVAL_NIX)?;
|
||||||
create_file(&temp_dir, "options.nix", false, OPTIONS_NIX);
|
create_file(&temp_dir, "options.nix", false, OPTIONS_NIX)?;
|
||||||
create_file(&temp_dir, "modules.nix", false, MODULES_NIX);
|
create_file(&temp_dir, "modules.nix", false, MODULES_NIX)?;
|
||||||
|
|
||||||
Self { temp_dir }
|
let mut assets_flake_uri = None;
|
||||||
|
|
||||||
|
if flake {
|
||||||
|
// Emit a temporary flake, then resolve the locked URI
|
||||||
|
create_file(&temp_dir, "flake.nix", false, FLAKE_NIX)?;
|
||||||
|
|
||||||
|
// We explicitly specify `path:` instead of letting Nix resolve
|
||||||
|
// automatically, which would involve checking parent directories
|
||||||
|
// for a git repository.
|
||||||
|
let uri = format!("path:{}", temp_dir.path().to_str().unwrap());
|
||||||
|
let assets_flake = Flake::from_uri(uri).await?;
|
||||||
|
assets_flake_uri = Some(assets_flake.locked_uri().to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
temp_dir,
|
||||||
|
assets_flake_uri,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the base expression from which the evaluated Hive can be used.
|
/// Returns the base expression from which the evaluated Hive can be used.
|
||||||
|
@ -49,11 +71,9 @@ impl Assets {
|
||||||
}
|
}
|
||||||
HivePath::Flake(flake) => {
|
HivePath::Flake(flake) => {
|
||||||
format!(
|
format!(
|
||||||
"with builtins; let eval = import {eval_nix}; hive = eval {{ flakeUri = \"{flake_uri}\"; colmenaOptions = import {options_nix}; colmenaModules = import {modules_nix}; }}; in ",
|
"with builtins; let assets = getFlake \"{assets_flake_uri}\"; hive = assets.lib.colmenaEval {{ flakeUri = \"{flake_uri}\"; }}; in ",
|
||||||
flake_uri = flake.uri(),
|
assets_flake_uri = self.assets_flake_uri.as_ref().expect("The assets flake must have been initialized"),
|
||||||
eval_nix = self.get_path("eval.nix"),
|
flake_uri = flake.locked_uri(),
|
||||||
options_nix = self.get_path("options.nix"),
|
|
||||||
modules_nix = self.get_path("modules.nix"),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,15 +89,16 @@ impl Assets {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_file(base: &TempDir, name: &str, executable: bool, contents: &[u8]) {
|
fn create_file(base: &TempDir, name: &str, executable: bool, contents: &[u8]) -> ColmenaResult<()> {
|
||||||
let mode = if executable { 0o700 } else { 0o600 };
|
let mode = if executable { 0o700 } else { 0o600 };
|
||||||
let path = base.path().join(name);
|
let path = base.path().join(name);
|
||||||
let mut f = OpenOptions::new()
|
let mut f = OpenOptions::new()
|
||||||
.create_new(true)
|
.create_new(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.mode(mode)
|
.mode(mode)
|
||||||
.open(path)
|
.open(path)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
f.write_all(contents).unwrap();
|
f.write_all(contents)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
15
src/nix/hive/flake.nix
Normal file
15
src/nix/hive/flake.nix
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
description = "Internal Colmena expressions";
|
||||||
|
|
||||||
|
outputs = { ... }: {
|
||||||
|
lib.colmenaEval = {
|
||||||
|
rawHive ? null,
|
||||||
|
flakeUri ? null,
|
||||||
|
hermetic ? flakeUri != null,
|
||||||
|
}: import ./eval.nix {
|
||||||
|
inherit rawHive flakeUri hermetic;
|
||||||
|
colmenaOptions = import ./options.nix;
|
||||||
|
colmenaModules = import ./modules.nix;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -90,6 +90,10 @@ impl HivePath {
|
||||||
Ok(Self::Legacy(path.canonicalize()?))
|
Ok(Self::Legacy(path.canonicalize()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_flake(&self) -> bool {
|
||||||
|
matches!(self, Self::Flake(_))
|
||||||
|
}
|
||||||
|
|
||||||
fn context_dir(&self) -> Option<PathBuf> {
|
fn context_dir(&self) -> Option<PathBuf> {
|
||||||
match self {
|
match self {
|
||||||
Self::Legacy(p) => p.parent().map(|d| d.to_owned()),
|
Self::Legacy(p) => p.parent().map(|d| d.to_owned()),
|
||||||
|
@ -99,13 +103,14 @@ impl HivePath {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hive {
|
impl Hive {
|
||||||
pub fn new(path: HivePath) -> ColmenaResult<Self> {
|
pub async fn new(path: HivePath) -> ColmenaResult<Self> {
|
||||||
let context_dir = path.context_dir();
|
let context_dir = path.context_dir();
|
||||||
|
let assets = Assets::new(path.is_flake()).await?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
path,
|
path,
|
||||||
context_dir,
|
context_dir,
|
||||||
assets: Assets::new(),
|
assets,
|
||||||
show_trace: false,
|
show_trace: false,
|
||||||
meta_config: OnceCell::new(),
|
meta_config: OnceCell::new(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -40,7 +40,7 @@ impl TempHive {
|
||||||
temp_file.write_all(text.as_bytes()).unwrap();
|
temp_file.write_all(text.as_bytes()).unwrap();
|
||||||
|
|
||||||
let hive_path = block_on(HivePath::from_path(temp_file.path())).unwrap();
|
let hive_path = block_on(HivePath::from_path(temp_file.path())).unwrap();
|
||||||
let hive = Hive::new(hive_path).unwrap();
|
let hive = block_on(Hive::new(hive_path)).unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
hive,
|
hive,
|
||||||
|
@ -168,7 +168,7 @@ fn test_parse_flake() {
|
||||||
let flake = block_on(Flake::from_dir(flake_dir)).unwrap();
|
let flake = block_on(Flake::from_dir(flake_dir)).unwrap();
|
||||||
|
|
||||||
let hive_path = HivePath::Flake(flake);
|
let hive_path = HivePath::Flake(flake);
|
||||||
let mut hive = Hive::new(hive_path).unwrap();
|
let mut hive = block_on(Hive::new(hive_path)).unwrap();
|
||||||
|
|
||||||
hive.set_show_trace(true);
|
hive.set_show_trace(true);
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,7 @@ pub async fn hive_from_args(args: &ArgMatches) -> ColmenaResult<Hive> {
|
||||||
log::info!("Using flake: {}", flake.uri());
|
log::info!("Using flake: {}", flake.uri());
|
||||||
|
|
||||||
let hive_path = HivePath::Flake(flake);
|
let hive_path = HivePath::Flake(flake);
|
||||||
let mut hive = Hive::new(hive_path)?;
|
let mut hive = Hive::new(hive_path).await?;
|
||||||
|
|
||||||
if args.is_present("show-trace") {
|
if args.is_present("show-trace") {
|
||||||
hive.set_show_trace(true);
|
hive.set_show_trace(true);
|
||||||
|
@ -267,7 +267,7 @@ pub async fn hive_from_args(args: &ArgMatches) -> ColmenaResult<Hive> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut hive = Hive::new(hive_path)?;
|
let mut hive = Hive::new(hive_path).await?;
|
||||||
|
|
||||||
if args.is_present("show-trace") {
|
if args.is_present("show-trace") {
|
||||||
hive.set_show_trace(true);
|
hive.set_show_trace(true);
|
||||||
|
|
Loading…
Add table
Reference in a new issue