Skip to main content

zoi_install/
plan.rs

1use crate::resolver::InstallNode;
2use crate::util;
3use anyhow::Result;
4use rayon::prelude::*;
5use std::collections::HashMap;
6use zoi_core::types;
7
8use std::path::PathBuf;
9
10#[derive(Clone)]
11pub struct PrebuiltDetails {
12    pub info: types::PrebuiltInfo,
13    pub download_size: u64,
14    pub installed_size: u64,
15}
16
17#[derive(Clone)]
18pub enum InstallAction {
19    DownloadAndInstall(PrebuiltDetails),
20    InstallFromArchive(PathBuf),
21    BuildAndInstall,
22}
23
24/// Creates an execution plan for installing the resolved dependency graph.
25///
26/// This function decides the Install Action for each package:
27/// - Download and Install: If a pre-built archive exists in the registry for
28///   the target platform and the user didn't force a build.
29/// - Build and Install: If no pre-built archive is available, or if the
30///   user explicitly requested a build (via `--build` or `--type source`).
31///
32/// It utilizes `rayon` for parallel evaluation of pre-built availability across
33/// mirrors and registries.
34pub fn create_install_plan(
35    graph: &HashMap<String, InstallNode>,
36    build_type: Option<&str>,
37    build: bool,
38) -> Result<HashMap<String, InstallAction>> {
39    let plan: HashMap<String, InstallAction> = graph
40        .par_iter()
41        .map(|(id, node)| {
42            if (build
43                || (build_type.is_some()
44                    && build_type != Some("pre-compiled")
45                    && build_type != Some("pre-built")))
46                && !node.source.ends_with(".zpa")
47                && !node.source.ends_with(".zsa")
48            {
49                return (id.clone(), InstallAction::BuildAndInstall);
50            }
51
52            if node.source.ends_with(".zpa") || node.source.ends_with(".zsa") {
53                return (
54                    id.clone(),
55                    InstallAction::InstallFromArchive(PathBuf::from(&node.source)),
56                );
57            }
58
59            let action = match util::find_prebuilt_info(node) {
60                Ok(Some(info)) => {
61                    let (down_size, inst_size) =
62                        util::get_package_sizes(&node.pkg, &node.registry_handle, &node.version);
63
64                    InstallAction::DownloadAndInstall(PrebuiltDetails {
65                        info,
66                        download_size: down_size,
67                        installed_size: inst_size,
68                    })
69                }
70                Ok(None) => InstallAction::BuildAndInstall,
71                Err(e) => {
72                    eprintln!(
73                        "Error finding prebuilt info for {}: {}. Assuming build.",
74                        node.pkg.name, e
75                    );
76                    InstallAction::BuildAndInstall
77                }
78            };
79            (id.clone(), action)
80        })
81        .collect();
82
83    Ok(plan)
84}