corge/tool/
dependency_source_fetcher.rs

1mod fs_registry;
2mod git_registry;
3
4use crate::config::{Config, Dependency, Registry};
5use anyhow::{Context, Result};
6use std::collections::HashMap;
7use std::fs;
8use std::path::PathBuf;
9
10
11pub struct Artifact {
12    pub path: PathBuf,
13    pub dependency: Dependency,
14}
15
16/**
17    Converts a dependency tree into a flat dependency list.
18 */
19pub struct DependencySourceFetcher {
20    registries: HashMap<String, Registry>,
21    dependencies: Vec<Dependency>,
22}
23
24impl DependencySourceFetcher {
25    pub fn new(registries: HashMap<String, Registry>, dependencies: Vec<Dependency>,) -> Self {
26        Self {
27            registries,
28            dependencies,
29        }
30    }
31
32    /* Fetch dependencies recursively and return a flat vector */
33    pub fn fetch(&self, sources_dir: &PathBuf) -> Result<Vec<Artifact>> {
34        let mut artifacts = vec![];
35
36        for dependency in &self.dependencies {
37            let artifact_path = sources_dir.join(&dependency.name);
38
39            let registry = self.registries.get(&dependency.registry_name)
40                .ok_or_else(|| anyhow::anyhow!("Registry '{}' not found", &dependency.registry_name))?;
41
42            let dependency_fetched = fs::exists(&artifact_path)
43                .with_context(|| format!("Failed to check if dependency '{}' is fetched", dependency.name))?;
44
45            if dependency_fetched {
46                log::info!("Skipping already fetched dependency '{}'", dependency.name);
47            } else {
48                fetch_dependency(registry, dependency, &artifact_path)?;
49            }
50
51            artifacts.push(
52                Artifact {
53                    path: sources_dir.join(&dependency.name),
54                    dependency: dependency.clone()
55                }
56            );
57
58            let config_path = sources_dir.join(&dependency.name).join("build.yaml");
59            let config_str = fs::read_to_string(config_path)
60                .with_context(|| format!("Failed to read build.yaml for dependency {}", dependency.name))?;
61
62            let config: Config = serde_yaml::from_str(&config_str)
63                .with_context(|| format!("Failed to parse build.yaml for dependency {}", dependency.name))?;
64
65            let children_artifacts = DependencySourceFetcher::new(config.registries, config.dependencies)
66                .fetch(sources_dir)
67                .with_context(|| format!("Failed to fetch dependencies for dependency {}", dependency.name))?;
68
69            artifacts.extend(children_artifacts);
70        }
71
72        Ok(artifacts)
73    }
74}
75
76fn fetch_dependency(registry: &Registry, dependency: &Dependency, artifact_path: &PathBuf) -> Result<()> {
77    match registry {
78        Registry::Git { url, branch } => {
79            log::info!("Fetching dependency '{}' from 'git' repository {}", dependency.name, url);
80            git_registry::fetch_git_dependency(
81                url,
82                branch,
83                dependency,
84                artifact_path
85            ).with_context(|| format!("Failed to fetch dependency '{}' from 'git' repository {}", dependency.name, url))
86        },
87        Registry::FileSystem(repository_path) => {
88            log::info!("Fetching dependency '{}' from 'fs' repository {:?}", dependency.name, repository_path);
89            fs_registry::fetch_fs_dependency(
90                repository_path.as_ref(),
91                dependency,
92                artifact_path
93            ).with_context(|| format!("Failed to fetch dependency '{}' from 'fs' repository {}", dependency.name, repository_path))
94        }
95    }
96}