1use crate::{
4 environment as e, git, packages, state::State, Data, Facts, FileSystem, Opts, SystemUnit,
5 Timestamp, UnitAllocator, UnitId,
6};
7use anyhow::Error;
8use directories::BaseDirs;
9use serde::Deserialize;
10use std::collections::HashMap;
11use std::fmt;
12use std::path::Path;
13
14#[macro_use]
15mod macros;
16mod copy_dir;
17mod download;
18mod download_and_run;
19mod from_db;
20mod git_sync;
21mod install;
22mod link;
23mod link_dir;
24mod only_for;
25
26use self::copy_dir::CopyDir;
27use self::download::Download;
28use self::download_and_run::DownloadAndRun;
29use self::from_db::FromDb;
30use self::git_sync::GitSync;
31use self::install::Install;
32use self::link::Link;
33use self::link_dir::LinkDir;
34use self::only_for::OnlyFor;
35
36pub enum Translation<'a> {
38 Keep,
40 Discard,
42 Expand(&'a [System]),
44}
45
46macro_rules! system_impl {
47 ($($name:ident,)*) => {
48 impl System {
49 pub fn translate(&self) -> Translation<'_> {
50 use self::System::*;
51
52 match self {
53 $($name(system) => system.translate(),)*
54 }
55 }
56
57 pub fn id(&self) -> Option<&str> {
59 use self::System::*;
60
61 match self {
62 $($name(system) => system.id(),)*
63 }
64 }
65
66 pub fn requires(&self) -> &[String] {
68 use self::System::*;
69
70 match self {
71 $($name(system) => system.requires(),)*
72 }
73 }
74
75 #[allow(unused)]
77 pub fn apply<E>(&self, input: $crate::system::SystemInput<E>)
78 -> Result<Vec<$crate::system::SystemUnit>, Error>
79 where
80 E: Copy + $crate::environment::Environment,
81 {
82 use anyhow::{Context as _, anyhow};
83 use self::System::*;
84
85 let res = match self {
86 $($name(system) => system.apply(input),)*
87 };
88
89 res.with_context(|| anyhow!("Failed to run system: {:?}", self))
90 }
91 }
92
93 impl fmt::Display for System {
94 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
95 match *self {
96 $(
97 System::$name(ref system) => {
98 if let Some(id) = system.id() {
99 write!(fmt, "{}: {}", id, system)
100 } else {
101 system.fmt(fmt)
102 }
103 }
104 )*
105 }
106 }
107 }
108 }
109}
110
111#[derive(Deserialize, Debug, PartialEq, Eq)]
112#[serde(tag = "type")]
113pub enum System {
114 #[serde(rename = "copy-dir")]
115 CopyDir(CopyDir),
116 #[serde(rename = "link-dir")]
117 LinkDir(LinkDir),
118 #[serde(rename = "install")]
119 Install(Install),
120 #[serde(rename = "download-and-run")]
121 DownloadAndRun(DownloadAndRun),
122 #[serde(rename = "download")]
123 Download(Download),
124 #[serde(rename = "link")]
125 Link(Link),
126 #[serde(rename = "git-sync")]
127 GitSync(GitSync),
128 #[serde(rename = "only-for")]
129 OnlyFor(OnlyFor),
130 #[serde(rename = "from-db")]
131 FromDb(FromDb),
132}
133
134system_impl![
135 CopyDir,
136 LinkDir,
137 Install,
138 DownloadAndRun,
139 Download,
140 Link,
141 GitSync,
142 OnlyFor,
143 FromDb,
144];
145
146#[derive(Clone, Copy)]
148pub struct SystemInput<'a, 'f, E>
149where
150 E: e::Environment,
151{
152 pub root: &'a Path,
154 pub base_dirs: Option<&'a BaseDirs>,
156 pub facts: &'a Facts,
158 pub data: &'a Data,
160 pub environment: E,
162 pub packages: &'a packages::Provider,
164 pub allocator: &'a UnitAllocator,
166 pub file_system: &'a FileSystem<'f>,
168 pub state: &'a State<'a>,
170 pub now: Timestamp,
172 pub opts: &'a Opts,
174 pub git_system: &'a dyn git::GitSystem,
176}
177
178#[derive(Default)]
180pub enum Dependency<'a> {
181 Transitive(&'a [String]),
183 Direct(UnitId),
185 #[default]
187 None,
188}
189
190impl<'a> Dependency<'a> {
191 pub fn resolve(
193 &self,
194 systems: &HashMap<&'a str, Dependency<'a>>,
195 ) -> impl IntoIterator<Item = crate::unit::Dependency> {
196 use std::collections::VecDeque;
197
198 let mut ids = Vec::new();
199
200 let mut queue = VecDeque::new();
201 queue.push_back(self);
202
203 while let Some(dependency) = queue.pop_front() {
204 match *dependency {
205 Dependency::Transitive(requires) => {
206 for id in requires {
207 queue.extend(systems.get(id.as_str()));
208 }
209 }
210 Dependency::Direct(id) => ids.push(crate::unit::Dependency::Unit(id)),
211 Dependency::None => continue,
212 }
213 }
214
215 ids
216 }
217}