fix: derivation (WIP)
This commit is contained in:
@@ -127,12 +127,7 @@ const structuredAttrsExcludedKeys = new Set([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const specialAttrs = new Set([
|
const specialAttrs = new Set([
|
||||||
"name",
|
|
||||||
"builder",
|
|
||||||
"system",
|
|
||||||
"args",
|
"args",
|
||||||
"outputs",
|
|
||||||
"__structuredAttrs",
|
|
||||||
"__ignoreNulls",
|
"__ignoreNulls",
|
||||||
"__contentAddressed",
|
"__contentAddressed",
|
||||||
"__impure",
|
"__impure",
|
||||||
@@ -300,14 +295,6 @@ export const derivationStrict = (args: NixValue): NixAttrs => {
|
|||||||
const drvArgs = extractArgs(attrs, collectedContext);
|
const drvArgs = extractArgs(attrs, collectedContext);
|
||||||
const env = extractEnv(attrs, structuredAttrs, ignoreNulls, collectedContext, drvName);
|
const env = extractEnv(attrs, structuredAttrs, ignoreNulls, collectedContext, drvName);
|
||||||
|
|
||||||
if (!structuredAttrs) {
|
|
||||||
env.set("name", drvName);
|
|
||||||
env.set("builder", builder);
|
|
||||||
env.set("system", platform);
|
|
||||||
if (outputs.length > 1 || outputs[0] !== "out") {
|
|
||||||
env.set("outputs", outputs.join(" "));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { inputDrvs, inputSrcs } = extractInputDrvsAndSrcs(collectedContext);
|
const { inputDrvs, inputSrcs } = extractInputDrvsAndSrcs(collectedContext);
|
||||||
|
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export const builtins: any = {
|
|||||||
warn: mkPrimop(functional.warn, "warn", 2),
|
warn: mkPrimop(functional.warn, "warn", 2),
|
||||||
break: mkPrimop(functional.breakFunc, "break", 1),
|
break: mkPrimop(functional.breakFunc, "break", 1),
|
||||||
|
|
||||||
derivation: mkPrimop(derivation.derivation, "derivation", 1),
|
derivation: undefined as any,
|
||||||
derivationStrict: mkPrimop(derivation.derivationStrict, "derivationStrict", 1),
|
derivationStrict: mkPrimop(derivation.derivationStrict, "derivationStrict", 1),
|
||||||
|
|
||||||
import: mkPrimop(io.importFunc, "import", 1),
|
import: mkPrimop(io.importFunc, "import", 1),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import type { NixValue, NixThunkInterface, NixStrictValue } from "./types";
|
import type { NixValue, NixThunkInterface, NixStrictValue } from "./types";
|
||||||
import { HAS_CONTEXT } from "./string-context";
|
import { HAS_CONTEXT } from "./string-context";
|
||||||
import { IS_PATH } from "./types";
|
import { IS_PATH } from "./types";
|
||||||
import { isAttrs } from "./builtins/type-check";
|
import { isAttrs, isList } from "./builtins/type-check";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbol used to mark objects as thunks
|
* Symbol used to mark objects as thunks
|
||||||
@@ -165,7 +165,9 @@ export const forceDeep = (value: NixValue, seen: WeakSet<object> = new WeakSet()
|
|||||||
}
|
}
|
||||||
return CYCLE_MARKER;
|
return CYCLE_MARKER;
|
||||||
}
|
}
|
||||||
|
if (isAttrs(forced) || isList(forced)) {
|
||||||
seen.add(forced);
|
seen.add(forced);
|
||||||
|
}
|
||||||
|
|
||||||
if (HAS_CONTEXT in forced || IS_PATH in forced) {
|
if (HAS_CONTEXT in forced || IS_PATH in forced) {
|
||||||
return forced;
|
return forced;
|
||||||
|
|||||||
@@ -41,7 +41,22 @@ impl Context {
|
|||||||
let ctx = Ctx::new()?;
|
let ctx = Ctx::new()?;
|
||||||
let runtime = Runtime::new()?;
|
let runtime = Runtime::new()?;
|
||||||
|
|
||||||
Ok(Self { ctx, runtime })
|
let mut context = Self { ctx, runtime };
|
||||||
|
context.init_derivation()?;
|
||||||
|
|
||||||
|
Ok(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_derivation(&mut self) -> Result<()> {
|
||||||
|
const DERIVATION_NIX: &str = include_str!("runtime/corepkgs/derivation.nix");
|
||||||
|
let source = Source::new_virtual(
|
||||||
|
"<nix/derivation-internal.nix>".into(),
|
||||||
|
DERIVATION_NIX.to_string(),
|
||||||
|
);
|
||||||
|
let code = self.ctx.compile(source, None)?;
|
||||||
|
self.runtime
|
||||||
|
.eval(format!("Nix.builtins.derivation = {}", code), &mut self.ctx)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
eval!(eval, "Nix.force({})");
|
eval!(eval, "Nix.force({})");
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ pub enum SourceType {
|
|||||||
Repl(Arc<PathBuf>),
|
Repl(Arc<PathBuf>),
|
||||||
/// file
|
/// file
|
||||||
File(Arc<PathBuf>),
|
File(Arc<PathBuf>),
|
||||||
|
/// virtual (name, no path)
|
||||||
|
Virtual(Arc<str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -71,6 +73,13 @@ impl Source {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_virtual(name: Arc<str>, src: String) -> Self {
|
||||||
|
Self {
|
||||||
|
ty: SourceType::Virtual(name),
|
||||||
|
src: src.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_dir(&self) -> &Path {
|
pub fn get_dir(&self) -> &Path {
|
||||||
use SourceType::*;
|
use SourceType::*;
|
||||||
match &self.ty {
|
match &self.ty {
|
||||||
@@ -79,6 +88,7 @@ impl Source {
|
|||||||
.as_path()
|
.as_path()
|
||||||
.parent()
|
.parent()
|
||||||
.expect("source file must have a parent dir"),
|
.expect("source file must have a parent dir"),
|
||||||
|
Virtual(_) => Path::new("/"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +97,7 @@ impl Source {
|
|||||||
SourceType::Eval(_) => "«eval»".into(),
|
SourceType::Eval(_) => "«eval»".into(),
|
||||||
SourceType::Repl(_) => "«repl»".into(),
|
SourceType::Repl(_) => "«repl»".into(),
|
||||||
SourceType::File(path) => path.as_os_str().to_string_lossy().to_string(),
|
SourceType::File(path) => path.as_os_str().to_string_lossy().to_string(),
|
||||||
|
SourceType::Virtual(name) => name.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,8 @@ pub fn op_fetch_tarball<Ctx: RuntimeContext>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref expected) = expected_sha256
|
if let Some(ref expected) = expected_sha256
|
||||||
&& nar_hash != *expected {
|
&& nar_hash != *expected
|
||||||
|
{
|
||||||
return Err(NixRuntimeError::from(format!(
|
return Err(NixRuntimeError::from(format!(
|
||||||
"NAR hash mismatch for '{}': expected {}, got {}",
|
"NAR hash mismatch for '{}': expected {}, got {}",
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ pub fn fetch_git(
|
|||||||
let temp_dir = tempfile::tempdir()?;
|
let temp_dir = tempfile::tempdir()?;
|
||||||
let checkout_dir = checkout_rev_to_temp(&bare_repo, &target_rev, submodules, temp_dir.path())?;
|
let checkout_dir = checkout_rev_to_temp(&bare_repo, &target_rev, submodules, temp_dir.path())?;
|
||||||
|
|
||||||
let nar_hash = hex::encode(crate::nar::compute_nar_hash(&checkout_dir)
|
let nar_hash = hex::encode(
|
||||||
.map_err(|e| GitError::NarHashError(e.to_string()))?);
|
crate::nar::compute_nar_hash(&checkout_dir)
|
||||||
|
.map_err(|e| GitError::NarHashError(e.to_string()))?,
|
||||||
|
);
|
||||||
|
|
||||||
let store_path = store
|
let store_path = store
|
||||||
.add_to_store_from_path(name, &checkout_dir, vec![])
|
.add_to_store_from_path(name, &checkout_dir, vec![])
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ mod downgrade;
|
|||||||
mod fetcher;
|
mod fetcher;
|
||||||
mod ir;
|
mod ir;
|
||||||
mod nar;
|
mod nar;
|
||||||
|
mod nix_utils;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod store;
|
mod store;
|
||||||
mod nix_utils;
|
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
||||||
|
|||||||
31
nix-js/src/runtime/corepkgs/derivation.nix
Normal file
31
nix-js/src/runtime/corepkgs/derivation.nix
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
drvAttrs@{
|
||||||
|
outputs ? [ "out" ],
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
strict = derivationStrict drvAttrs;
|
||||||
|
|
||||||
|
commonAttrs =
|
||||||
|
drvAttrs
|
||||||
|
// (builtins.listToAttrs outputsList)
|
||||||
|
// {
|
||||||
|
all = map (x: x.value) outputsList;
|
||||||
|
inherit drvAttrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
outputToAttrListElement = outputName: {
|
||||||
|
name = outputName;
|
||||||
|
value = commonAttrs // {
|
||||||
|
outPath = builtins.getAttr outputName strict;
|
||||||
|
drvPath = strict.drvPath;
|
||||||
|
type = "derivation";
|
||||||
|
inherit outputName;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputsList = map outputToAttrListElement outputs;
|
||||||
|
|
||||||
|
in
|
||||||
|
(builtins.head outputsList).value
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use hashbrown::hash_map::{Entry, HashMap};
|
use hashbrown::hash_map::{Entry, HashMap};
|
||||||
|
|
||||||
@@ -53,12 +52,12 @@ pub(super) fn op_import<Ctx: RuntimeContext>(
|
|||||||
let corepkg_name = &path[5..path.len() - 1];
|
let corepkg_name = &path[5..path.len() - 1];
|
||||||
if let Some(file) = CorePkgs::get(corepkg_name) {
|
if let Some(file) = CorePkgs::get(corepkg_name) {
|
||||||
tracing::info!("Importing corepkg: {}", corepkg_name);
|
tracing::info!("Importing corepkg: {}", corepkg_name);
|
||||||
let source = Source {
|
let source = Source::new_virtual(
|
||||||
ty: crate::error::SourceType::Eval(Arc::new(ctx.get_current_dir().to_path_buf())),
|
path.into(),
|
||||||
src: str::from_utf8(&file.data)
|
str::from_utf8(&file.data)
|
||||||
.expect("corrupted corepkgs file")
|
.expect("corrupted corepkgs file")
|
||||||
.into(),
|
.into(),
|
||||||
};
|
);
|
||||||
ctx.add_source(source.clone());
|
ctx.add_source(source.clone());
|
||||||
return Ok(ctx.compile(source).map_err(|err| err.to_string())?);
|
return Ok(ctx.compile(source).map_err(|err| err.to_string())?);
|
||||||
} else {
|
} else {
|
||||||
@@ -445,8 +444,7 @@ pub(super) fn op_add_path<Ctx: RuntimeContext>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref expected_hash) = sha256 {
|
if let Some(ref expected_hash) = sha256 {
|
||||||
let expected_hex =
|
let expected_hex = NixHash::from_str(expected_hash, Some(HashAlgo::Sha256))
|
||||||
NixHash::from_str(expected_hash, Some(HashAlgo::Sha256))
|
|
||||||
.map_err(|err| err.to_string())?;
|
.map_err(|err| err.to_string())?;
|
||||||
if computed_hash != expected_hex.digest_as_bytes() {
|
if computed_hash != expected_hex.digest_as_bytes() {
|
||||||
return Err(NixRuntimeError::from(format!(
|
return Err(NixRuntimeError::from(format!(
|
||||||
@@ -960,8 +958,7 @@ pub(super) fn op_add_filtered_path<Ctx: RuntimeContext>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref expected_hash) = sha256 {
|
if let Some(ref expected_hash) = sha256 {
|
||||||
let expected_hex =
|
let expected_hex = NixHash::from_str(expected_hash, Some(HashAlgo::Sha256))
|
||||||
NixHash::from_str(expected_hash, Some(HashAlgo::Sha256))
|
|
||||||
.map_err(|err| err.to_string())?;
|
.map_err(|err| err.to_string())?;
|
||||||
if computed_hash != expected_hex.digest_as_bytes() {
|
if computed_hash != expected_hex.digest_as_bytes() {
|
||||||
return Err(NixRuntimeError::from(format!(
|
return Err(NixRuntimeError::from(format!(
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ impl StoreConfig {
|
|||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
.unwrap_or_else(|_| PathBuf::from("/nix/var/nix/daemon-socket/socket"));
|
.unwrap_or_else(|_| PathBuf::from("/nix/var/nix/daemon-socket/socket"));
|
||||||
|
|
||||||
Self {
|
Self { daemon_socket }
|
||||||
daemon_socket,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ use nix_compat::wire::ProtocolVersion;
|
|||||||
use nix_compat::wire::de::{NixRead, NixReader};
|
use nix_compat::wire::de::{NixRead, NixReader};
|
||||||
use nix_compat::wire::ser::{NixSerialize, NixWrite, NixWriter, NixWriterBuilder};
|
use nix_compat::wire::ser::{NixSerialize, NixWrite, NixWriter, NixWriterBuilder};
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
|
use thiserror::Error;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf, WriteHalf, split};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf, WriteHalf, split};
|
||||||
use tokio::net::UnixStream;
|
use tokio::net::UnixStream;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
|
||||||
use super::Store;
|
use super::Store;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
pub struct DaemonStore {
|
pub struct DaemonStore {
|
||||||
runtime: tokio::runtime::Runtime,
|
runtime: tokio::runtime::Runtime,
|
||||||
@@ -569,11 +569,7 @@ impl NixDaemonClient {
|
|||||||
traces.push(trace_hint);
|
traces.push(trace_hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(NixDaemonError {
|
Ok(NixDaemonError { level, msg, traces })
|
||||||
level,
|
|
||||||
msg,
|
|
||||||
traces,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a path is valid in the store
|
/// Check if a path is valid in the store
|
||||||
|
|||||||
Reference in New Issue
Block a user