This commit is contained in:
Sebastian Moser
2026-11-02 21:53:31 +01:00
parent a347145348
commit 72a707299f
39 changed files with 7068 additions and 287 deletions

18
parts/c2vi/Cargo.toml Normal file
View File

@@ -0,0 +1,18 @@
[package]
name = "mize-part-c2vi"
version = "0.1.0"
edition = "2024"
[lib]
name = "mize_part_c2vi"
path = "./src/mpart.rs"
crate-type = ["cdylib", "rlib"]
[features]
default = ["desktop"]
desktop = ["dep:dioxus"]
[dependencies]
mize = { workspace = true }
cmd_lib = "2.0.1"
dioxus = { version = "0.7", optional = true, features = ["desktop"] }

View File

@@ -0,0 +1,11 @@
[package]
name = "mize-generated-c2vi"
version = "0.1.0"
edition = "2024"
[lib]
name = "mize_generated_c2vi"
path = "src/lib.rs"
[dependencies]
mize = { workspace = true }

View File

@@ -0,0 +1,92 @@
// AUTO-GENERATED by mize dev gen -- do not edit manually
use mize::prelude::*;
use mize::config::MizeFun;
pub struct CliPart {
id: MizeId
}
impl MizePart for CliPart {
fn id(&self) -> MizeResult<MizeId> {
Ok(self.id.clone())
}
}
impl CliPart {
pub fn get(name: &str) -> MizeResult<CliPart> {
let mut mize = get_global_mize()?;
let part = mize.get_part(name)?;
Ok(CliPart { id: part.id()? })
}
pub fn set_command(&self, arg0: &str) -> MizeResult<()> {
let mut args = ItemData::new();
args.set_path("0", arg0.into_item_data())?;
dyn_call(self.id.clone(), "set_command", args)?;
Ok(())
}
pub fn subcommand(&self, arg0: Command, arg1: MizeFun) -> MizeResult<()> {
let mut args = ItemData::new();
let mut __arg0 = ItemData::new();
__arg0.set_path("_native", arg0.native_num)?;
args.set_path("0", __arg0)?;
args.set_path("1", ItemData::fun(arg1)?)?;
dyn_call(self.id.clone(), "subcommand", args)?;
Ok(())
}
pub fn run(&self, arg0: Vec<String>) -> MizeResult<()> {
let mut args = ItemData::new();
args.set_path("0", arg0.into_item_data())?;
dyn_call(self.id.clone(), "run", args)?;
Ok(())
}
pub fn opt_state(&self) -> MizeResult<ItemData> {
get_config(&format!("{}/state", self.id.dot()))
}
}
// native type: Command (clap::Command)
pub struct Command {
pub native_num: u32
}
impl FromItemData for Command {
fn from_itemdata(data: ItemData) -> MizeResult<Self> {
Ok(Command { native_num: data.get_path("_native")?.value_u32()? })
}
}
impl Command {
pub fn new(arg0: &str) -> MizeResult<Command> {
let mut args = ItemData::new();
args.set_path("0", arg0.into_item_data())?;
let mut mize = get_global_mize()?;
let id = mize.id_new_dots("cli.Command")?;
let data = dyn_call(id, "new", args)?;
let native_num: u32 = data.get_path("_native")?.value_u32()?;
Ok(Command { native_num })
}
}
// native type: ArgMatches (clap::ArgMatches)
pub struct ArgMatches {
pub native_num: u32
}
impl FromItemData for ArgMatches {
fn from_itemdata(data: ItemData) -> MizeResult<Self> {
Ok(ArgMatches { native_num: data.get_path("_native")?.value_u32()? })
}
}
impl ArgMatches {
}
// part id string: cli

2
parts/c2vi/part Normal file
View File

@@ -0,0 +1,2 @@
id = "c2vi"
gen = [ "cli" ]

37
parts/c2vi/src/dash.rs Normal file
View File

@@ -0,0 +1,37 @@
#[cfg(feature = "desktop")]
use dioxus::prelude::*;
#[cfg(feature = "desktop")]
pub fn launch_c2vi_dashboard() {
unsafe {
std::env::remove_var("WAYLAND_DISPLAY");
std::env::set_var("DISPLAY", ":0");
}
use dioxus::desktop::{Config, WindowBuilder};
dioxus::LaunchBuilder::new()
.with_cfg(
Config::new().with_window(
WindowBuilder::new()
.with_decorations(false)
.with_title("SCI display"),
),
)
.launch(c2vi_dash_main);
}
#[cfg(feature = "desktop")]
fn c2vi_dash_main() -> Element {
// spacetime SDK not wired yet — show a clear failure state until then
let current = use_signal(|| "spacetime SDK not wired yet".to_string());
let next = use_signal(|| "".to_string());
rsx! {
div {
style: "text-align: center; padding: 2rem; font-size: 120px;",
p { "{current}" }
p {
style: "font-size: 50px; color: grey; opacity: 0.7;",
"{next}"
}
}
}
}

159
parts/c2vi/src/deploy.rs Normal file
View File

@@ -0,0 +1,159 @@
use crate::generated::ArgMatches;
use cmd_lib::run_cmd as sh;
use mize::prelude::*;
fn cfg_str(key: &str) -> MizeResult<String> {
get_global_mize()?.get_config(key)?.value_string()
}
fn cfg_str_or(key: &str, default: &str) -> String {
get_global_mize()
.ok()
.and_then(|mut m| m.get_config(key).ok())
.and_then(|v| v.value_string().ok())
.unwrap_or_else(|| default.to_owned())
}
pub fn remote_deploy(_matches: ArgMatches, hostname: &str) -> MizeResult<()> {
let config_src = cfg_str("c2vi.config_src")?;
let rsync_excludes = cfg_str("c2vi.rsync_excludes")?;
let remote_src_dir = cfg_str(&format!("c2vi.deploy.{hostname}.remote_dir"))?;
let mize_store_dir = cfg_str(&format!("c2vi.deploy.{hostname}.mize_store_dir"))?;
let rclone_flag = cfg_str_or(&format!("c2vi.deploy.{hostname}.rsync_chown"), "");
let bin = cfg_str_or("c2vi.deploy.bin", "mize");
let do_mize_restart = false;
unsafe {
std::env::set_var("SRC", &config_src);
std::env::set_var("HOSTNAME", hostname);
}
sh!(echo cmd: rsync -r -u -v -a --delete --perms $rclone_flag --include=".git/" --include=".git/**" --exclude="target" --mkpath $rsync_excludes $config_src/ $hostname:$remote_src_dir)?;
sh!(rsync -r -u -v -a --delete --perms $rclone_flag --include=".git/" --include=".git/**" --exclude="target" --mkpath $rsync_excludes $config_src/ $hostname:$remote_src_dir)?;
let ssh_cmd = format!(
r#"
if ! tmux has-session -t mize-deploy 2>/dev/null; then
echo "Created new tmux session...."
tmux new-session -d -s mize-deploy "nix develop git+file://{remote_src_dir}/mize#buildShell --max-jobs 1"
else
echo "using existing session..."
fi
tmux send-keys -t mize-deploy "DO_MIZE_RESTART={do_mize_restart}" Enter
tmux send-keys -t mize-deploy "cargo build --manifest-path {remote_src_dir}/mize/Cargo.toml --bin {bin}" Enter
tmux send-keys -t mize-deploy 'BUILD_SUCCESS=$?' Enter
tmux send-keys -t mize-deploy '[[ "$BUILD_SUCCESS" == "0" ]] && echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" > {mize_store_dir}/daemon.env' Enter
tmux send-keys -t mize-deploy '[[ "$BUILD_SUCCESS" == "0" ]] && echo "MIZE_CONFIG_FILES={mize_store_dir}/config.toml" >> {mize_store_dir}/daemon.env' Enter
tmux send-keys -t mize-deploy '[[ "$BUILD_SUCCESS" == "0" ]] && [[ "$HOSTNAME" == "nico" ]] && echo "PATH=/root/work/path-extra:$PATH" >> {mize_store_dir}/daemon.env' Enter
tmux send-keys -t mize-deploy '[[ "$BUILD_SUCCESS" == "0" ]] && [[ "$DO_MIZE_RESTART" == "true" ]] && systemctl --user restart mize' Enter
"#
);
sh!(ssh $hostname $ssh_cmd)?;
Ok(())
}
pub fn new_deploy(_matches: ArgMatches, hostname: &str) -> MizeResult<()> {
let config_src = cfg_str("c2vi.config_src")?;
let path = cfg_str(&format!("c2vi.deploy.{hostname}.mize_bin_dir"))?;
let is_release = hostname == "mac";
let ld_lib_path = std::env::var("LD_LIBRARY_PATH").unwrap_or_default();
unsafe {
std::env::set_var("SRC", &config_src);
}
if is_release {
sh!(echo cmd: cargo build --manifest-path $config_src/mize/Cargo.toml --bin mize --release)?;
sh!(cargo build --manifest-path $config_src/mize/Cargo.toml --bin mize --release)?;
sh!(echo cmd: patchelf --set-rpath $ld_lib_path $config_src/mize/target/release/mize)?;
let _ = sh!(patchelf --set-rpath $ld_lib_path $config_src/mize/target/release/mize);
sh!(echo cmd: scp $config_src/mize/target/release/mize $hostname:$path)?;
sh!(scp $config_src/mize/target/release/mize $hostname:$path)?;
} else {
sh!(echo cmd: cargo build --manifest-path $config_src/mize/Cargo.toml --bin mize)?;
sh!(cargo build --manifest-path $config_src/mize/Cargo.toml --bin mize)?;
sh!(echo cmd: patchelf --set-rpath $ld_lib_path $config_src/mize/target/debug/mize)?;
let _ = sh!(patchelf --set-rpath $ld_lib_path $config_src/mize/target/debug/mize);
sh!(echo cmd: scp $config_src/mize/target/debug/mize $hostname:$path)?;
sh!(scp $config_src/mize/target/debug/mize $hostname:$path)?;
}
Ok(())
}
pub fn deploy_spacetime(_: ArgMatches) -> MizeResult<()> {
let mize_src = cfg_str("c2vi.mize_src")?;
let module_path = cfg_str_or(
"c2vi.deploy.spacetime.module_path",
&format!("{mize_src}/marts/spacetime"),
);
let config_src = cfg_str("c2vi.config_src")?;
unsafe {
std::env::set_var("SRC", &config_src);
}
let cmd = format!(
r#"
if ! tmux has-session -t mize-deploy 2>/dev/null; then
echo "Created new tmux session...."
systemd-run --user --scope --description="mize deploy tmux session" tmux new-session -d -s mize-deploy "nix develop git+file://$SRC/mize --impure"
else
echo "using existing session..."
fi
tmux send-keys -t mize-deploy "spacetime publish -p {module_path} --yes mize" Enter
"#
);
sh!(/bin/sh -c "$cmd")?;
Ok(())
}
pub fn obsidian_deploy(_: ArgMatches) -> MizeResult<()> {
let config_src = cfg_str("c2vi.config_src")?;
let plugin_dir = cfg_str("c2vi.deploy.obsidian.plugin_dir")?;
unsafe {
std::env::set_var("SRC", &config_src);
}
let cmd = format!(
r#"
if ! tmux has-session -t mize-deploy 2>/dev/null; then
echo "Created new tmux session...."
systemd-run --user --scope --description="mize deploy tmux session" tmux new-session -d -s mize-deploy "nix develop git+file://$SRC/mize --impure"
else
echo "using existing session..."
fi
tmux send-keys -t mize-deploy "deno run --config {config_src}/mize/apps/obsidian-plugin/deno.json build" Enter
tmux send-keys -t mize-deploy "cp -r {config_src}/mize/apps/obsidian-plugin/dist/* {plugin_dir}/" Enter
"#
);
sh!(/bin/sh -c "$cmd")?;
Ok(())
}
pub fn main_deploy(_: ArgMatches) -> MizeResult<()> {
let config_src = cfg_str("c2vi.config_src")?;
let daemon_env = cfg_str("c2vi.deploy.main.daemon_env")?;
unsafe {
std::env::set_var("SRC", &config_src);
}
let cmd = format!(
r#"
if ! tmux has-session -t mize-deploy 2>/dev/null; then
systemd-run --user --scope --description="mize deploy tmux session" tmux new-session -d -s mize-deploy "nix develop git+file://$SRC/mize#buildShell"
else
echo "using existing session..."
fi
tmux send-keys -t mize-deploy "cargo build --manifest-path $SRC/mize/Cargo.toml --bin mize" Enter
tmux send-keys -t mize-deploy 'echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" > {daemon_env}' Enter
tmux send-keys -t mize-deploy "systemctl --user restart mize" Enter
"#
);
sh!(/bin/sh -c "$cmd")?;
Ok(())
}

View File

@@ -0,0 +1,74 @@
use mize::prelude::*;
pub struct CliPart {
id: MizeId,
}
impl MizePart for CliPart {
fn id(&self) -> MizeResult<MizeId> {
Ok(self.id.clone())
}
}
impl CliPart {
pub fn get(name: &str) -> MizeResult<CliPart> {
let mut mize = get_global_mize()?;
let part = mize.get_part(name)?;
Ok(CliPart { id: part.id()? })
}
pub fn set_command(&self, name: &str) -> MizeResult<()> {
let mut args = ItemData::new();
args.set_path("0", name.into_item_data())?;
dyn_call(self.id.clone(), "set_command", args)?;
Ok(())
}
pub fn subcommand<T: Fn(ArgMatches) -> MizeResult<()> + Send + Sync + 'static>(
&self,
subcmd: Command,
action: T,
) -> MizeResult<()> {
let mut subcmd_arg = ItemData::new();
subcmd_arg.set_path("_native", subcmd.native_id)?;
let action_arg = ItemData::fun(Box::new(move |args: ItemData| {
let matches = args.clone().get_path("0")?.native_take_from::<ArgMatches>()?;
action(matches)?;
Ok(ItemData::new())
}))?;
let mut args = ItemData::new();
args.set_path("0", subcmd_arg)?;
args.set_path("1", action_arg)?;
dyn_call(self.id.clone(), "subcommand", args)?;
Ok(())
}
}
pub struct Command {
native_id: u32,
}
pub struct ArgMatches {
#[allow(dead_code)]
native_id: u32,
}
impl FromItemData for ArgMatches {
fn from_itemdata(data: ItemData) -> MizeResult<Self> {
Ok(ArgMatches {
native_id: data.get_path("_native")?.value_u32()?,
})
}
}
impl Command {
pub fn new(name: &str) -> MizeResult<Command> {
let mut args = ItemData::new();
args.set_path("0", name.into_item_data())?;
let mut mize = get_global_mize()?;
let id = mize.id_new_dots("cli.Command")?;
let data = dyn_call(id, "new", args)?;
let native_id: u32 = data.get_path("_native")?.native_take()?;
Ok(Command { native_id })
}
}

152
parts/c2vi/src/mpart.rs Normal file
View File

@@ -0,0 +1,152 @@
mod dash;
mod deploy;
mod generated;
use generated::{CliPart, Command};
use mize::prelude::*;
fn ensure_default(rel: &str, default: ItemData) -> MizeResult<()> {
let mut mize = get_global_mize()?;
let cur = mize
.cur_eval_part()?
.ok_or_else(|| mize_err!("no cur_eval_part"))?;
let full = format!("{}.{}", cur.dot(), rel);
if mize.get_config(&full).is_ok() {
return Ok(());
}
let segs: Vec<&str> = rel.split('.').filter(|s| !s.is_empty()).collect();
let last = *segs.last().ok_or_else(|| mize_err!("empty opt path"))?;
let mut parent = cur.clone();
for seg in &segs[..segs.len() - 1] {
parent = parent.join(seg)?;
}
let original = Some(cur);
mize.set_cur_eval_part(Some(parent))?;
opt(last).default_val(default);
mize.set_cur_eval_part(original)?;
Ok(())
}
fn declare_deploy_defaults() -> MizeResult<()> {
ensure_default("mize_src", "/home/me/work/config/mize".into_item_data())?;
ensure_default("config_src", "/home/me/work/config".into_item_data())?;
ensure_default(
"rsync_excludes",
"--exclude=node_modules --exclude=target --exclude=mize_config.toml --exclude=rust_dist --exclude=deno_dist --exclude=dist --exclude=result --exclude=pkg --exclude /src --exclude obsidian-brat --exclude forked-zed".into_item_data(),
)?;
ensure_default("dash.enable", false.into_item_data())?;
ensure_default("deploy.bin", "mize".into_item_data())?;
ensure_default("deploy.te.remote_dir", "/home/me/here/config".into_item_data())?;
ensure_default("deploy.te.mize_store_dir", "/home/me/host/mize".into_item_data())?;
ensure_default("deploy.te.rsync_chown", "".into_item_data())?;
ensure_default("deploy.mac.remote_dir", "/data/external/config".into_item_data())?;
ensure_default("deploy.mac.mize_store_dir", "/home/me/host/mize".into_item_data())?;
ensure_default("deploy.mac.rsync_chown", "".into_item_data())?;
ensure_default("deploy.mac.mize_bin_dir", "/home/me/here/mize".into_item_data())?;
ensure_default(
"deploy.files.remote_dir",
"/home/files/here/config".into_item_data(),
)?;
ensure_default(
"deploy.files.mize_store_dir",
"/home/files/storage/files/mize".into_item_data(),
)?;
ensure_default("deploy.files.rsync_chown", "".into_item_data())?;
ensure_default(
"deploy.ppc-hosting.remote_dir",
"/root/host/c2vi-config".into_item_data(),
)?;
ensure_default(
"deploy.ppc-hosting.mize_store_dir",
"/root/host/mize".into_item_data(),
)?;
ensure_default(
"deploy.ppc-hosting.rsync_chown",
"--chown=root:root".into_item_data(),
)?;
ensure_default(
"deploy.nico.remote_dir",
"/root/work/config-c2vi".into_item_data(),
)?;
ensure_default(
"deploy.nico.mize_store_dir",
"/root/work/app-data/mize".into_item_data(),
)?;
ensure_default(
"deploy.nico.rsync_chown",
"--chown=root:root".into_item_data(),
)?;
ensure_default(
"deploy.main.daemon_env",
"/home/me/work/app-data/mize/daemon.env".into_item_data(),
)?;
ensure_default(
"deploy.obsidian.plugin_dir",
"/home/me/work/things/.obsidian/plugins/mize".into_item_data(),
)?;
ensure_default(
"deploy.spacetime.module_path",
"/home/me/work/config/mize/marts/spacetime".into_item_data(),
)?;
Ok(())
}
#[unsafe(no_mangle)]
pub extern "C" fn part_c2vi() -> MizeResult<()> {
declare_deploy_defaults()?;
let cli = CliPart::get("cli")?;
cli.set_command("dev")?;
cli.subcommand(Command::new("deploy-lush")?, |m| deploy::remote_deploy(m, "te"))?;
cli.subcommand(Command::new("dlu")?, |m| deploy::remote_deploy(m, "te"))?;
cli.subcommand(Command::new("deploy-mac")?, |m| deploy::new_deploy(m, "mac"))?;
cli.subcommand(Command::new("dmc")?, |m| deploy::new_deploy(m, "mac"))?;
cli.subcommand(Command::new("deploy-files")?, |m| {
deploy::remote_deploy(m, "files")
})?;
cli.subcommand(Command::new("dfi")?, |m| deploy::remote_deploy(m, "files"))?;
cli.subcommand(Command::new("deploy-ppc")?, |m| {
deploy::remote_deploy(m, "ppc-hosting")
})?;
cli.subcommand(Command::new("dpp")?, |m| {
deploy::remote_deploy(m, "ppc-hosting")
})?;
cli.subcommand(Command::new("deploy-nico")?, |m| {
deploy::remote_deploy(m, "nico")
})?;
cli.subcommand(Command::new("dni")?, |m| deploy::remote_deploy(m, "nico"))?;
cli.subcommand(Command::new("deploy-main")?, deploy::main_deploy)?;
cli.subcommand(Command::new("dma")?, deploy::main_deploy)?;
cli.subcommand(Command::new("deploy-obsidian")?, deploy::obsidian_deploy)?;
cli.subcommand(Command::new("do")?, deploy::obsidian_deploy)?;
cli.subcommand(Command::new("deploy-spacetime")?, deploy::deploy_spacetime)?;
cli.subcommand(Command::new("dsp")?, deploy::deploy_spacetime)?;
#[cfg(feature = "desktop")]
{
let enable = get_global_mize()?
.get_config("c2vi.dash.enable")
.ok()
.and_then(|v| v.value_bool().ok())
.unwrap_or(false);
if enable {
dash::launch_c2vi_dashboard();
}
}
Ok(())
}

1
parts/vicinae Submodule

Submodule parts/vicinae added at 8c63ae2ef1