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
build_exec_context() -> Result<DADKExecContext>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 /// 获取工作目录的绝对路径
workdir(&self) -> PathBuf41 pub fn workdir(&self) -> PathBuf {
42 abs_path(&PathBuf::from(&self.command.workdir))
43 }
44
45 /// 设置进程的工作目录
setup_workdir(&self) -> Result<()>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
rootfs(&self) -> &RootFSConfigFile51 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
sysroot_dir(&self) -> Result<PathBuf>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
cache_root_dir(&self) -> Result<PathBuf>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]
user_config_dir(&self) -> Result<PathBuf>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
target_arch(&self) -> TargetArch83 pub fn target_arch(&self) -> TargetArch {
84 self.manifest.metadata.arch
85 }
86
87 /// 获取磁盘镜像的路径,路径由工作目录、架构和固定文件名组成
disk_image_path(&self) -> PathBuf88 pub fn disk_image_path(&self) -> PathBuf {
89 self.workdir()
90 .join(format!("bin/{}.img", self.disk_image_basename()))
91 }
92
93 /// 获取磁盘挂载路径
disk_mount_path(&self) -> PathBuf94 pub fn disk_mount_path(&self) -> PathBuf {
95 self.workdir()
96 .join(format!("bin/mnt/{}", self.disk_image_basename()))
97 }
98
disk_image_basename(&self) -> String99 fn disk_image_basename(&self) -> String {
100 let arch: String = self.target_arch().into();
101 format!("disk-image-{}", arch)
102 }
103
104 /// 获取磁盘镜像大小
disk_image_size(&self) -> usize105 pub fn disk_image_size(&self) -> usize {
106 self.rootfs().metadata.size
107 }
108 }
109