1use url_source::UrlSource;
2
3use crate::resolver::Install;
4use crate::sources::file_source::FileSource;
5use crate::sources::registry_source::RegistrySource;
6use crate::{config::DependencyOptions, sources::git_source::GitSource};
7use crate::{dependency::Dependency, sources::url_source};
8use crate::{resolver::Resolver, sources::dir_source::DirSource};
9use log::*;
10use std::path::Path;
11
12pub trait Source: SourceClone {
13 fn install(&self, dependency: &Dependency, path: &Path) -> std::io::Result<()>;
14
15 fn installed(&self, dependency: &Dependency, destination: &Path) -> bool {
16 let destination = destination.join(dependency.clone().name);
17 destination.exists()
18 }
19
20 fn update_resolver(
21 &self,
22 resolver: &mut Resolver,
23 dependency: &Dependency,
24 destination: &Path,
25 ) {
26 let project_dir = destination.parent().unwrap();
27 let destination = destination.join(dependency.clone().name);
28 let config_path = destination.join("Smaug.toml");
29 let config = crate::config::load(&config_path).expect("Could not find Smaug.toml");
30 debug!("Package config: {:?}", config);
31 let package = config.package.expect("No package configuration found.");
32
33 for (from, to) in package.installs {
34 let install_source = from.to_path(destination.as_path());
35 let install_destination = to.to_path(project_dir);
36
37 let install = Install {
38 from: install_source,
39 to: install_destination,
40 };
41
42 resolver.installs.push(install);
43 }
44
45 let mut requires = package
46 .requires
47 .iter()
48 .map(|require| {
49 let package_file = require.to_path(destination.clone());
50 trace!("Checking package file {:?}", package_file);
51
52 if package_file.exists() {
53 trace!("package file exists");
54 format!("smaug/{}/{}", dependency.name, require)
55 } else {
56 trace!("package file does not exists");
57 require.to_string()
58 }
59 })
60 .collect();
61 resolver.requires.append(&mut requires);
62 }
63}
64
65pub trait SourceClone {
66 fn clone_box(&self) -> Box<dyn Source>;
67}
68
69pub fn from_dependency_options(options: &DependencyOptions) -> Option<Box<dyn Source>> {
70 match options {
71 DependencyOptions::Git {
72 repo,
73 branch,
74 rev,
75 tag,
76 } => Some(Box::new(GitSource {
77 repo: repo.clone(),
78 branch: branch.clone(),
79 rev: rev.clone(),
80 tag: tag.clone(),
81 })),
82 DependencyOptions::Dir { dir: path } => Some(Box::new(DirSource {
83 path: path.to_path_buf(),
84 })),
85 DependencyOptions::File { file: path } => Some(Box::new(FileSource {
86 path: path.to_path_buf(),
87 })),
88 DependencyOptions::Url { url } => Some(Box::new(UrlSource {
89 url: url.to_string(),
90 })),
91 DependencyOptions::Registry { version } => Some(Box::new(RegistrySource {
92 version: version.to_string(),
93 })),
94 }
95}
96
97impl<T> SourceClone for T
98where
99 T: 'static + Source + Clone,
100{
101 fn clone_box(&self) -> Box<dyn Source> {
102 Box::new(self.clone())
103 }
104}
105
106impl Clone for Box<dyn Source> {
107 fn clone(&self) -> Box<dyn Source> {
108 self.clone_box()
109 }
110}