bricks/libs/
install_lib.rs

1use std::fs;
2
3use anyhow::{bail, Result};
4
5use crate::{
6    build,
7    cli::{
8        args::{BuildCommand, InstallCommand},
9        init::templates,
10        install, pretty,
11    },
12    config::{
13        lib::{Lib, LibKind, LibPathificationError},
14        overrides::Overrides,
15        Config,
16    },
17};
18
19use super::{copy_dir::copy_dir, git_utils::RepositoryExt};
20
21pub fn install_lib(name: &str, lib: &Lib, force: bool, silent: bool) -> Result<Option<Overrides>> {
22    if !silent {
23        pretty::msg("install", name);
24    }
25    match lib.kind {
26        LibKind::System => {
27            // you don't need to do anything here.
28            Ok(None)
29        }
30        LibKind::Git => {
31            let Some(repo_uri) = lib.normalize_repo() else {
32                bail!("{} is missing the `repo` property", name);
33            };
34
35            // if the library version is already there, use that (and dont do anything)
36            let versioned_path = lib.pathify_repo()?;
37            if !force && fs::exists(&versioned_path)? {
38                // TODO: return the Overrides!
39                return Ok(None);
40            }
41
42            // check if the FULL lib already exists
43            // if the library isn't already installed:
44            // git clone it from the provided source
45            // else just open it
46            let full_path = lib.pathify_repo_no_version()?.join("full");
47            let repo: git2::Repository = if !fs::exists(&full_path)? {
48                pretty::info(format!("cloning {}", &repo_uri));
49                git2::Repository::clone(&repo_uri, &full_path)?
50            } else {
51                let repo = git2::Repository::open(&full_path)?;
52                pretty::info(format!("fetching all {}", &repo_uri));
53                repo.fetch_all(&repo_uri)?;
54                repo
55            };
56
57            // checkout to requested version
58            let Some(ref version) = lib.version else {
59                return Err(LibPathificationError::VersionMissing.into());
60            };
61            repo.checkout(version)?;
62            pretty::info(format!("checked out to version {}", version));
63
64            // copy the required version to another directory and use that
65            copy_dir(&full_path, &versioned_path, &[".git"])?;
66
67            // in the library's directory:
68            // read the config file
69            let foreign_config_file = match fs::read_to_string(versioned_path.join("brick.toml")) {
70                Ok(v) => v,
71                Err(err) => {
72                    pretty::warning(format!(
73                        "got error while reading {}: {}",
74                        versioned_path.join("brick.toml").display(),
75                        err
76                    ));
77                    pretty::warning("fallback to default config");
78                    templates::config(name, "library", "c", "unknown").to_string()
79                }
80            };
81
82            let foreign_config: Config = toml::from_str(&foreign_config_file)?;
83            // run bricks install
84            install::install(
85                &foreign_config,
86                InstallCommand {
87                    path: String::from(versioned_path.to_string_lossy()),
88                    force,
89                    silent: true,
90                },
91            )?;
92
93            // run bricks build
94            // PERF: remove clone
95            let overrides = match lib.overrides.clone() {
96                Some(v) => Some(v),
97                None => foreign_config.brick.overrides.clone(), // PERF: remove clone
98            };
99
100            let build_cmd = BuildCommand {
101                force: true,
102                emit_compile_commands: false,
103                path: String::from(versioned_path.to_string_lossy()),
104                silent: true,
105            };
106            let override_build = match overrides {
107                Some(ref v) => &v.build,
108                None => &None,
109            };
110            build::build(&foreign_config, build_cmd, override_build.clone())?;
111
112            Ok(overrides)
113        }
114    }
115}