recipe: Implement run
This commit is contained in:
Generated
+1
@@ -183,6 +183,7 @@ dependencies = [
|
|||||||
"allocative",
|
"allocative",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
|
"either",
|
||||||
"petgraph 0.8.3",
|
"petgraph 0.8.3",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"starlark",
|
"starlark",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2024"
|
|||||||
allocative = "0.3.4"
|
allocative = "0.3.4"
|
||||||
anyhow = "1.0.102"
|
anyhow = "1.0.102"
|
||||||
clap = { version = "4.6.1", features = ["derive"] }
|
clap = { version = "4.6.1", features = ["derive"] }
|
||||||
|
either = "1.16.0"
|
||||||
petgraph = "0.8.3"
|
petgraph = "0.8.3"
|
||||||
smallvec = "1.15.1"
|
smallvec = "1.15.1"
|
||||||
starlark = "0.13.0"
|
starlark = "0.13.0"
|
||||||
|
|||||||
+43
-7
@@ -1,11 +1,20 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
container::{ContainerManager, PodmanRuntime},
|
container::{ContainerManager, PodmanRuntime},
|
||||||
eval::{Config, ContainerConfig, config_globals, eval_files, types_globals},
|
eval::{
|
||||||
|
Config, ContainerConfig, ContainerManagerWrapper, Context, Path, config_globals,
|
||||||
|
eval_files, types_globals,
|
||||||
|
},
|
||||||
|
log,
|
||||||
|
plan::{Plan, PlanKey},
|
||||||
recipe::RecipeSet,
|
recipe::RecipeSet,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use starlark::environment::GlobalsBuilder;
|
use starlark::{
|
||||||
|
environment::{GlobalsBuilder, Module},
|
||||||
|
eval,
|
||||||
|
values::Value,
|
||||||
|
};
|
||||||
use std::{cell::Cell, path::PathBuf, sync::Arc};
|
use std::{cell::Cell, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
@@ -80,7 +89,7 @@ pub fn run() -> anyhow::Result<()> {
|
|||||||
ContainerConfig::Podman(_) => Arc::new(PodmanRuntime::new()?),
|
ContainerConfig::Podman(_) => Arc::new(PodmanRuntime::new()?),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut container_manager = ContainerManager::new(container_runtime);
|
let container_manager = ContainerManager::new(container_runtime);
|
||||||
let mut recipes = RecipeSet::new(&config);
|
let mut recipes = RecipeSet::new(&config);
|
||||||
|
|
||||||
recipes.load_recipes(
|
recipes.load_recipes(
|
||||||
@@ -88,14 +97,41 @@ pub fn run() -> anyhow::Result<()> {
|
|||||||
&root_path.join(config.host_recipes_dir()),
|
&root_path.join(config.host_recipes_dir()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for (name, recipe) in recipes.packages.iter() {
|
// let wrapper = ContainerManagerWrapper(&container_manager);
|
||||||
println!("{name}: {:#?}", recipe);
|
// for (name, recipe) in recipes.packages.iter() {
|
||||||
}
|
// println!("{name}: {:#?}", recipe);
|
||||||
|
|
||||||
|
// let mo = Module::new();
|
||||||
|
// let mut eval = eval::Evaluator::new(&mo);
|
||||||
|
// eval.extra = Some(&wrapper);
|
||||||
|
// eval.eval_function(
|
||||||
|
// recipe.build.unwrap().0.to_value(),
|
||||||
|
// &[mo.heap().alloc(Context {
|
||||||
|
// source_dir: Path::new("/source"),
|
||||||
|
// build_dir: Path::new("/build"),
|
||||||
|
// jobs: 4,
|
||||||
|
// })],
|
||||||
|
// &[],
|
||||||
|
// )
|
||||||
|
// .unwrap();
|
||||||
|
// }
|
||||||
|
|
||||||
|
let mut plan = Plan::new(&recipes);
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Command::Fetch(_) => {}
|
Command::Fetch(_) => {}
|
||||||
Command::Build(_) => {}
|
Command::Build(cmd) => {
|
||||||
|
for recipe in cmd.recipes.iter() {
|
||||||
|
plan.add_wanted(if let Some(recipe) = recipe.strip_prefix("host:") {
|
||||||
|
PlanKey::ToolInstall(recipe.to_string())
|
||||||
|
} else {
|
||||||
|
PlanKey::PkgPackage(recipe.clone())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log!("plan", "{:#?}", plan.steps());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-11
@@ -1,9 +1,14 @@
|
|||||||
use std::{collections::HashMap, path::Path, sync::Arc};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
path::Path,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
mod podman;
|
mod podman;
|
||||||
|
|
||||||
pub use podman::PodmanRuntime;
|
pub use podman::PodmanRuntime;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
id: String,
|
id: String,
|
||||||
runtime: Arc<dyn ContainerRuntime>,
|
runtime: Arc<dyn ContainerRuntime>,
|
||||||
@@ -51,6 +56,10 @@ pub trait ContainerRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ContainerManager {
|
pub struct ContainerManager {
|
||||||
|
inner: Mutex<ContainerManagerInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ContainerManagerInner {
|
||||||
containers: HashMap<String, Container>,
|
containers: HashMap<String, Container>,
|
||||||
runtime: Arc<dyn ContainerRuntime>,
|
runtime: Arc<dyn ContainerRuntime>,
|
||||||
}
|
}
|
||||||
@@ -58,31 +67,33 @@ pub struct ContainerManager {
|
|||||||
impl ContainerManager {
|
impl ContainerManager {
|
||||||
pub fn new(runtime: Arc<dyn ContainerRuntime>) -> Self {
|
pub fn new(runtime: Arc<dyn ContainerRuntime>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
inner: Mutex::new(ContainerManagerInner {
|
||||||
containers: HashMap::new(),
|
containers: HashMap::new(),
|
||||||
runtime,
|
runtime,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn container(&mut self, name: &str) -> anyhow::Result<&Container> {
|
pub fn container(&self, name: &str) -> anyhow::Result<Container> {
|
||||||
if self.containers.get(name).is_none() {
|
let mut inner = self.inner.lock().unwrap();
|
||||||
let container_id = self.runtime.start_container("alpine:edge", &[])?;
|
if inner.containers.get(name).is_none() {
|
||||||
|
let container_id = inner.runtime.start_container("alpine:edge", &[])?;
|
||||||
|
|
||||||
crate::log!("info", "Started new container ({container_id})");
|
crate::log!("info", "Started new container ({container_id})");
|
||||||
|
|
||||||
self.containers.insert(
|
let container = Container::new(container_id, inner.runtime.clone());
|
||||||
name.into(),
|
inner.containers.insert(name.into(), container);
|
||||||
Container::new(container_id, self.runtime.clone()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.containers.get(name).unwrap())
|
Ok(inner.containers.get(name).cloned().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ContainerManager {
|
impl Drop for ContainerManager {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
for (_, container) in self.containers.iter() {
|
let inner = self.inner.lock().unwrap();
|
||||||
self.runtime.stop_container(container.id());
|
for (_, container) in inner.containers.iter() {
|
||||||
|
inner.runtime.stop_container(container.id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-1
@@ -1,9 +1,9 @@
|
|||||||
use anyhow::Context;
|
|
||||||
use starlark::{
|
use starlark::{
|
||||||
any::AnyLifetime,
|
any::AnyLifetime,
|
||||||
environment::{FrozenModule, Globals, Module},
|
environment::{FrozenModule, Globals, Module},
|
||||||
eval::Evaluator,
|
eval::Evaluator,
|
||||||
syntax::{AstModule, Dialect, DialectTypes},
|
syntax::{AstModule, Dialect, DialectTypes},
|
||||||
|
values::{UnpackValue, Value, type_repr::StarlarkTypeRepr},
|
||||||
};
|
};
|
||||||
use std::path::Path as StdPath;
|
use std::path::Path as StdPath;
|
||||||
|
|
||||||
@@ -18,6 +18,19 @@ pub use recipe::*;
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
pub use types::*;
|
pub use types::*;
|
||||||
|
|
||||||
|
pub trait UnpackCloned: Sized + StarlarkTypeRepr {
|
||||||
|
fn unpack_cloned(value: Value<'_>) -> Option<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> UnpackCloned for T
|
||||||
|
where
|
||||||
|
for<'v> T: UnpackValue<'v>,
|
||||||
|
{
|
||||||
|
fn unpack_cloned(value: Value<'_>) -> Option<Self> {
|
||||||
|
T::unpack_value(value).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eval_files(
|
pub fn eval_files(
|
||||||
path: &[&StdPath],
|
path: &[&StdPath],
|
||||||
globals: &Globals,
|
globals: &Globals,
|
||||||
@@ -25,6 +38,8 @@ pub fn eval_files(
|
|||||||
config: Option<&Config>,
|
config: Option<&Config>,
|
||||||
extra: Option<&dyn AnyLifetime>,
|
extra: Option<&dyn AnyLifetime>,
|
||||||
) -> anyhow::Result<Module> {
|
) -> anyhow::Result<Module> {
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
let module = Module::new();
|
let module = Module::new();
|
||||||
|
|
||||||
if let Some(lib_module) = lib_module {
|
if let Some(lib_module) = lib_module {
|
||||||
|
|||||||
+129
-2
@@ -1,10 +1,24 @@
|
|||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
use allocative::Allocative;
|
use allocative::Allocative;
|
||||||
use starlark::{
|
use starlark::{
|
||||||
environment::GlobalsBuilder, starlark_module, starlark_simple_value, values::StarlarkValue,
|
environment::{GlobalsBuilder, Methods, MethodsBuilder, MethodsStatic},
|
||||||
|
eval::Evaluator,
|
||||||
|
starlark_module, starlark_simple_value,
|
||||||
|
typing::Ty,
|
||||||
|
values::{
|
||||||
|
Heap, StarlarkValue, UnpackValue, Value, ValueLike, none::NoneType, tuple::UnpackTuple,
|
||||||
|
type_repr::StarlarkTypeRepr,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use starlark_derive::{NoSerialize, ProvidesStaticType, starlark_value};
|
use starlark_derive::{NoSerialize, ProvidesStaticType, starlark_value};
|
||||||
|
|
||||||
use crate::recipe::Source;
|
use crate::{
|
||||||
|
container::{Container, ContainerManager},
|
||||||
|
eval::{Path, UnpackCloned},
|
||||||
|
log,
|
||||||
|
recipe::Source,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Allocative, NoSerialize, ProvidesStaticType)]
|
#[derive(Debug, Clone, Allocative, NoSerialize, ProvidesStaticType)]
|
||||||
pub struct TarballSource {
|
pub struct TarballSource {
|
||||||
@@ -24,6 +38,12 @@ starlark_simple_value!(TarballSource);
|
|||||||
#[starlark_value(type = "tarball")]
|
#[starlark_value(type = "tarball")]
|
||||||
impl<'v> StarlarkValue<'v> for TarballSource {}
|
impl<'v> StarlarkValue<'v> for TarballSource {}
|
||||||
|
|
||||||
|
impl UnpackCloned for TarballSource {
|
||||||
|
fn unpack_cloned(value: Value<'_>) -> Option<Self> {
|
||||||
|
value.downcast_ref().cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Source for TarballSource {}
|
impl Source for TarballSource {}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Allocative, NoSerialize, ProvidesStaticType)]
|
#[derive(Debug, Clone, Allocative, NoSerialize, ProvidesStaticType)]
|
||||||
@@ -45,6 +65,113 @@ starlark_simple_value!(Metadata);
|
|||||||
#[starlark_value(type = "metadata")]
|
#[starlark_value(type = "metadata")]
|
||||||
impl<'v> StarlarkValue<'v> for Metadata {}
|
impl<'v> StarlarkValue<'v> for Metadata {}
|
||||||
|
|
||||||
|
impl UnpackCloned for Metadata {
|
||||||
|
fn unpack_cloned(value: Value<'_>) -> Option<Self> {
|
||||||
|
value.downcast_ref().cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Allocative, NoSerialize, ProvidesStaticType)]
|
||||||
|
pub struct Context {
|
||||||
|
pub source_dir: Path,
|
||||||
|
pub build_dir: Path,
|
||||||
|
pub jobs: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Context {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "context")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
starlark_simple_value!(Context);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RunArg(pub String);
|
||||||
|
|
||||||
|
impl UnpackValue<'_> for RunArg {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn unpack_value_impl(value: Value) -> anyhow::Result<Option<Self>> {
|
||||||
|
Ok(if let Some(str) = value.unpack_str() {
|
||||||
|
Some(RunArg(str.to_owned()))
|
||||||
|
} else if let Some(int) = value.unpack_i32() {
|
||||||
|
Some(RunArg(int.to_string()))
|
||||||
|
} else if let Some(path) = value.downcast_ref::<Path>() {
|
||||||
|
Some(RunArg(path.path().to_str().unwrap_or("").to_string()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StarlarkTypeRepr for RunArg {
|
||||||
|
type Canonical = Self;
|
||||||
|
|
||||||
|
fn starlark_type_repr() -> starlark::typing::Ty {
|
||||||
|
Ty::string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ProvidesStaticType)]
|
||||||
|
pub struct ContainerManagerWrapper<'a>(pub &'a ContainerManager);
|
||||||
|
|
||||||
|
#[starlark_module]
|
||||||
|
fn context_methods(b: &mut MethodsBuilder) {
|
||||||
|
fn run(
|
||||||
|
#[starlark(this)] this: &Context,
|
||||||
|
#[starlark(args)] args: UnpackTuple<RunArg>,
|
||||||
|
eval: &mut Evaluator,
|
||||||
|
) -> anyhow::Result<NoneType> {
|
||||||
|
let ContainerManagerWrapper(container_manager) = eval
|
||||||
|
.extra
|
||||||
|
.and_then(|extra| extra.downcast_ref())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("`config` called outside of config.star"))?;
|
||||||
|
|
||||||
|
let argv = args.items.iter().map(|x| x.0.as_str()).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
log!("run", "Running command: {argv:?}");
|
||||||
|
|
||||||
|
container_manager
|
||||||
|
.container("changeme")? // TODO
|
||||||
|
.exec(argv, [], std::path::Path::new("/"))?;
|
||||||
|
|
||||||
|
Ok(NoneType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[starlark_value(type = "context")]
|
||||||
|
impl<'v> StarlarkValue<'v> for Context {
|
||||||
|
fn get_methods() -> Option<&'static Methods> {
|
||||||
|
static RES: MethodsStatic = MethodsStatic::new();
|
||||||
|
RES.methods(context_methods)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_attr(&self, attr: &str, _heap: &Heap) -> bool {
|
||||||
|
match attr {
|
||||||
|
"source_dir" => true,
|
||||||
|
"build_dir" => true,
|
||||||
|
"jobs" => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_attr(&self, attr: &str, heap: &'v Heap) -> Option<Value<'v>> {
|
||||||
|
match attr {
|
||||||
|
"source_dir" => Some(heap.alloc(self.source_dir.clone())),
|
||||||
|
"build_dir" => Some(heap.alloc(self.build_dir.clone())),
|
||||||
|
"jobs" => Some(heap.alloc(self.jobs)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnpackCloned for Context {
|
||||||
|
fn unpack_cloned(value: Value<'_>) -> Option<Self> {
|
||||||
|
value.downcast_ref().cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[starlark_module]
|
#[starlark_module]
|
||||||
pub fn recipe_globals(b: &mut GlobalsBuilder) {
|
pub fn recipe_globals(b: &mut GlobalsBuilder) {
|
||||||
fn tarball(
|
fn tarball(
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ pub fn __emit(color: &str, action: &str, args: std::fmt::Arguments) {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! log {
|
macro_rules! log {
|
||||||
($action:literal) => {{
|
|
||||||
$crate::log::__emit("1;34", $action, format_args!());
|
|
||||||
}};
|
|
||||||
($action:literal, $($arg:tt)*) => {{
|
($action:literal, $($arg:tt)*) => {{
|
||||||
$crate::log::__emit("1;34", $action, format_args!($($arg)*));
|
$crate::log::__emit("1;34", $action, format_args!($($arg)*));
|
||||||
}};
|
}};
|
||||||
|
|||||||
+61
-21
@@ -1,14 +1,20 @@
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use starlark::{
|
use starlark::{
|
||||||
environment::{GlobalsBuilder, Module},
|
environment::{FrozenModule, GlobalsBuilder, Module},
|
||||||
values::UnpackValue,
|
eval,
|
||||||
|
values::{
|
||||||
|
UnpackValue,
|
||||||
|
typing::{FrozenStarlarkCallable, StarlarkCallable, StarlarkCallableParamSpec},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::eval::{Config, Metadata, TarballSource, eval_files, recipe_globals, types_globals};
|
use crate::eval::{
|
||||||
|
Config, Metadata, TarballSource, UnpackCloned, eval_files, recipe_globals, types_globals,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct SourceRecipe {
|
pub struct SourceRecipe {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -33,6 +39,10 @@ pub struct PackageRecipe {
|
|||||||
pub sources: Vec<String>,
|
pub sources: Vec<String>,
|
||||||
pub tools_wanted: Vec<String>,
|
pub tools_wanted: Vec<String>,
|
||||||
pub pkgs_wanted: Vec<String>,
|
pub pkgs_wanted: Vec<String>,
|
||||||
|
pub module: FrozenModule,
|
||||||
|
pub configure: Option<FrozenStarlarkCallable>,
|
||||||
|
pub build: Option<FrozenStarlarkCallable>,
|
||||||
|
pub install: Option<FrozenStarlarkCallable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RecipeSet<'a> {
|
pub struct RecipeSet<'a> {
|
||||||
@@ -80,19 +90,22 @@ impl<'a> RecipeSet<'a> {
|
|||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let version: String = get_value_required(&module, "version")?;
|
let module = module.freeze().map_err(|err| anyhow::anyhow!("{err:?}"))?;
|
||||||
|
|
||||||
let revision = get_value_option(&module, "revision")?.unwrap_or(1);
|
let version: String = get_value(&module, "version")?;
|
||||||
|
let revision: u32 = get_value_option(&module, "revision")?.unwrap_or(1);
|
||||||
|
let metadata: Option<Metadata> = get_value_option(&module, "metadata")?;
|
||||||
|
let source: TarballSource = get_value(&module, "source")?;
|
||||||
|
|
||||||
let metadata: Option<&Metadata> = get_value_option(&module, "metadata")?;
|
let configure = get_frozen_callable(&module, "configure")?;
|
||||||
|
let build = get_frozen_callable(&module, "build")?;
|
||||||
let source: &TarballSource = get_value_required(&module, "source")?;
|
let install = get_frozen_callable(&module, "install")?;
|
||||||
|
|
||||||
self.add_source(
|
self.add_source(
|
||||||
name,
|
name,
|
||||||
SourceRecipe {
|
SourceRecipe {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
source: Box::new(source.clone()),
|
source: Box::new(source),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -100,12 +113,16 @@ impl<'a> RecipeSet<'a> {
|
|||||||
name,
|
name,
|
||||||
PackageRecipe {
|
PackageRecipe {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
meta: metadata.cloned(),
|
meta: metadata,
|
||||||
version: version.to_string(),
|
version,
|
||||||
revision: revision as u32,
|
revision,
|
||||||
sources: vec![name.to_string()],
|
sources: vec![name.to_string()],
|
||||||
tools_wanted: vec![],
|
tools_wanted: vec![],
|
||||||
pkgs_wanted: vec![],
|
pkgs_wanted: vec![],
|
||||||
|
module,
|
||||||
|
configure,
|
||||||
|
build,
|
||||||
|
install,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -183,34 +200,57 @@ fn get_recipe_name_and_patch(
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_value_option<'v, T: UnpackValue<'v>>(
|
fn get_value_option<T: UnpackCloned>(
|
||||||
module: &'v Module,
|
module: &FrozenModule,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> anyhow::Result<Option<T>> {
|
) -> anyhow::Result<Option<T>> {
|
||||||
module
|
module
|
||||||
.get(name)
|
.get_option(name)?
|
||||||
.map(|value| {
|
.map(|value| {
|
||||||
T::unpack_value(value).unwrap().ok_or_else(|| {
|
T::unpack_cloned(value.value()).ok_or_else(|| {
|
||||||
anyhow::anyhow!(
|
anyhow::anyhow!(
|
||||||
"`{name}` should be of type `{}` but got `{}`",
|
"`{name}` should be of type `{}` but got `{}`",
|
||||||
T::starlark_type_repr(),
|
T::starlark_type_repr(),
|
||||||
value.get_type()
|
value.value().get_type()
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_value_required<'v, T: UnpackValue<'v>>(module: &'v Module, name: &str) -> anyhow::Result<T> {
|
fn get_value<T: UnpackCloned>(module: &FrozenModule, name: &str) -> anyhow::Result<T> {
|
||||||
let value = module
|
let value = module
|
||||||
.get(name)
|
.get_option(name)?
|
||||||
.ok_or_else(|| anyhow::anyhow!("`{name}` is required"))?;
|
.ok_or_else(|| anyhow::anyhow!("`{name}` is required"))?;
|
||||||
|
|
||||||
T::unpack_value(value).unwrap().ok_or_else(|| {
|
T::unpack_cloned(value.value()).ok_or_else(|| {
|
||||||
anyhow::anyhow!(
|
anyhow::anyhow!(
|
||||||
"`{name}` should be of type `{}` but got `{}`",
|
"`{name}` should be of type `{}` but got `{}`",
|
||||||
T::starlark_type_repr(),
|
T::starlark_type_repr(),
|
||||||
value.get_type()
|
value.value().get_type()
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_frozen_callable<P: StarlarkCallableParamSpec>(
|
||||||
|
module: &FrozenModule,
|
||||||
|
name: &str,
|
||||||
|
) -> anyhow::Result<Option<FrozenStarlarkCallable<P>>> {
|
||||||
|
let Some(value) = module.get_option(name)? else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let callable = StarlarkCallable::unpack_value(value.value())
|
||||||
|
.map_err(|err| anyhow::anyhow!("{err}"))?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
anyhow::anyhow!(
|
||||||
|
"`{name}` should be callable but got `{}`",
|
||||||
|
value.value().get_type()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
callable
|
||||||
|
.unpack_frozen()
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("`{name}` was callable but not frozen"))
|
||||||
|
.map(Some)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user