diff --git a/Cargo.lock b/Cargo.lock index 87507adef25..be715416f93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3290,6 +3290,8 @@ dependencies = [ "miette", "moon_cache_item", "moon_common", + "moon_hash", + "moon_target", "moon_time", "serde", "starbase_sandbox", @@ -4365,7 +4367,6 @@ dependencies = [ "moon_cache", "moon_common", "moon_config", - "moon_hash", "moon_vcs", "proto_core", "starbase", diff --git a/crates/cli/src/queries/hash.rs b/crates/cli/src/queries/hash.rs index 9a4cd10a051..437a9f37f47 100644 --- a/crates/cli/src/queries/hash.rs +++ b/crates/cli/src/queries/hash.rs @@ -7,7 +7,7 @@ use tracing::debug; pub async fn query_hash(workspace: &Workspace, hash: &str) -> AppResult<(String, String)> { debug!("Querying for hash manifest with {}", color::hash(hash)); - for file in fs::read_dir(&workspace.hash_engine.hashes_dir)? { + for file in fs::read_dir(&workspace.cache_engine.hash.hashes_dir)? { let path = file.path(); let name = fs::file_name(&path).replace(".json", ""); diff --git a/crates/cli/tests/run_test.rs b/crates/cli/tests/run_test.rs index da936f24905..1b0b3d66022 100644 --- a/crates/cli/tests/run_test.rs +++ b/crates/cli/tests/run_test.rs @@ -46,6 +46,7 @@ fn extract_hash_from_run(fixture: &Path, target_id: &str) -> String { let engine = CacheEngine::new(fixture).unwrap(); let cache: RunTargetState = json::read_file( engine + .state .states_dir .join(target_id.replace(':', "/")) .join("lastRun.json"), diff --git a/crates/core/action-pipeline/src/actions/install_deps.rs b/crates/core/action-pipeline/src/actions/install_deps.rs index cb4efbd7e14..4f2974296e3 100644 --- a/crates/core/action-pipeline/src/actions/install_deps.rs +++ b/crates/core/action-pipeline/src/actions/install_deps.rs @@ -114,7 +114,8 @@ pub async fn install_deps( let manifest_path = working_dir.join(&manifest); let lockfile_path = working_dir.join(&lockfile); let mut hasher = workspace - .hash_engine + .cache_engine + .hash .create_hasher(format!("Install {} deps", runtime.label())); let mut last_modified = 0; @@ -145,16 +146,21 @@ pub async fn install_deps( } // Install dependencies in the working directory - let hash = workspace.hash_engine.save_manifest(hasher)?; + let hash = workspace.cache_engine.hash.save_manifest(hasher)?; let state_path = format!("deps{runtime}.json"); - let mut state = workspace.cache_engine.cache_state::( - if let Some(project) = &project { - project.get_cache_dir().join(state_path) + let mut state = workspace + .cache_engine + .state + .load_state::(if let Some(project) = &project { + workspace + .cache_engine + .state + .get_project_dir(&project.id) + .join(state_path) } else { PathBuf::from(state_path) - }, - )?; + })?; if hash != state.data.last_hash || last_modified == 0 diff --git a/crates/core/action-pipeline/src/actions/setup_tool.rs b/crates/core/action-pipeline/src/actions/setup_tool.rs index d1d364126e2..5b626a9b9ca 100644 --- a/crates/core/action-pipeline/src/actions/setup_tool.rs +++ b/crates/core/action-pipeline/src/actions/setup_tool.rs @@ -52,7 +52,8 @@ pub async fn setup_tool( let mut state = workspace .cache_engine - .cache_state::(format!("tool{}-{}.json", runtime, runtime.requirement))?; + .state + .load_state::(format!("tool{}-{}.json", runtime, runtime.requirement))?; // Install and setup the specific tool + version in the toolchain! let installed_count = PlatformManager::write() diff --git a/crates/core/action-pipeline/src/actions/sync_project.rs b/crates/core/action-pipeline/src/actions/sync_project.rs index 357b7a720c9..369ccabbb42 100644 --- a/crates/core/action-pipeline/src/actions/sync_project.rs +++ b/crates/core/action-pipeline/src/actions/sync_project.rs @@ -42,7 +42,8 @@ pub async fn sync_project( // Create a snapshot for tasks to reference workspace .cache_engine - .write_state(project.get_cache_dir().join("snapshot.json"), project)?; + .state + .save_project_snapshot(&project.id, project)?; // Collect all project dependencies so we can pass them along. // We can't pass the graph itself because of circuler references between crates! diff --git a/crates/core/action-pipeline/src/subscribers/local_cache.rs b/crates/core/action-pipeline/src/subscribers/local_cache.rs index 0b4588afe35..dc9e6bff57b 100644 --- a/crates/core/action-pipeline/src/subscribers/local_cache.rs +++ b/crates/core/action-pipeline/src/subscribers/local_cache.rs @@ -31,7 +31,7 @@ impl Subscriber for LocalCacheSubscriber { // We only check for the archive, as the manifest is purely for local debugging! Event::TargetOutputCacheCheck { hash, .. } => { if get_cache_mode().is_readable() - && workspace.hash_engine.get_archive_path(hash).exists() + && workspace.cache_engine.hash.get_archive_path(hash).exists() { return Ok(EventFlow::Return("local-cache".into())); } @@ -44,8 +44,8 @@ impl Subscriber for LocalCacheSubscriber { task, .. } => { - let state_dir = workspace.cache_engine.states_dir.join(task.get_cache_dir()); - let archive_path = workspace.hash_engine.get_archive_path(hash); + let state_dir = workspace.cache_engine.state.get_target_dir(&task.target); + let archive_path = workspace.cache_engine.hash.get_archive_path(hash); let output_paths = task .outputs .iter() @@ -64,8 +64,8 @@ impl Subscriber for LocalCacheSubscriber { task, .. } => { - let state_dir = workspace.cache_engine.states_dir.join(task.get_cache_dir()); - let archive_path = workspace.hash_engine.get_archive_path(hash); + let state_dir = workspace.cache_engine.state.get_target_dir(&task.target); + let archive_path = workspace.cache_engine.hash.get_archive_path(hash); let output_paths = task .outputs .iter() diff --git a/crates/core/action-pipeline/src/subscribers/moonbase.rs b/crates/core/action-pipeline/src/subscribers/moonbase.rs index 41670a7abc6..5b9b204ad6b 100644 --- a/crates/core/action-pipeline/src/subscribers/moonbase.rs +++ b/crates/core/action-pipeline/src/subscribers/moonbase.rs @@ -499,7 +499,7 @@ impl Subscriber for MoonbaseSubscriber { Event::TargetOutputHydrating { hash, .. } => { if get_cache_mode().is_readable() { if let Some(download_url) = self.download_urls.get(*hash) { - let archive_file = workspace.hash_engine.get_archive_path(hash); + let archive_file = workspace.cache_engine.hash.get_archive_path(hash); trace!( target: LOG_TARGET, diff --git a/crates/core/actions/src/sync_codeowners.rs b/crates/core/actions/src/sync_codeowners.rs index 4771a4aee80..7075929a64e 100644 --- a/crates/core/actions/src/sync_codeowners.rs +++ b/crates/core/actions/src/sync_codeowners.rs @@ -1,4 +1,3 @@ -use moon_cache_item::CommonState; use moon_codeowners::{CodeownersGenerator, CodeownersHash}; use moon_config::CodeownersOrderBy; use moon_project_graph::ProjectGraph; @@ -10,8 +9,7 @@ pub async fn sync_codeowners( project_graph: &ProjectGraph, force: bool, ) -> miette::Result { - let cache_engine = &workspace.cache_engine; - let hash_engine = &workspace.hash_engine; + let mut generator = CodeownersGenerator::new(&workspace.root, workspace.config.vcs.provider)?; // Sort the projects based on config let mut projects = project_graph.get_all_unexpanded(); @@ -22,19 +20,18 @@ pub async fn sync_codeowners( CodeownersOrderBy::ProjectName => a.id.cmp(&d.id), }); - // Generate the codeowners file + // Generate a hash for the codeowners file let mut codeowners_hash = CodeownersHash::new(&workspace.config.codeowners); - let mut codeowners = CodeownersGenerator::new(&workspace.root, workspace.config.vcs.provider)?; if !workspace.config.codeowners.global_paths.is_empty() { - codeowners.add_workspace_entries(&workspace.config.codeowners)?; + generator.add_workspace_entries(&workspace.config.codeowners)?; } - for project in &projects { + for project in projects { if !project.config.owners.paths.is_empty() { codeowners_hash.add_project(&project.id, &project.config.owners); - codeowners.add_project_entry( + generator.add_project_entry( &project.id, project.source.as_str(), &project.config.owners, @@ -42,17 +39,20 @@ pub async fn sync_codeowners( } } - let file_path = codeowners.file_path.clone(); - - // Check the cache before writing the file - let mut state = cache_engine.cache_state::("codeowners.json")?; - let hash = hash_engine.save_manifest_without_hasher("CODEOWNERS", &codeowners_hash)?; + let file_path = generator.file_path.clone(); - if force || hash != state.data.last_hash { - codeowners.generate()?; - - state.data.last_hash = hash; - state.save()?; + // Force run the generator and bypass cache + if force { + generator.generate()?; + } + // Only generate if the hash has changed + else { + workspace + .cache_engine + .execute_if_changed("codeowners.json", codeowners_hash, || async { + generator.generate() + }) + .await?; } Ok(file_path) diff --git a/crates/core/actions/src/sync_vcs_hooks.rs b/crates/core/actions/src/sync_vcs_hooks.rs index 50be78b58dd..b62faf9accc 100644 --- a/crates/core/actions/src/sync_vcs_hooks.rs +++ b/crates/core/actions/src/sync_vcs_hooks.rs @@ -1,11 +1,14 @@ -use moon_cache_item::CommonState; use moon_vcs_hooks::{HooksGenerator, HooksHash}; use moon_workspace::Workspace; pub async fn sync_vcs_hooks(workspace: &Workspace, force: bool) -> miette::Result<()> { let vcs_config = &workspace.config.vcs; - let cache_engine = &workspace.cache_engine; - let hash_engine = &workspace.hash_engine; + let generator = HooksGenerator::new(&workspace.root, &workspace.vcs, vcs_config); + + // Force run the generator and bypass cache + if force { + return generator.generate().await; + } // Hash all the hook commands let mut hooks_hash = HooksHash::new(&vcs_config.manager); @@ -14,18 +17,13 @@ pub async fn sync_vcs_hooks(workspace: &Workspace, force: bool) -> miette::Resul hooks_hash.add_hook(hook_name, commands); } - // Check the cache before creating the files - let mut state = cache_engine.cache_state::("vcsHooks.json")?; - let hash = hash_engine.save_manifest_without_hasher("VCS hooks", &hooks_hash)?; - - if force || hash != state.data.last_hash { - HooksGenerator::new(&workspace.root, &workspace.vcs, vcs_config) - .generate() - .await?; - - state.data.last_hash = hash; - state.save()?; - } + // Only generate if the hash has changed + workspace + .cache_engine + .execute_if_changed("vcsHooks.json", hooks_hash, || async { + generator.generate().await + }) + .await?; Ok(()) } diff --git a/crates/core/moon/src/lib.rs b/crates/core/moon/src/lib.rs index 7c717a71dbb..08a96519752 100644 --- a/crates/core/moon/src/lib.rs +++ b/crates/core/moon/src/lib.rs @@ -212,9 +212,7 @@ pub async fn build_project_graph(workspace: &mut Workspace) -> miette::Result miette::Result { let context = create_project_graph_context(workspace).await; - let builder = - ProjectGraphBuilder::generate(context, &workspace.cache_engine, &workspace.hash_engine) - .await?; + let builder = ProjectGraphBuilder::generate(context, &workspace.cache_engine).await?; let graph = builder.build().await?; diff --git a/crates/core/runner/src/runner.rs b/crates/core/runner/src/runner.rs index f5b7e35886d..b30e25ad4d7 100644 --- a/crates/core/runner/src/runner.rs +++ b/crates/core/runner/src/runner.rs @@ -84,7 +84,8 @@ impl<'a> Runner<'a> { ) -> miette::Result> { let mut cache = workspace .cache_engine - .cache_state::(task.get_cache_dir().join("lastRun.json"))?; + .state + .load_target_state::(&task.target)?; if cache.data.target.is_empty() { cache.data.target = task.target.to_string(); @@ -420,8 +421,8 @@ impl<'a> Runner<'a> { path::to_string( self.workspace .cache_engine - .states_dir - .join(self.project.get_cache_dir().join("snapshot.json")), + .state + .get_project_snapshot_path(&self.project.id), )?, ); @@ -551,7 +552,8 @@ impl<'a> Runner<'a> { ) -> miette::Result> { let mut hasher = self .workspace - .hash_engine + .cache_engine + .hash .create_hasher(format!("Run {} target", self.task.target)); self.hash_common_target(context, &mut hasher).await?; @@ -595,7 +597,7 @@ impl<'a> Runner<'a> { self.cache.data.hash = hash.clone(); // Refresh the hash manifest - self.workspace.hash_engine.save_manifest(hasher)?; + self.workspace.cache_engine.hash.save_manifest(hasher)?; // Check if that hash exists in the cache if let EventFlow::Return(value) = self diff --git a/nextgen/api/src/launchpad.rs b/nextgen/api/src/launchpad.rs index 1f9d06385a9..8113e422edf 100644 --- a/nextgen/api/src/launchpad.rs +++ b/nextgen/api/src/launchpad.rs @@ -66,7 +66,9 @@ impl Launchpad { moon_env: &MoonEnvironment, bypass_cache: bool, ) -> miette::Result> { - let mut state = cache_engine.cache_state::("moonVersion.json")?; + let mut state = cache_engine + .state + .load_state::("moonVersion.json")?; if let Some(last_check) = state.data.last_check { if (last_check + ALERT_PAUSE_DURATION) > SystemTime::now() && !bypass_cache { diff --git a/nextgen/cache/Cargo.toml b/nextgen/cache/Cargo.toml index 8f6692f010d..5dbc8a14e7c 100644 --- a/nextgen/cache/Cargo.toml +++ b/nextgen/cache/Cargo.toml @@ -11,6 +11,8 @@ publish = false [dependencies] moon_cache_item = { path = "../cache-item" } moon_common = { path = "../common" } +moon_hash = { path = "../hash" } +moon_target = { path = "../target" } moon_time = { path = "../time" } miette = { workspace = true } serde = { workspace = true } diff --git a/nextgen/cache/src/cache_engine.rs b/nextgen/cache/src/cache_engine.rs index e658d53b6c2..fbb58176caf 100644 --- a/nextgen/cache/src/cache_engine.rs +++ b/nextgen/cache/src/cache_engine.rs @@ -1,3 +1,4 @@ +use crate::{merge_clean_results, resolve_path, HashEngine, StateEngine}; use moon_cache_item::*; use moon_common::consts; use moon_time::parse_duration; @@ -5,6 +6,7 @@ use serde::de::DeserializeOwned; use serde::Serialize; use starbase_utils::{fs, json}; use std::ffi::OsStr; +use std::future::Future; use std::path::{Path, PathBuf}; use tracing::debug; @@ -13,24 +15,24 @@ pub struct CacheEngine { /// Contains cached items pertaining to runs and processes. pub cache_dir: PathBuf, - /// The `.moon/cache/states` directory. Stores state information about anything... - /// tools, dependencies, projects, tasks, etc. - pub states_dir: PathBuf, + /// Manages reading and writing of content hashable items. + pub hash: HashEngine, + + /// Manages states of projects, tasks, tools, and more. + pub state: StateEngine, } impl CacheEngine { pub fn new(workspace_root: &Path) -> miette::Result { let dir = workspace_root.join(consts::CONFIG_DIRNAME).join("cache"); - let states_dir = dir.join("states"); let cache_tag = dir.join("CACHEDIR.TAG"); debug!( cache_dir = ?dir, - states_dir = ?states_dir, "Creating cache engine", ); - fs::create_dir_all(&states_dir)?; + fs::create_dir_all(&dir)?; // Create a cache directory tag if !cache_tag.exists() { @@ -43,8 +45,9 @@ impl CacheEngine { } Ok(CacheEngine { + hash: HashEngine::new(&dir)?, + state: StateEngine::new(&dir)?, cache_dir: dir, - states_dir, }) } @@ -55,50 +58,39 @@ impl CacheEngine { CacheItem::::load(self.resolve_path(path)) } - pub fn cache_state(&self, path: impl AsRef) -> miette::Result> - where - T: Default + DeserializeOwned + Serialize, - { - self.cache(self.states_dir.join(path.as_ref())) - } - pub fn clean_stale_cache(&self, lifetime: &str, all: bool) -> miette::Result<(usize, u64)> { - let duration = - parse_duration(lifetime).map_err(|e| miette::miette!("Invalid lifetime: {e}"))?; + let duration = parse_duration(lifetime) + .map_err(|error| miette::miette!("Invalid lifetime: {error}"))?; debug!( "Cleaning up and deleting stale cached artifacts older than \"{}\"", lifetime ); - let mut deleted = 0; - let mut bytes = 0; - - if all { - let stats = fs::remove_dir_stale_contents(&self.cache_dir, duration)?; - deleted += stats.files_deleted; - bytes += stats.bytes_saved; + let result = if all { + merge_clean_results( + self.state.clean_stale_cache(duration)?, + self.hash.clean_stale_cache(duration)?, + ) } else { - let stats = fs::remove_dir_stale_contents(self.cache_dir.join("hashes"), duration)?; - deleted += stats.files_deleted; - bytes += stats.bytes_saved; + self.hash.clean_stale_cache(duration)? + }; - let stats = fs::remove_dir_stale_contents(self.cache_dir.join("outputs"), duration)?; - deleted += stats.files_deleted; - bytes += stats.bytes_saved; - } - - debug!("Deleted {} artifacts and saved {} bytes", deleted, bytes); + debug!( + "Deleted {} artifacts and saved {} bytes", + result.files_deleted, result.bytes_saved + ); - Ok((deleted, bytes)) + Ok((result.files_deleted, result.bytes_saved)) } pub fn get_mode(&self) -> CacheMode { get_cache_mode() } - pub fn write(&self, path: impl AsRef, data: &T) -> miette::Result<()> + pub fn write(&self, path: K, data: &T) -> miette::Result<()> where + K: AsRef, T: ?Sized + Serialize, { let path = self.resolve_path(path); @@ -111,20 +103,35 @@ impl CacheEngine { Ok(()) } - pub fn write_state(&self, path: impl AsRef, state: &T) -> miette::Result<()> + pub async fn execute_if_changed( + &self, + path: K, + data: T, + op: F, + ) -> miette::Result<()> where - T: ?Sized + Serialize, + K: AsRef, + T: Serialize, + F: FnOnce() -> Fut, + Fut: Future> + Send, { - self.write(self.states_dir.join(path.as_ref()), state) - } + let path = self.resolve_path(path); + let name = fs::file_name(&path); - fn resolve_path(&self, path: impl AsRef) -> PathBuf { - let path = PathBuf::from(path.as_ref()); + let mut state = self.state.load_state::(&name)?; + let hash = self.hash.save_manifest_without_hasher(&name, data)?; - if path.is_absolute() { - path - } else { - self.cache_dir.join(path) + if hash != state.data.last_hash { + op().await?; + + state.data.last_hash = hash; + state.save()?; } + + Ok(()) + } + + pub fn resolve_path(&self, path: impl AsRef) -> PathBuf { + resolve_path(&self.cache_dir, path) } } diff --git a/nextgen/hash/src/hash_engine.rs b/nextgen/cache/src/hash_engine.rs similarity index 80% rename from nextgen/hash/src/hash_engine.rs rename to nextgen/cache/src/hash_engine.rs index adb5abfcf4b..068db68a571 100644 --- a/nextgen/hash/src/hash_engine.rs +++ b/nextgen/cache/src/hash_engine.rs @@ -1,7 +1,9 @@ -use crate::hasher::ContentHasher; +use crate::merge_clean_results; +use moon_hash::ContentHasher; use serde::Serialize; -use starbase_utils::fs; +use starbase_utils::fs::{self, RemoveDirContentsResult}; use std::path::{Path, PathBuf}; +use std::time::Duration; use tracing::debug; pub struct HashEngine { @@ -32,6 +34,13 @@ impl HashEngine { }) } + pub fn clean_stale_cache(&self, duration: Duration) -> miette::Result { + Ok(merge_clean_results( + fs::remove_dir_stale_contents(&self.hashes_dir, duration)?, + fs::remove_dir_stale_contents(&self.outputs_dir, duration)?, + )) + } + pub fn create_hasher>(&self, label: T) -> ContentHasher { ContentHasher::new(label.as_ref()) } diff --git a/nextgen/cache/src/lib.rs b/nextgen/cache/src/lib.rs index 94c009c9080..2690d95566d 100644 --- a/nextgen/cache/src/lib.rs +++ b/nextgen/cache/src/lib.rs @@ -1,4 +1,34 @@ mod cache_engine; +mod hash_engine; +mod state_engine; pub use cache_engine::*; +pub use hash_engine::*; pub use moon_cache_item::*; +pub use state_engine::*; + +use starbase_utils::fs::RemoveDirContentsResult; +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; + +pub(crate) fn resolve_path(base_dir: &Path, path: impl AsRef) -> PathBuf { + let path = PathBuf::from(path.as_ref()); + + let mut path = if path.is_absolute() { + path + } else { + base_dir.join(path) + }; + + path.set_extension("json"); + path +} + +pub(crate) fn merge_clean_results( + mut left: RemoveDirContentsResult, + right: RemoveDirContentsResult, +) -> RemoveDirContentsResult { + left.bytes_saved += right.bytes_saved; + left.files_deleted += right.files_deleted; + left +} diff --git a/nextgen/cache/src/state_engine.rs b/nextgen/cache/src/state_engine.rs new file mode 100644 index 00000000000..861aab75a15 --- /dev/null +++ b/nextgen/cache/src/state_engine.rs @@ -0,0 +1,94 @@ +use crate::resolve_path; +use moon_cache_item::CacheItem; +use moon_target::{Target, TargetScope}; +use serde::de::DeserializeOwned; +use serde::Serialize; +use starbase_utils::fs::RemoveDirContentsResult; +use starbase_utils::{fs, json}; +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; +use std::time::Duration; +use tracing::debug; + +pub struct StateEngine { + /// The `.moon/cache/states` directory. Stores state information about anything... + /// tools, dependencies, projects, tasks, etc. + pub states_dir: PathBuf, +} + +impl StateEngine { + pub fn new(cache_dir: &Path) -> miette::Result { + let states_dir = cache_dir.join("states"); + + debug!( + states_dir = ?states_dir, + "Creating states engine", + ); + + fs::create_dir_all(&states_dir)?; + + Ok(StateEngine { states_dir }) + } + + pub fn clean_stale_cache(&self, duration: Duration) -> miette::Result { + Ok(fs::remove_dir_stale_contents(&self.states_dir, duration)?) + } + + pub fn get_project_dir(&self, project_id: &str) -> PathBuf { + self.states_dir.join(project_id) + } + + pub fn get_project_snapshot_path(&self, project_id: &str) -> PathBuf { + self.get_project_dir(project_id).join("snapshot.json") + } + + pub fn get_tag_dir(&self, tag: &str) -> PathBuf { + self.states_dir.join(format!("tag-{tag}")) + } + + pub fn get_task_dir(&self, project_id: &str, task_id: &str) -> PathBuf { + self.get_project_dir(project_id).join(task_id) + } + + pub fn get_target_dir(&self, target: &Target) -> PathBuf { + let dir = match &target.scope { + TargetScope::Project(id) => self.get_project_dir(id), + TargetScope::Tag(tag) => self.get_tag_dir(tag), + _ => self.get_project_dir("_"), + }; + + dir.join(target.task_id.as_str()) + } + + pub fn load_state(&self, path: impl AsRef) -> miette::Result> + where + T: Default + DeserializeOwned + Serialize, + { + CacheItem::::load(self.resolve_path(path)) + } + + pub fn load_target_state(&self, target: &Target) -> miette::Result> + where + T: Default + DeserializeOwned + Serialize, + { + CacheItem::::load(self.get_target_dir(target).join("lastRun.json")) + } + + pub fn save_project_snapshot(&self, project_id: &str, data: &T) -> miette::Result<()> + where + T: ?Sized + Serialize, + { + let path = self.get_project_snapshot_path(project_id); + + debug!(cache = ?path, "Writing project snapshot"); + + // This purposefully ignores the cache mode and always writes! + json::write_file(path, &data, false)?; + + Ok(()) + } + + pub fn resolve_path(&self, path: impl AsRef) -> PathBuf { + resolve_path(&self.states_dir, path) + } +} diff --git a/nextgen/cache/tests/cache_engine_test.rs b/nextgen/cache/tests/cache_engine_test.rs index 72a48e1c47f..f947049aa66 100644 --- a/nextgen/cache/tests/cache_engine_test.rs +++ b/nextgen/cache/tests/cache_engine_test.rs @@ -18,7 +18,10 @@ mod cache_engine { fn returns_default_if_cache_missing() { let sandbox = create_empty_sandbox(); let engine = CacheEngine::new(sandbox.path()).unwrap(); - let item = engine.cache_state::("state.json").unwrap(); + let item = engine + .state + .load_state::("state.json") + .unwrap(); assert_eq!(item.data, CommonState::default()); } @@ -32,7 +35,10 @@ mod cache_engine { ); let engine = CacheEngine::new(sandbox.path()).unwrap(); - let item = engine.cache_state::("state.json").unwrap(); + let item = engine + .state + .load_state::("state.json") + .unwrap(); assert_eq!( item.data, @@ -71,8 +77,8 @@ mod cache_engine { env::set_var("MOON_CACHE", "read"); engine - .write_state( - "test.json", + .write( + engine.state.resolve_path("test.json"), &CommonState { last_hash: "abc123".into(), }, diff --git a/nextgen/hash/tests/hash_engine_test.rs b/nextgen/cache/tests/hash_engine_test.rs similarity index 98% rename from nextgen/hash/tests/hash_engine_test.rs rename to nextgen/cache/tests/hash_engine_test.rs index 4083f4fdefd..bd8fa27338d 100644 --- a/nextgen/hash/tests/hash_engine_test.rs +++ b/nextgen/cache/tests/hash_engine_test.rs @@ -1,3 +1,4 @@ +use moon_cache::*; use moon_hash::*; use starbase_sandbox::create_empty_sandbox; use std::fs; diff --git a/nextgen/hash/src/lib.rs b/nextgen/hash/src/lib.rs index 691796a35e4..cde2b178470 100644 --- a/nextgen/hash/src/lib.rs +++ b/nextgen/hash/src/lib.rs @@ -1,9 +1,7 @@ mod deps_hash; -mod hash_engine; mod hasher; pub use deps_hash::*; -pub use hash_engine::*; pub use hasher::*; #[macro_export] diff --git a/nextgen/project-graph/src/project_graph_builder.rs b/nextgen/project-graph/src/project_graph_builder.rs index 7807f55e818..364a7b74884 100644 --- a/nextgen/project-graph/src/project_graph_builder.rs +++ b/nextgen/project-graph/src/project_graph_builder.rs @@ -11,7 +11,6 @@ use moon_config::{ DependencyScope, InheritedTasksManager, ProjectConfig, ProjectsSourcesList, ToolchainConfig, WorkspaceConfig, WorkspaceProjects, }; -use moon_hash::HashEngine; use moon_project::Project; use moon_project_builder::{ProjectBuilder, ProjectBuilderContext}; use moon_project_constraints::{enforce_project_type_relationships, enforce_tag_relationships}; @@ -99,7 +98,6 @@ impl<'app> ProjectGraphBuilder<'app> { pub async fn generate( context: ProjectGraphBuilderContext<'app>, cache_engine: &CacheEngine, - hash_engine: &HashEngine, ) -> miette::Result> { let is_vcs_enabled = context .vcs @@ -121,13 +119,17 @@ impl<'app> ProjectGraphBuilder<'app> { graph_contents.add_aliases(&graph.aliases); graph_contents.add_configs(graph.hash_required_configs().await?); - let hash = hash_engine.save_manifest_without_hasher("Project graph", &graph_contents)?; + let hash = cache_engine + .hash + .save_manifest_without_hasher("Project graph", &graph_contents)?; debug!(hash, "Generated hash for project graph"); // Check the current state and cache - let mut state = cache_engine.cache_state::("projects.json")?; - let cache_path = cache_engine.states_dir.join("partialProjectGraph.json"); + let mut state = cache_engine + .state + .load_state::("projects.json")?; + let cache_path = cache_engine.state.resolve_path("partialProjectGraph.json"); if hash == state.data.last_hash && cache_path.exists() { debug!( diff --git a/nextgen/project-graph/tests/project_graph_test.rs b/nextgen/project-graph/tests/project_graph_test.rs index 87317054357..576a948cc4f 100644 --- a/nextgen/project-graph/tests/project_graph_test.rs +++ b/nextgen/project-graph/tests/project_graph_test.rs @@ -244,7 +244,6 @@ mod project_graph { mod cache { use super::*; use moon_cache::CacheEngine; - use moon_hash::HashEngine; use moon_project_graph::ProjectsState; const CACHE_PATH: &str = ".moon/cache/states/partialProjectGraph.json"; @@ -252,11 +251,10 @@ mod project_graph { async fn do_generate(root: &Path) -> ProjectGraph { let cache_engine = CacheEngine::new(root).unwrap(); - let hash_engine = HashEngine::new(&cache_engine.cache_dir).unwrap(); let container = ProjectGraphContainer::with_vcs(root); let context = container.create_context(); - let mut builder = ProjectGraphBuilder::generate(context, &cache_engine, &hash_engine) + let mut builder = ProjectGraphBuilder::generate(context, &cache_engine) .await .unwrap(); builder.load_all().await.unwrap(); diff --git a/nextgen/project/src/project.rs b/nextgen/project/src/project.rs index e7314d01538..6019a93831d 100644 --- a/nextgen/project/src/project.rs +++ b/nextgen/project/src/project.rs @@ -59,11 +59,6 @@ cacheable!( ); impl Project { - /// Return a cache directory for this project, relative from the cache root. - pub fn get_cache_dir(&self) -> PathBuf { - PathBuf::from(self.id.as_str()) - } - /// Return a list of project IDs this project depends on. pub fn get_dependency_ids(&self) -> Vec<&Id> { self.dependencies diff --git a/nextgen/task/src/task.rs b/nextgen/task/src/task.rs index 380af1a0eba..b7db278a2fb 100644 --- a/nextgen/task/src/task.rs +++ b/nextgen/task/src/task.rs @@ -109,11 +109,6 @@ impl Task { Ok(files) } - /// Return a cache directory for this task, relative from the cache root. - pub fn get_cache_dir(&self) -> PathBuf { - PathBuf::from(self.target.get_project_id().unwrap().as_str()).join(self.id.as_str()) - } - /// Return true if this task is affected based on touched files. /// Will attempt to find any file that matches our list of inputs. pub fn is_affected( diff --git a/nextgen/workspace/Cargo.toml b/nextgen/workspace/Cargo.toml index 6dc17fd9b03..e723b62a832 100644 --- a/nextgen/workspace/Cargo.toml +++ b/nextgen/workspace/Cargo.toml @@ -9,7 +9,6 @@ moon_api = { path = "../api" } moon_cache = { path = "../cache" } moon_common = { path = "../common" } moon_config = { path = "../config", features = ["loader", "proto", "tracing"] } -moon_hash = { path = "../hash" } moon_vcs = { path = "../vcs" } miette = { workspace = true } proto_core = { workspace = true } diff --git a/nextgen/workspace/src/workspace.rs b/nextgen/workspace/src/workspace.rs index 3a7ee979c07..87d8561f41b 100644 --- a/nextgen/workspace/src/workspace.rs +++ b/nextgen/workspace/src/workspace.rs @@ -3,7 +3,6 @@ use moon_api::Moonbase; use moon_cache::CacheEngine; use moon_common::consts; use moon_config::{InheritedTasksManager, ToolchainConfig, WorkspaceConfig}; -use moon_hash::HashEngine; use moon_vcs::{BoxedVcs, Git}; use proto_core::{ProtoConfig, ProtoEnvironment, Version}; use starbase::Resource; @@ -136,9 +135,6 @@ pub struct Workspace { /// Workspace configuration loaded from ".moon/workspace.yml". pub config: Arc, - /// Engine for reading and writing hashes/outputs. - pub hash_engine: Arc, - /// Local `.prototools` config. pub proto_config: Arc, @@ -202,7 +198,6 @@ impl Workspace { // Setup components let cache_engine = CacheEngine::new(&root_dir)?; - let hash_engine = HashEngine::new(&cache_engine.cache_dir)?; let vcs = Git::load( &root_dir, &config.vcs.default_branch, @@ -212,7 +207,6 @@ impl Workspace { Ok(Workspace { cache_engine: Arc::new(cache_engine), config: Arc::new(config), - hash_engine: Arc::new(hash_engine), proto_config: Arc::new(proto_config.to_owned()), root: root_dir, session: None,