diff --git a/Cargo.lock b/Cargo.lock index 878f346..e6d27e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -505,7 +505,7 @@ dependencies = [ [[package]] name = "rgl" -version = "0.1.7" +version = "0.1.8" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index ce9622f..fc32ef6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ -[[bin]] -name = "rgl" - [package] name = "rgl" -version = "0.1.7" +version = "0.1.8" edition = "2021" +[[bin]] +name = "rgl" + [dependencies] anyhow = "1.0.75" clap = { version = "4.3.22", features = ["cargo"] } diff --git a/src/rgl/cache.rs b/src/rgl/cache.rs index 96914d6..c1b44b9 100644 --- a/src/rgl/cache.rs +++ b/src/rgl/cache.rs @@ -39,17 +39,18 @@ fn copy_cached(from: &Path, to: &Path) -> Result<()> { let entry = entry?; let from = entry.path(); let to = to.join(entry.file_name()); - if diff(&from, &to)? { + let from_is_dir = from.is_dir(); + let to_is_dir = to.is_dir(); + if !from_is_dir && !to_is_dir && diff(&from, &to)? { return Ok(()); } - let to_dir = to.is_dir(); - if from.is_dir() { - if !to_dir { + if from_is_dir { + if !to_is_dir { fs::remove_file(&to)?; } return copy_cached(&from, &to); } - if to_dir { + if to_is_dir { fs::remove_dir_all(&to)?; } fs::copy(&from, &to)?; @@ -87,7 +88,7 @@ fn cleanup(from: &Path, to: &Path) -> Result<()> { } /// Compare two file contents. Return true if they are identical. -fn diff(a: impl AsRef, b: impl AsRef) -> Result { +fn diff(a: &Path, b: &Path) -> Result { let a = fs::File::open(a); let b = fs::File::open(b); if a.is_err() || b.is_err() { diff --git a/src/rgl/context.rs b/src/rgl/context.rs index dd02fd2..48aebfa 100644 --- a/src/rgl/context.rs +++ b/src/rgl/context.rs @@ -39,7 +39,7 @@ impl RunContext { } pub fn watch_project_files(&self) -> Result<()> { - let mut file_watcher = FileWatcher::new(); + let mut file_watcher = FileWatcher::new()?; file_watcher.watch(&self.data_path)?; file_watcher.watch(&self.behavior_pack)?; diff --git a/src/rgl/core.rs b/src/rgl/core.rs index 1cf23d4..b7bf3b1 100644 --- a/src/rgl/core.rs +++ b/src/rgl/core.rs @@ -44,16 +44,16 @@ pub fn run_or_watch(profile_name: &str, watch: bool, cached: bool) -> Result<()> measure_time!("Export project", { info!( "Moving files to target location: \n\ - \tBP: {} \n\ - \tRP: {}", + \tBP: {} \n\ + \tRP: {}", bp.display(), rp.display() ); - let export: Result<()> = { + let export = || -> Result<()> { move_dir(temp_bp, bp)?; move_dir(temp_rp, rp) }; - export.context("Failed to export project")?; + export().context("Failed to export project")?; }); info!("Successfully ran the {profile_name} profile"); diff --git a/src/rgl/file_system.rs b/src/rgl/file_system.rs index cb47350..634db81 100644 --- a/src/rgl/file_system.rs +++ b/src/rgl/file_system.rs @@ -4,7 +4,7 @@ use rayon::prelude::*; use std::{fs, io, path::Path}; fn copy_dir_impl(from: &Path, to: &Path) -> Result<()> { - fs::create_dir_all(&to)?; + fs::create_dir_all(to)?; fs::read_dir(from)? .par_bridge() .map(|entry| -> Result<()> { diff --git a/src/rgl/file_watcher.rs b/src/rgl/file_watcher.rs index 971bb59..0cf06e6 100644 --- a/src/rgl/file_watcher.rs +++ b/src/rgl/file_watcher.rs @@ -1,4 +1,3 @@ -use crate::error; use anyhow::{Context, Result}; use notify::{Error, RecommendedWatcher, RecursiveMode}; use notify_debouncer_mini::{new_debouncer, DebouncedEvent, Debouncer}; @@ -10,13 +9,11 @@ pub struct FileWatcher { } impl FileWatcher { - pub fn new() -> Self { + pub fn new() -> Result { let (tx, rx) = std::sync::mpsc::channel(); - let debouncer = new_debouncer(Duration::from_millis(100), None, tx).unwrap_or_else(|err| { - error!("Failed to create file watcher: {}", err); - std::process::exit(1); - }); - Self { rx, debouncer } + let debouncer = new_debouncer(Duration::from_millis(100), None, tx) + .context("Failed to create file watcher")?; + Ok(Self { rx, debouncer }) } pub fn watch(&mut self, path: &str) -> Result<()> { diff --git a/src/rgl/filter_installer.rs b/src/rgl/filter_installer.rs index f9f9857..aeca104 100644 --- a/src/rgl/filter_installer.rs +++ b/src/rgl/filter_installer.rs @@ -1,12 +1,12 @@ use super::{ - copy_dir, empty_dir, get_filter_cache_dir, read_json, resolve_url, rimraf, write_json, - FilterRemote, Subprocess, + copy_dir, empty_dir, get_filter_cache_dir, move_dir, read_json, resolve_url, rimraf, + write_json, FilterRemote, Subprocess, }; use crate::{info, warn}; use anyhow::{bail, Result}; use semver::Version; use serde_json::Value; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; pub struct FilterInstaller { pub name: String, @@ -54,7 +54,7 @@ impl FilterInstaller { Ok(Self { name, url, git_ref }) } - pub fn install(&self, force: bool) -> Result { + pub fn install(&self, data_path: &Path, force: bool) -> Result { let filter_dir = PathBuf::from(".regolith") .join("cache") .join("filters") @@ -73,7 +73,12 @@ impl FilterInstaller { let https_url = format!("https://{}", self.url); let cache_dir = get_filter_cache_dir(&https_url)?; - if !cache_dir.exists() { + if cache_dir.exists() { + Subprocess::new("git") + .args(vec!["fetch", "--all"]) + .current_dir(&cache_dir) + .run_silent()?; + } else { empty_dir(&cache_dir)?; Subprocess::new("git") .args(vec!["clone", &https_url, "."]) @@ -88,6 +93,13 @@ impl FilterInstaller { copy_dir(cache_dir.join(&self.name), &filter_dir)?; + let filter_data = filter_dir.join("data"); + let target_path = data_path.join(&self.name); + if filter_data.is_dir() && !target_path.exists() { + info!("Moving filter data to {}", target_path.display()); + move_dir(&filter_data, target_path)?; + } + let filter_config_path = filter_dir.join("filter.json"); let mut filter_config = read_json::(&filter_config_path)?; filter_config["version"] = ref_to_version(&self.git_ref).into(); diff --git a/src/rgl/install.rs b/src/rgl/install.rs index 5ec9cc3..863b82a 100644 --- a/src/rgl/install.rs +++ b/src/rgl/install.rs @@ -2,9 +2,11 @@ use super::{ref_to_version, Config, FilterDefinition, FilterInstaller, RemoteFil use crate::info; use anyhow::Result; use semver::Version; +use std::path::Path; pub fn install_filters(force: bool) -> Result<()> { let config = Config::load()?; + let data_path = Path::new(&config.regolith.data_path); for (name, def) in config.regolith.filter_definitions { if let FilterDefinition::Remote(def) = def { info!("Installing filter {}...", name); @@ -12,7 +14,7 @@ pub fn install_filters(force: bool) -> Result<()> { .map(|version| format!("{name}-{version}")) .unwrap_or(def.version); let filter = FilterInstaller::new(name, def.url, git_ref)?; - filter.install(force)?; + filter.install(data_path, force)?; } } info!("Successfully installed all filters"); @@ -21,10 +23,11 @@ pub fn install_filters(force: bool) -> Result<()> { pub fn install_add(filters: Vec<&String>, force: bool) -> Result<()> { let mut config = Config::load()?; + let data_path = Path::new(&config.regolith.data_path); for arg in filters { info!("Installing filter {}...", arg); let filter = FilterInstaller::from_arg(arg)?; - if filter.install(force)? { + if filter.install(data_path, force)? { info!("Filter {} successfully installed", filter.name); let version = ref_to_version(&filter.git_ref); config.regolith.filter_definitions.insert( diff --git a/src/rgl/profile.rs b/src/rgl/profile.rs index e3af9ad..a86bc6c 100644 --- a/src/rgl/profile.rs +++ b/src/rgl/profile.rs @@ -1,9 +1,10 @@ use super::{find_mojang_dir, RunContext}; use crate::{info, measure_time}; use anyhow::{bail, Context, Result}; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::{collections::HashMap, fs, path::PathBuf}; +use std::{fs, path::PathBuf}; #[derive(Serialize, Deserialize)] pub struct Profile { @@ -25,7 +26,7 @@ pub enum FilterRunner { #[serde(skip_serializing_if = "Option::is_none")] arguments: Option>, #[serde(skip_serializing_if = "Option::is_none")] - settings: Option>, + settings: Option>, }, ProfileFilter { #[serde(rename = "profile")]