1 use std::{cell::OnceCell, path::PathBuf}; 2 3 use anyhow::Result; 4 use clap::Parser; 5 use dadk_config::{ 6 common::target_arch::TargetArch, manifest::DadkManifestFile, rootfs::RootFSConfigFile, 7 }; 8 use derive_builder::Builder; 9 use manifest::parse_manifest; 10 11 use crate::{ 12 console::CommandLineArgs, 13 utils::{abs_path, check_dir_exists}, 14 }; 15 16 mod manifest; 17 18 /// DADK的执行上下文 19 #[derive(Debug, Clone, Builder)] 20 pub struct DADKExecContext { 21 pub command: CommandLineArgs, 22 /// DADK manifest file 23 pub manifest: DadkManifestFile, 24 25 /// RootFS config file 26 rootfs: OnceCell<RootFSConfigFile>, 27 } 28 29 pub fn build_exec_context() -> Result<DADKExecContext> { 30 let mut builder = DADKExecContextBuilder::create_empty(); 31 builder.command(CommandLineArgs::parse()); 32 builder.rootfs(OnceCell::new()); 33 parse_manifest(&mut builder).expect("Failed to parse manifest"); 34 let ctx = builder.build()?; 35 ctx.setup_workdir().expect("Failed to setup workdir"); 36 Ok(ctx) 37 } 38 39 impl DADKExecContext { 40 /// 获取工作目录的绝对路径 41 pub fn workdir(&self) -> PathBuf { 42 abs_path(&PathBuf::from(&self.command.workdir)) 43 } 44 45 /// 设置进程的工作目录 46 fn setup_workdir(&self) -> Result<()> { 47 std::env::set_current_dir(&self.workdir()).expect("Failed to set current directory"); 48 Ok(()) 49 } 50 /// Get rootfs configuration 51 pub fn rootfs(&self) -> &RootFSConfigFile { 52 self.rootfs.get_or_init(|| { 53 RootFSConfigFile::load(&self.manifest.metadata.rootfs_config) 54 .expect("Failed to load rootfs config") 55 }) 56 } 57 58 /// Get sysroot directory 59 /// 60 /// If the directory does not exist, or the path is not a folder, an error is returned 61 pub fn sysroot_dir(&self) -> Result<PathBuf> { 62 check_dir_exists(&self.manifest.metadata.sysroot_dir) 63 .map(|p| p.clone()) 64 .map_err(|e| anyhow::anyhow!("Failed to get sysroot dir: {}", e)) 65 } 66 67 /// Get cache root directory 68 /// 69 /// If the directory does not exist, or the path is not a folder, an error is returned 70 pub fn cache_root_dir(&self) -> Result<PathBuf> { 71 check_dir_exists(&self.manifest.metadata.cache_root_dir) 72 .map(|p| p.clone()) 73 .map_err(|e| anyhow::anyhow!("Failed to get cache root dir: {}", e)) 74 } 75 76 #[deprecated] 77 pub fn user_config_dir(&self) -> Result<PathBuf> { 78 check_dir_exists(&self.manifest.metadata.user_config_dir) 79 .map(|p| p.clone()) 80 .map_err(|e| anyhow::anyhow!("Failed to get user config dir: {}", e)) 81 } 82 83 pub fn target_arch(&self) -> TargetArch { 84 self.manifest.metadata.arch 85 } 86 87 /// 获取磁盘镜像的路径,路径由工作目录、架构和固定文件名组成 88 pub fn disk_image_path(&self) -> PathBuf { 89 let arch: String = self.target_arch().into(); 90 self.workdir().join(format!("bin/disk-image-{}.img", arch)) 91 } 92 93 /// 获取磁盘镜像大小 94 pub fn disk_image_size(&self) -> usize { 95 self.rootfs().metadata.size 96 } 97 } 98