use std::{ fs::{self}, io::{Cursor, Write}, path::PathBuf, }; use anyhow::Context; use bindings::{ component::churn_tasks::{http, process::Process}, exports::component::churn_tasks::task::Guest, }; use flate2::bufread::GzDecoder; use tar::Archive; #[allow(warnings)] mod bindings; struct Component; impl Guest for Component { fn id() -> String { "clank/dev-packages".into() } fn should_run() -> bool { if !std::path::PathBuf::from("/usr/local/bin/starship").exists() { return true; }; if !std::path::PathBuf::from("/root/.bashrc").exists() { return true; }; if let Ok(content) = std::fs::read_to_string("/root/.bashrc") { if !content.contains("starship") { return true; } } if !std::path::PathBuf::from("/usr/local/bin/zellij").exists() { return true; }; false } fn execute() { println!("running dev-packages installation"); Process::new().run_process( &[ "bash", "-c", "curl -sS https://starship.rs/install.sh | sh -s -- --force", ] .into_iter() .map(|i| i.to_string()) .collect::>(), ); println!("downloaded starship"); if !std::path::PathBuf::from("/root/.bashrc").exists() { println!("appending to bashrc"); if let Ok(content) = std::fs::read_to_string("/root/.bashrc") { if !content.contains("starship") { let mut bashrc = std::fs::File::options() .write(true) .open("/root/.bashrc") .expect("failed to open bash"); bashrc .write_all(r#"eval "$(starship init bash)"#.as_bytes()) .expect("failed to write to bashrc file"); } } } else { let mut bashrc = std::fs::File::create("/root/.bashrc").expect("failed to open bash"); bashrc .write_all(r#"eval "$(starship init bash)""#.as_bytes()) .expect("failed to write to bashrc file"); } println!("installing zellij"); if !PathBuf::from("/usr/local/bin/zellij").exists() { if let Err(err) = install_zellij() { panic!("failed to install zellij: {}", err); } } } } fn install_zellij() -> anyhow::Result<()> { let url = "https://github.com/zellij-org/zellij/releases/download/v0.41.2/zellij-x86_64-unknown-linux-musl.tar.gz"; // TODO: Until this is merged: https://github.com/bytecodealliance/wasmtime/pull/9582 we just spawn a runtime println!("getting zellij"); let content = http::Client::new().get(url); println!("creating tempdir"); let temp_dir = PathBuf::from("/tmp/zellij_install/"); if let Err(e) = std::fs::remove_dir_all(&temp_dir) { println!("failed to remove tmp dir: {e}"); } std::fs::create_dir_all(&temp_dir).context("creating tmp dir")?; let mut zellij_archive = std::fs::File::create(temp_dir.join("zellij.tar.gz"))?; zellij_archive.write_all(&content)?; zellij_archive.flush()?; Process::new().run_process( &[ "tar", "-xvf", &temp_dir.join("zellij.tar.gz").display().to_string(), "-C", &temp_dir.display().to_string(), ] .into_iter() .map(|i| i.to_string()) .collect::>(), ); // Move binary to /usr/local/bin println!("move binary"); let binary_path = temp_dir.join("zellij"); fs::File::create("/usr/local/bin/zellij")?; fs::copy(&binary_path, "/usr/local/bin/zellij")?; Process::new().run_process( &["chmod", "+x", "/usr/local/bin/zellij"] .into_iter() .map(|i| i.to_string()) .collect::>(), ); // Set executable permissions using std::fs::Permissions #[cfg(unix)] { //use std::os::unix::fs::PermissionsExt; //let mut perms = fs::metadata("/usr/local/bin/zellij")?.permissions(); //perms.set_mode(0o755); //fs::set_permissions("/usr/local/bin/zellij", perms) // .context("Failed to set executable permissions")?; } Ok(()) } bindings::export!(Component with_types_in bindings);