Skip to main content

helm_schema/
chart_source.rs

1use std::path::Path;
2
3use vfs::VfsPath;
4
5use crate::chart::discovery::{extract_chart_archive, is_chart_archive};
6use crate::error::{CliError, EngineResult};
7use crate::load_budget::LoadBudget;
8
9/// Open root chart directory shared by config discovery and chart analysis.
10#[derive(Debug, Clone)]
11pub struct RootChartSource {
12    chart_dir: VfsPath,
13}
14
15impl RootChartSource {
16    /// Opens a physical chart directory or extracts a packaged chart archive.
17    ///
18    /// # Errors
19    ///
20    /// Returns an error when the path cannot be inspected, is neither a
21    /// directory nor a supported chart archive, or archive extraction fails.
22    pub fn open(path: &Path, load_budget: LoadBudget) -> EngineResult<Self> {
23        let metadata = std::fs::metadata(path)?;
24        let chart_dir = if metadata.is_dir() {
25            let path = path.to_string_lossy();
26            VfsPath::new(vfs::PhysicalFS::new(path.as_ref()))
27        } else if metadata.is_file()
28            && path
29                .file_name()
30                .is_some_and(|name| is_chart_archive(&name.to_string_lossy()))
31        {
32            let parent = path.parent().unwrap_or_else(|| Path::new("."));
33            let parent = parent.to_string_lossy();
34            let root = VfsPath::new(vfs::PhysicalFS::new(parent.as_ref()));
35            let file_name = path
36                .file_name()
37                .map(|name| name.to_string_lossy())
38                .ok_or_else(|| {
39                    CliError::CliValidation(format!(
40                        "chart archive path has no file name: {}",
41                        path.display()
42                    ))
43                })?;
44            extract_chart_archive(&root.join(file_name.as_ref())?, load_budget)?
45        } else {
46            return Err(CliError::CliValidation(format!(
47                "chart source must be a directory or .tgz/.tar.gz archive: {}",
48                path.display()
49            )));
50        };
51
52        Ok(Self { chart_dir })
53    }
54
55    /// Returns the root VFS directory used for both config and chart loading.
56    #[must_use]
57    pub fn chart_dir(&self) -> &VfsPath {
58        &self.chart_dir
59    }
60
61    /// Consumes the source and returns its root VFS directory.
62    #[must_use]
63    pub fn into_chart_dir(self) -> VfsPath {
64        self.chart_dir
65    }
66}