xref: /DADK/dadk/src/context/mod.rs (revision f60cc4eb0593781f9412d78e3277baddfff311bb)
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         self.workdir()
90             .join(format!("bin/{}.img", self.disk_image_basename()))
91     }
92 
93     /// 获取磁盘挂载路径
94     pub fn disk_mount_path(&self) -> PathBuf {
95         self.workdir()
96             .join(format!("bin/mnt/{}", self.disk_image_basename()))
97     }
98 
99     fn disk_image_basename(&self) -> String {
100         let arch: String = self.target_arch().into();
101         format!("disk-image-{}", arch)
102     }
103 
104     /// 获取磁盘镜像大小
105     pub fn disk_image_size(&self) -> usize {
106         self.rootfs().metadata.size
107     }
108 }
109