assemble_core/startup/initialization/
settings.rs

1use crate::plugins::PluginAware;
2use crate::prelude::PluginManager;
3use crate::project::shared::SharedProject;
4use crate::startup::initialization::{ProjectBuilder, ProjectDescriptor, ProjectGraph};
5use crate::startup::invocation::{Assemble, AssembleAware};
6use parking_lot::RwLock;
7use std::ops::{Deref, DerefMut};
8use std::path::{Path, PathBuf};
9use std::sync::Arc;
10
11/// Declares the configuration required to instantiate and configure the hierarchy of [`SharedProject`](crate::project::SharedProject)
12/// which are part of this build. There's exactly one settings instance that's created per
13/// settings file.
14///
15/// # Assembling a mutli-project build
16/// One of the purposes of the `Settings` object is to allow you to declare projects which are
17/// included in this build.
18///
19/// When included, a [`ProjectDescriptor`][pd] is created which can be used to configure the default
20/// values for several properties of the project.
21///
22/// [pd]: super::descriptor::ProjectDescriptor
23///
24/// # Using Settings in a Settings File
25/// Depends on the builder..
26///
27#[derive(Debug)]
28pub struct Settings {
29    assemble: Arc<RwLock<Assemble>>,
30    plugin_manager: PluginManager<Settings>,
31    project_graph: ProjectGraph,
32    root_dir: PathBuf,
33    settings_file: PathBuf,
34}
35
36impl Settings {
37    /// Create a new [`Settings`](Settings) instance.
38    pub fn new(
39        assemble: &Arc<RwLock<Assemble>>,
40        root_dir: PathBuf,
41        settings_file: PathBuf,
42    ) -> Self {
43        Self {
44            assemble: assemble.clone(),
45            plugin_manager: PluginManager::new(),
46            project_graph: ProjectGraph::new(root_dir.clone()),
47            root_dir,
48            settings_file,
49        }
50    }
51
52    /// Gets the root project descriptor
53    pub fn root_project(&self) -> &ProjectDescriptor {
54        self.project_graph.root_project()
55    }
56
57    /// Gets a mutable reference to the root project descriptor
58    pub fn root_project_mut(&mut self) -> &mut ProjectDescriptor {
59        self.project_graph.root_project_mut()
60    }
61
62    /// Adds a child project to the root project
63    pub fn add_project<S: AsRef<str>, F: FnOnce(&mut ProjectBuilder)>(
64        &mut self,
65        path: S,
66        configure: F,
67    ) {
68        self.project_graph.project(path, configure)
69    }
70
71    /// Includes a project a path.
72    pub fn include<S: AsRef<str>>(&mut self, path: S) {
73        self.add_project(path, |_| {});
74    }
75
76    /// Includes a project a path.
77    pub fn include_all<S: AsRef<str>, I: IntoIterator<Item = S>>(&mut self, paths: I) {
78        for path in paths {
79            self.include(path)
80        }
81    }
82
83    /// Find a project within this build
84    pub fn find_project(&self, path: impl AsRef<Path>) -> Option<&ProjectDescriptor> {
85        self.project_graph.find_project(path)
86    }
87
88    /// Find a project within this build
89    pub fn find_project_mut(&mut self, path: impl AsRef<Path>) -> Option<&mut ProjectDescriptor> {
90        self.project_graph.find_project_mut(path)
91    }
92
93    /// Gets the child project of a given project
94    pub fn children_projects(
95        &self,
96        proj: &ProjectDescriptor,
97    ) -> impl IntoIterator<Item = &ProjectDescriptor> {
98        self.project_graph.children_projects(proj)
99    }
100
101    /// Gets the root directory of this build
102    pub fn root_dir(&self) -> &Path {
103        &self.root_dir
104    }
105
106    pub fn set_build_file_name(&mut self, path: impl AsRef<str>) {
107        self.project_graph
108            .set_default_build_file_name(path.as_ref())
109    }
110
111    /// Gets the assemble instance
112    pub fn assemble(&self) -> &Arc<RwLock<Assemble>> {
113        &self.assemble
114    }
115    pub fn settings_file(&self) -> &Path {
116        &self.settings_file
117    }
118
119    /// Gets the project graph
120    pub fn project_graph(&self) -> &ProjectGraph {
121        &self.project_graph
122    }
123}
124
125/// A type that's aware of the settings value
126pub trait SettingsAware {
127    fn with_settings<F: FnOnce(&Settings) -> R, R>(&self, func: F) -> R;
128    fn with_settings_mut<F: FnOnce(&mut Settings) -> R, R>(&mut self, func: F) -> R;
129}
130
131impl SettingsAware for Settings {
132    fn with_settings<F: FnOnce(&Settings) -> R, R>(&self, func: F) -> R {
133        (func)(self)
134    }
135
136    fn with_settings_mut<F: FnOnce(&mut Settings) -> R, R>(&mut self, func: F) -> R {
137        (func)(self)
138    }
139}
140
141impl SettingsAware for Arc<RwLock<Settings>> {
142    fn with_settings<F: FnOnce(&Settings) -> R, R>(&self, func: F) -> R {
143        (func)(self.read().deref())
144    }
145
146    fn with_settings_mut<F: FnOnce(&mut Settings) -> R, R>(&mut self, func: F) -> R {
147        (func)(self.write().deref_mut())
148    }
149}
150
151impl PluginAware for Settings {
152    fn plugin_manager(&self) -> &PluginManager<Self> {
153        &self.plugin_manager
154    }
155
156    fn plugin_manager_mut(&mut self) -> &mut PluginManager<Self> {
157        &mut self.plugin_manager
158    }
159}
160
161impl<S: SettingsAware> AssembleAware for S {
162    fn with_assemble<F, R>(&self, func: F) -> R
163    where
164        F: FnOnce(&Assemble) -> R,
165    {
166        self.with_settings(|s| s.assemble.with_assemble(func))
167    }
168
169    fn with_assemble_mut<F, R>(&mut self, func: F) -> R
170    where
171        F: FnOnce(&mut Assemble) -> R,
172    {
173        self.with_settings_mut(|s| s.assemble.with_assemble_mut(func))
174    }
175}