diff --git a/src/api/app/actions/build/bootstrap.rs b/src/api/app/actions/build/bootstrap.rs index 70afa4f..2c41b37 100644 --- a/src/api/app/actions/build/bootstrap.rs +++ b/src/api/app/actions/build/bootstrap.rs @@ -1,4 +1,4 @@ -use std::{path::Path, sync::Arc}; +use std::{collections::HashSet, path::Path, sync::Arc}; use anyhow::{Context, Result}; use futures::{StreamExt, TryStreamExt}; @@ -12,21 +12,37 @@ impl App { pub async fn action_bootstrap(self: Arc, base: &Path) -> Result<()> { let mut list = vec![]; - if let Some(path) = self.server.read().await.as_ref().map(|(path, _)| path.clone()) { - list.push(path.parent().unwrap().join("config")); + if let Some((server_path, server)) = &*self.server.read().await { + if let Some((network_path, network)) = &*self.network.read().await { + list.push(network_path.parent().unwrap().join("groups").join("global").join("config")); + + if let Some(entry) = network.servers.get(&server.name) { + for group in &entry.groups { + list.push(network_path.parent().unwrap().join("groups").join(group).join("config")); + } + } + } + + list.push(server_path.parent().unwrap().join("config")); } - // TODO: use self.network + let mut changed_variables = HashSet::new(); + + for (k, v) in &self.existing_lockfile.read().await.as_ref().map(|lock| lock.vars.clone()).unwrap_or_default() { + if !self.resolve_variable_value(k).await.is_some_and(|value| &value == v) { + changed_variables.insert(k.clone()); + } + } for entry in list { - self.clone().action_bootstrap_recursive(base, &entry).await?; + self.clone().action_bootstrap_recursive(base, &entry, &changed_variables).await?; } Ok(()) } /// Recursively walks through the directory and bootstraps every eccountered file - pub async fn action_bootstrap_recursive(self: Arc, output_base: &Path, input_base: &Path) -> Result<()> { + pub async fn action_bootstrap_recursive(self: Arc, output_base: &Path, input_base: &Path, changed_variables: &HashSet) -> Result<()> { let output_base = Arc::new(output_base); let input_base = Arc::new(input_base); @@ -51,7 +67,7 @@ impl App { return Ok(()); } - app.action_bootstrap_file(&output_base, &input_base, entry.path()) + app.action_bootstrap_file(&output_base, &input_base, entry.path(), &changed_variables) .await .with_context(|| format!("Bootstrapping file: {:?}", entry.path())) } @@ -83,10 +99,14 @@ impl App { /// Process a single file. Calls [`Self::should_bootstrap_file`] on the file to decide if it should process it /// or copy it. - pub async fn action_bootstrap_file(self: Arc, output_base: &Path, input_base: &Path, file: &Path) -> Result<()> { - let lockfile_entry = self.existing_lockfile.read().await.as_ref().map(|lock| lock.bootstrapped_files.get(file)).flatten().cloned(); - - // TODO: should cancel? + pub async fn action_bootstrap_file( + self: Arc, + output_base: &Path, + input_base: &Path, + file: &Path, + changed_variables: &HashSet + ) -> Result<()> { + //let lockfile_entry = self.existing_lockfile.read().await.as_ref().map(|lock| lock.bootstrapped_files.get(file)).flatten().cloned(); let relative = input_base.try_diff_to(file)?; diff --git a/src/api/app/actions/lockfile/mod.rs b/src/api/app/actions/lockfile/mod.rs index cac6044..b583c67 100644 --- a/src/api/app/actions/lockfile/mod.rs +++ b/src/api/app/actions/lockfile/mod.rs @@ -12,6 +12,7 @@ impl App { Ok(()) } + /// Read .mcman.lock from the output directory pub async fn read_existing_lockfile(&self, base: &Path) -> Result<()> { let path = base.join(LOCKFILE); @@ -23,6 +24,7 @@ impl App { Ok(()) } + /// Write contents of the newly generated lockfile into the output directory pub async fn write_lockfile(&self, base: &Path) -> Result<()> { let lockfile = self.new_lockfile.read().await; @@ -31,8 +33,8 @@ impl App { Ok(()) } + /// Adds an addon to the new_lockfile pub async fn add_addon_to_lockfile(self: Arc, addon: Addon) { - println!("Added Addon to lockfile"); self.new_lockfile.write().await.addons.push(addon); } } diff --git a/src/api/app/vars.rs b/src/api/app/vars.rs index fd64e98..d6be4b4 100644 --- a/src/api/app/vars.rs +++ b/src/api/app/vars.rs @@ -54,28 +54,28 @@ impl App { // TODO actual expressions like ternary // TODO recursive expansions - let value = self.resolve_variable_value(expr).await?; + let value = self.resolve_variable_value(expr).await; Ok((value.unwrap_or_else(|| expr.to_owned()), visited)) } - pub async fn resolve_variable_value(&self, key: &str) -> Result> { + pub async fn resolve_variable_value(&self, key: &str) -> Option { if let Some((_, server)) = &*self.server.read().await { if let Some(v) = server.variables.get(key).cloned() { - return Ok(Some(v)); + return Some(v); } } if let Some((_, network)) = &*self.network.read().await { if let Some(v) = network.variables.get(&format!("network_{key}")).cloned() { - return Ok(Some(v)); + return Some(v); } } if let Ok(v) = std::env::var(key) { - return Ok(Some(v)); + return Some(v); } - Ok(None) + None } } diff --git a/src/api/models/network/mod.rs b/src/api/models/network/mod.rs index e6417a7..16f2397 100644 --- a/src/api/models/network/mod.rs +++ b/src/api/models/network/mod.rs @@ -8,4 +8,11 @@ pub const NETWORK_TOML: &str = "network.toml"; pub struct Network { pub name: String, pub variables: HashMap, + + pub servers: HashMap, +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)] +pub struct ServerEntry { + pub groups: Vec, } diff --git a/src/api/sources/modrinth/mod.rs b/src/api/sources/modrinth/mod.rs index e7ae1da..a8eeb67 100644 --- a/src/api/sources/modrinth/mod.rs +++ b/src/api/sources/modrinth/mod.rs @@ -14,11 +14,9 @@ pub use models::*; pub struct ModrinthAPI<'a>(pub &'a App); -static API_URL: &str = "https://api.modrinth.com/v2"; - impl<'a> ModrinthAPI<'a> { pub async fn fetch_api(&self, url: String) -> Result { - self.0.http_get_json(&*format!("{API_URL}/{url}")).await + self.0.http_get_json(&*format!("{}/{url}", self.0.options.api_urls.modrinth)).await } pub async fn fetch_project(&self, id: &str) -> Result { @@ -102,7 +100,7 @@ impl<'a> ModrinthAPI<'a> { pub async fn version_from_hash(&self, hash: &str, algo: &str) -> Result { self.fetch_api(format!( - "{API_URL}/version_file/{hash}{}", + "version_file/{hash}{}", if algo.is_empty() || algo == "sha1" { String::new() } else {