recipe: Implement run

This commit is contained in:
2026-05-23 00:10:08 +02:00
parent 1a7c817fb9
commit 2e6704516a
8 changed files with 275 additions and 47 deletions
+129 -2
View File
@@ -1,10 +1,24 @@
use std::cell::Cell;
use allocative::Allocative;
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 crate::recipe::Source;
use crate::{
container::{Container, ContainerManager},
eval::{Path, UnpackCloned},
log,
recipe::Source,
};
#[derive(Debug, Clone, Allocative, NoSerialize, ProvidesStaticType)]
pub struct TarballSource {
@@ -24,6 +38,12 @@ starlark_simple_value!(TarballSource);
#[starlark_value(type = "tarball")]
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 {}
#[derive(Debug, Clone, Allocative, NoSerialize, ProvidesStaticType)]
@@ -45,6 +65,113 @@ starlark_simple_value!(Metadata);
#[starlark_value(type = "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]
pub fn recipe_globals(b: &mut GlobalsBuilder) {
fn tarball(