diff --git a/Cargo.lock b/Cargo.lock index c4fb365b..58bddf31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,6 +141,17 @@ version = "9.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59051ec02907378a67b0ba1b8631121f5388c8dbbb3cec8c749d8f93c2c3c211" +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -1433,6 +1444,8 @@ dependencies = [ "console", "globset", "once_cell", + "pest", + "pest_derive", "serde", "similar", "walkdir", @@ -1980,6 +1993,49 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "132dca9b868d927b35b5dd728167b2dee150eb1ad686008fc71ccb298b776fca" +[[package]] +name = "pest" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "pest_meta" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" +dependencies = [ + "pest", + "sha2", +] + [[package]] name = "petgraph" version = "0.8.3" @@ -3009,6 +3065,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "unicode-ident" version = "1.0.19" @@ -3164,14 +3226,19 @@ name = "vite_task" version = "0.0.0" dependencies = [ "anyhow", + "async-trait", "bincode", "bstr", + "clap", "compact_str 0.9.0", + "copy_dir", "dashmap", + "derive_more", "diff-struct", "fspy", "futures-core", "futures-util", + "insta", "itertools 0.14.0", "nix 0.30.1", "owo-colors", @@ -3186,6 +3253,7 @@ dependencies = [ "tempfile", "thiserror 2.0.17", "tokio", + "toml", "tracing", "twox-hash", "uuid", @@ -3193,35 +3261,25 @@ dependencies = [ "vite_path", "vite_shell", "vite_str", + "vite_task_graph", + "vite_task_plan", "vite_workspace", "wax", ] -[[package]] -name = "vite_task_bin" -version = "0.1.0" -dependencies = [ - "clap", - "vite_str", - "vite_task_graph", -] - [[package]] name = "vite_task_graph" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "clap", - "copy_dir", - "insta", "monostate", "petgraph", "serde", "serde_json", - "tempfile", "thiserror 2.0.17", "tokio", - "toml", "vec1", "vite_path", "vite_str", @@ -3233,7 +3291,7 @@ name = "vite_task_plan" version = "0.1.0" dependencies = [ "anyhow", - "futures-core", + "async-trait", "futures-util", "petgraph", "sha2", diff --git a/Cargo.toml b/Cargo.toml index f0b19e44..814b4921 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ allocator-api2 = { version = "0.2.21", default-features = false, features = ["al anyhow = "1.0.98" assert2 = "0.3.16" assertables = "9.8.1" +async-trait = "0.1.89" base64 = "0.22.1" bincode = "2.0.1" bindgen = "0.72.1" @@ -122,6 +123,7 @@ vite_path = { path = "crates/vite_path" } vite_shell = { path = "crates/vite_shell" } vite_str = { path = "crates/vite_str" } vite_task_graph = { path = "crates/vite_task_graph" } +vite_task_plan = { path = "crates/vite_task_plan" } vite_workspace = { path = "crates/vite_workspace" } wax = "0.6.0" which = "8.0.0" diff --git a/crates/vite_path/Cargo.toml b/crates/vite_path/Cargo.toml index 01d16110..5184a749 100644 --- a/crates/vite_path/Cargo.toml +++ b/crates/vite_path/Cargo.toml @@ -14,6 +14,9 @@ serde = { workspace = true, features = ["derive", "rc"] } thiserror = { workspace = true } vite_str = { workspace = true } +[features] +absolute-redaction = [] + [lints] workspace = true diff --git a/crates/vite_path/src/absolute.rs b/crates/vite_path/src/absolute/mod.rs similarity index 87% rename from crates/vite_path/src/absolute.rs rename to crates/vite_path/src/absolute/mod.rs index 89beb90c..928327cc 100644 --- a/crates/vite_path/src/absolute.rs +++ b/crates/vite_path/src/absolute/mod.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "absolute-redaction")] +pub mod redaction; + use std::{ ffi::OsStr, fmt::Display, @@ -8,6 +11,7 @@ use std::{ }; use ref_cast::{RefCastCustom, ref_cast_custom}; +use serde::Serialize; use crate::relative::{FromPathError, InvalidPathDataError, RelativePathBuf}; @@ -21,6 +25,35 @@ impl AsRef for AbsolutePath { } } +impl Serialize for AbsolutePath { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + #[cfg(feature = "absolute-redaction")] + { + use redaction::REDACTION_PREFIX; + + if let Some(redaction_prefix) = REDACTION_PREFIX + .with(|redaction_prefix| redaction_prefix.borrow().as_ref().map(Arc::clone)) + { + match self.strip_prefix(redaction_prefix) { + Ok(Some(stripped_path)) => return stripped_path.serialize(serializer), + Err(strip_error) => { + return Err(serde::ser::Error::custom(format!( + "Failed to redact absolute path '{}': {}", + self.as_path().display(), + strip_error + ))); + } + Ok(None) => { /* continue to serialize full path */ } + } + } + } + self.as_path().serialize(serializer) + } +} + impl PartialEq for AbsolutePath { fn eq(&self, other: &AbsolutePathBuf) -> bool { self.0 == other.0 @@ -46,6 +79,14 @@ impl From<&AbsolutePath> for Arc { } } +impl From<&AbsolutePath> for Box { + fn from(path: &AbsolutePath) -> Self { + let path_box: Box = path.0.into(); + let path_box_raw = Box::into_raw(path_box) as *mut AbsolutePath; + unsafe { Self::from_raw(path_box_raw) } + } +} + impl AbsolutePath { /// Creates a [`AbsolutePath`] if the give path is absolute. pub fn new + ?Sized>(path: &P) -> Option<&Self> { diff --git a/crates/vite_path/src/absolute/redaction.rs b/crates/vite_path/src/absolute/redaction.rs new file mode 100644 index 00000000..5bc81281 --- /dev/null +++ b/crates/vite_path/src/absolute/redaction.rs @@ -0,0 +1,25 @@ +use std::sync::Arc; + +use super::AbsolutePath; + +thread_local! { + pub(crate) static REDACTION_PREFIX: std::cell::RefCell>> = std::cell::RefCell::new(None); +} + +#[derive(Debug)] +pub struct RedactionGuard(()); + +impl Drop for RedactionGuard { + fn drop(&mut self) { + REDACTION_PREFIX.set(None); + } +} + +pub fn redact_absolute_paths(prefix: &Arc) -> RedactionGuard { + REDACTION_PREFIX.with(|redaction_prefix| { + let mut redaction_prefix = redaction_prefix.borrow_mut(); + assert!(redaction_prefix.is_none(), "RedactionGuard already active"); + *redaction_prefix = Some(Arc::clone(&prefix)); + }); + RedactionGuard(()) +} diff --git a/crates/vite_path/src/lib.rs b/crates/vite_path/src/lib.rs index 9014e4ef..87a3808f 100644 --- a/crates/vite_path/src/lib.rs +++ b/crates/vite_path/src/lib.rs @@ -3,6 +3,8 @@ pub mod relative; use std::io; +#[cfg(feature = "absolute-redaction")] +pub use absolute::redaction; pub use absolute::{AbsolutePath, AbsolutePathBuf}; pub use relative::{RelativePath, RelativePathBuf}; diff --git a/crates/vite_task/Cargo.toml b/crates/vite_task/Cargo.toml index 60396af1..25b22fd0 100644 --- a/crates/vite_task/Cargo.toml +++ b/crates/vite_task/Cargo.toml @@ -13,10 +13,13 @@ workspace = true [dependencies] anyhow = { workspace = true } +async-trait = { workspace = true } bincode = { workspace = true, features = ["derive"] } bstr = { workspace = true } +clap = { workspace = true, features = ["derive"] } compact_str = { workspace = true, features = ["serde"] } dashmap = { workspace = true } +derive_more = { workspace = true } diff-struct = { workspace = true } fspy = { workspace = true } futures-core = { workspace = true } @@ -41,6 +44,8 @@ vite_glob = { workspace = true } vite_path = { workspace = true } vite_shell = { workspace = true } vite_str = { workspace = true } +vite_task_graph = { workspace = true } +vite_task_plan = { workspace = true } vite_workspace = { workspace = true } wax = { workspace = true } @@ -48,4 +53,8 @@ wax = { workspace = true } nix = { workspace = true } [dev-dependencies] +copy_dir = { workspace = true } +insta = { workspace = true, features = ["glob", "json", "redactions"] } tempfile = { workspace = true } +toml = { workspace = true } +vite_path = { workspace = true, features = ["absolute-redaction"] } diff --git a/crates/vite_task/src/bin/vite.rs b/crates/vite_task/src/bin/vite.rs new file mode 100644 index 00000000..42acd1ac --- /dev/null +++ b/crates/vite_task/src/bin/vite.rs @@ -0,0 +1,13 @@ +use clap::Parser; +use vite_str::Str; +use vite_task::CLIArgs; + +#[derive(Debug, Parser)] +enum CustomTaskSubCommand { + /// oxlint + Lint { args: Vec }, +} + +fn main() { + let _subcommand = CLIArgs::::parse(); +} diff --git a/crates/vite_task/src/cli/mod.rs b/crates/vite_task/src/cli/mod.rs new file mode 100644 index 00000000..62b5736f --- /dev/null +++ b/crates/vite_task/src/cli/mod.rs @@ -0,0 +1,101 @@ +use std::sync::Arc; + +use clap::Subcommand; +use vite_path::AbsolutePath; +use vite_str::Str; +use vite_task_graph::{TaskSpecifier, query::TaskQueryKind}; +use vite_task_plan::plan_request::{PlanOptions, PlanRequest, QueryPlanRequest}; + +#[derive(Debug, clap::Parser)] +pub enum CLIArgs { + /// subcommands provided by vite task + #[command(flatten)] + ViteTaskSubCommand(ViteTaskSubCommand), + + /// custom subcommands provided by vite+ + #[command(flatten)] + Custom(CustomSubCommand), +} + +/// vite task CLI subcommands +#[derive(Debug, Subcommand)] +pub enum ViteTaskSubCommand { + /// Run tasks + Run { + /// `packageName#taskName` or `taskName`. + task_specifier: TaskSpecifier, + + /// Run tasks found in all packages in the workspace, in topological order based on package dependencies. + #[clap(default_value = "false", short, long)] + recursive: bool, + + /// Run tasks found in the current package and all its transitive dependencies, in topological order based on package dependencies. + #[clap(default_value = "false", short, long)] + transitive: bool, + + /// Do not run dependencies specified in `dependsOn` fields. + #[clap(default_value = "false", long)] + ignore_depends_on: bool, + + /// Additional arguments to pass to the tasks + #[clap(trailing_var_arg = true)] + additional_args: Vec, + }, +} + +#[derive(thiserror::Error, Debug)] +pub enum CLITaskQueryError { + #[error("--recursive and --transitive cannot be used together")] + RecursiveTransitiveConflict, + + #[error("cannot specify package '{package_name}' for task '{task_name}' with --recursive")] + PackageNameSpecifiedWithRecursive { package_name: Str, task_name: Str }, +} + +impl ViteTaskSubCommand { + /// Convert to `TaskQuery`, or return an error if invalid. + pub fn into_plan_request( + self, + cwd: &Arc, + ) -> Result { + match self { + Self::Run { + task_specifier, + recursive, + transitive, + ignore_depends_on, + additional_args, + } => { + let include_explicit_deps = !ignore_depends_on; + + let query_kind = if recursive { + if transitive { + return Err(CLITaskQueryError::RecursiveTransitiveConflict); + } + let task_name = if let Some(package_name) = task_specifier.package_name { + return Err(CLITaskQueryError::PackageNameSpecifiedWithRecursive { + package_name, + task_name: task_specifier.task_name, + }); + } else { + task_specifier.task_name + }; + TaskQueryKind::Recursive { task_names: [task_name].into() } + } else { + TaskQueryKind::Normal { + task_specifiers: [task_specifier].into(), + cwd: Arc::clone(cwd), + include_topological_deps: transitive, + } + }; + Ok(PlanRequest::Query(QueryPlanRequest { + query: vite_task_graph::query::TaskQuery { + kind: query_kind, + include_explicit_deps, + }, + plan_options: PlanOptions { extra_args: additional_args.into() }, + })) + } + } + } +} diff --git a/crates/vite_task/src/lib.rs b/crates/vite_task/src/lib.rs index 67a0fa25..88eb2f20 100644 --- a/crates/vite_task/src/lib.rs +++ b/crates/vite_task/src/lib.rs @@ -1,4 +1,5 @@ mod cache; +mod cli; mod collections; mod config; mod error; @@ -7,13 +8,16 @@ mod fingerprint; mod fs; mod maybe_str; mod schedule; +mod session; mod types; mod ui; // Public exports for vite-plus-cli to use pub use cache::TaskCache; +pub use cli::CLIArgs; pub use config::{ResolvedTask, Workspace}; pub use error::Error; pub use execute::{CURRENT_EXECUTION_ID, EXECUTION_SUMMARY_DIR}; pub use schedule::{ExecutionPlan, ExecutionStatus, ExecutionSummary}; +pub use session::{Session, SessionCallbacks}; pub use types::ResolveCommandResult; diff --git a/crates/vite_task/src/session.rs b/crates/vite_task/src/session.rs new file mode 100644 index 00000000..207547a5 --- /dev/null +++ b/crates/vite_task/src/session.rs @@ -0,0 +1,173 @@ +use std::{ffi::OsStr, fmt::Debug, sync::Arc}; + +use clap::Parser; +use vite_path::AbsolutePath; +use vite_str::Str; +use vite_task_graph::{IndexedTaskGraph, TaskGraph, TaskGraphLoadError, loader::UserConfigLoader}; +use vite_task_plan::{ + ExecutionPlan, TaskGraphLoader, TaskPlanErrorKind, + plan_request::{PlanRequest, SyntheticPlanRequest}, +}; +use vite_workspace::{WorkspaceRoot, find_workspace_root}; + +use crate::{CLIArgs, collections::HashMap}; + +#[derive(Debug)] +enum LazyTaskGraph<'a> { + Uninitialized { workspace_root: WorkspaceRoot, config_loader: &'a dyn UserConfigLoader }, + Initialized(IndexedTaskGraph), +} + +#[async_trait::async_trait(?Send)] +impl TaskGraphLoader for LazyTaskGraph<'_> { + async fn load_task_graph( + &mut self, + ) -> Result<&vite_task_graph::IndexedTaskGraph, TaskGraphLoadError> { + Ok(match self { + Self::Uninitialized { workspace_root, config_loader } => { + let graph = IndexedTaskGraph::load(workspace_root, *config_loader).await?; + *self = Self::Initialized(graph); + match self { + Self::Initialized(graph) => &*graph, + _ => unreachable!(), + } + } + Self::Initialized(graph) => &*graph, + }) + } +} + +pub struct SessionCallbacks<'a, CustomSubCommand> { + task_synthesizer: &'a mut (dyn TaskSynthesizer + 'a), + user_config_loader: &'a mut (dyn UserConfigLoader + 'a), +} + +#[async_trait::async_trait(?Send)] +pub trait TaskSynthesizer: Debug { + fn should_synthesize_for_program(&self, program: &str) -> bool; + async fn synthesize_task( + &mut self, + subcommand: CustomSubCommand, + cwd: &Arc, + ) -> anyhow::Result; +} + +#[derive(derive_more::Debug)] +#[debug(bound())] // Avoid requiring CustomSubCommand: Debug +struct PlanRequestParser<'a, CustomSubCommand> { + task_synthesizer: &'a mut (dyn TaskSynthesizer + 'a), +} + +impl PlanRequestParser<'_, CustomSubCommand> { + async fn get_plan_request_from_cli_args( + &mut self, + cli_args: CLIArgs, + cwd: &Arc, + ) -> anyhow::Result { + match cli_args { + CLIArgs::ViteTaskSubCommand(vite_task_subcommand) => { + Ok(vite_task_subcommand.into_plan_request(cwd)?) + } + CLIArgs::Custom(custom_subcommand) => { + let synthetic_plan_request = + self.task_synthesizer.synthesize_task(custom_subcommand, cwd).await?; + Ok(PlanRequest::Synthetic(synthetic_plan_request)) + } + } + } +} + +#[async_trait::async_trait(?Send)] +impl vite_task_plan::PlanRequestParser + for PlanRequestParser<'_, CustomSubCommand> +{ + async fn get_plan_request( + &mut self, + program: &str, + args: &[Str], + cwd: &Arc, + ) -> anyhow::Result> { + if !self.task_synthesizer.should_synthesize_for_program(program) { + return Ok(None); + } + let cli_args = CLIArgs::::try_parse_from( + std::iter::once(program).chain(args.iter().map(Str::as_str)), + )?; + Ok(Some(self.get_plan_request_from_cli_args(cli_args, cwd).await?)) + } +} + +/// Represents a vite task session for planning and executing tasks. A process typically has one session. +/// +/// A session manages task graph loading internally and provides non-consuming methods to plan and/or execute tasks (allows multiple plans/executions per session). +pub struct Session<'a, CustomSubCommand> { + workspace_path: Arc, + /// A session doesn't necessarily load the task graph immediately. + /// The task graph is loaded on-demand and cached for future use. + lazy_task_graph: LazyTaskGraph<'a>, + + envs: HashMap, Arc>, + cwd: Arc, + + plan_request_parser: PlanRequestParser<'a, CustomSubCommand>, +} + +impl<'a, CustomSubCommand> Session<'a, CustomSubCommand> { + /// Initialize a session with real environment variables and cwd + pub fn init(callbacks: SessionCallbacks<'a, CustomSubCommand>) -> anyhow::Result { + let envs = std::env::vars_os() + .map(|(k, v)| (Arc::::from(k.as_os_str()), Arc::::from(v.as_os_str()))) + .collect(); + Self::init_with(envs, vite_path::current_dir()?.into(), callbacks) + } + + /// Initialize a session with custom cwd, environment variables. Useful for testing. + pub fn init_with( + envs: HashMap, Arc>, + cwd: Arc, + callbacks: SessionCallbacks<'a, CustomSubCommand>, + ) -> anyhow::Result { + let (workspace_root, _) = find_workspace_root(&cwd)?; + Ok(Self { + workspace_path: Arc::clone(&workspace_root.path), + lazy_task_graph: LazyTaskGraph::Uninitialized { + workspace_root, + config_loader: callbacks.user_config_loader, + }, + envs, + cwd, + plan_request_parser: PlanRequestParser { task_synthesizer: callbacks.task_synthesizer }, + }) + } + + pub fn task_graph(&self) -> Option<&TaskGraph> { + match &self.lazy_task_graph { + LazyTaskGraph::Initialized(graph) => Some(graph.task_graph()), + _ => None, + } + } +} + +impl<'a, CustomSubCommand: clap::Subcommand> Session<'a, CustomSubCommand> { + pub async fn plan( + &mut self, + cli_args: CLIArgs, + ) -> Result { + let plan_request = self + .plan_request_parser + .get_plan_request_from_cli_args(cli_args, &self.cwd) + .await + .map_err(|error| { + TaskPlanErrorKind::ParsePlanRequestError { error }.with_empty_call_stack() + })?; + ExecutionPlan::plan( + plan_request, + &self.workspace_path, + &self.cwd, + &self.envs, + &mut self.plan_request_parser, + &mut self.lazy_task_graph, + ) + .await + } +} diff --git a/crates/vite_task_graph/tests/fixtures/cache-sharing/package.json b/crates/vite_task/tests/fixtures/cache-sharing/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/cache-sharing/package.json rename to crates/vite_task/tests/fixtures/cache-sharing/package.json diff --git a/crates/vite_task_graph/tests/fixtures/cache-sharing/pnpm-lock.yaml b/crates/vite_task/tests/fixtures/cache-sharing/pnpm-lock.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/cache-sharing/pnpm-lock.yaml rename to crates/vite_task/tests/fixtures/cache-sharing/pnpm-lock.yaml diff --git a/crates/vite_task_graph/tests/fixtures/cache-sharing/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/cache-sharing/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/cache-sharing/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/cache-sharing/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/api/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/api/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/api/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/api/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/app/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/app/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/app/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/app/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/config/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/config/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/config/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/config/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/pkg#special/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/pkg#special/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/pkg#special/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/pkg#special/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/shared/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/shared/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/shared/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/shared/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/tools/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/tools/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/tools/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/tools/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/ui/package.json b/crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/ui/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/packages/ui/package.json rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/packages/ui/package.json diff --git a/crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/comprehensive-task-graph/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/comprehensive-task-graph/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/comprehensive-task-graph/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/fixtures/conflict-test/package.json b/crates/vite_task/tests/fixtures/conflict-test/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/conflict-test/package.json rename to crates/vite_task/tests/fixtures/conflict-test/package.json diff --git a/crates/vite_task_graph/tests/fixtures/conflict-test/packages/scope-a-b/package.json b/crates/vite_task/tests/fixtures/conflict-test/packages/scope-a-b/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/conflict-test/packages/scope-a-b/package.json rename to crates/vite_task/tests/fixtures/conflict-test/packages/scope-a-b/package.json diff --git a/crates/vite_task_graph/tests/fixtures/conflict-test/packages/scope-a/package.json b/crates/vite_task/tests/fixtures/conflict-test/packages/scope-a/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/conflict-test/packages/scope-a/package.json rename to crates/vite_task/tests/fixtures/conflict-test/packages/scope-a/package.json diff --git a/crates/vite_task_graph/tests/fixtures/conflict-test/packages/test-package/package.json b/crates/vite_task/tests/fixtures/conflict-test/packages/test-package/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/conflict-test/packages/test-package/package.json rename to crates/vite_task/tests/fixtures/conflict-test/packages/test-package/package.json diff --git a/crates/vite_task_graph/tests/fixtures/conflict-test/packages/test-package/vite.config.json b/crates/vite_task/tests/fixtures/conflict-test/packages/test-package/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/conflict-test/packages/test-package/vite.config.json rename to crates/vite_task/tests/fixtures/conflict-test/packages/test-package/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/conflict-test/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/conflict-test/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/conflict-test/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/conflict-test/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/package.json b/crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/package.json rename to crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/package.json diff --git a/crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/packages/a/package.json b/crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/packages/a/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/packages/a/package.json rename to crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/packages/a/package.json diff --git a/crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/packages/a/vite.config.json b/crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/packages/a/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/packages/a/vite.config.json rename to crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/packages/a/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/packages/b/package.json b/crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/packages/b/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/packages/b/package.json rename to crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/packages/b/package.json diff --git a/crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/package.json b/crates/vite_task/tests/fixtures/empty-package-test/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/package.json rename to crates/vite_task/tests/fixtures/empty-package-test/package.json diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/packages/another-empty/package.json b/crates/vite_task/tests/fixtures/empty-package-test/packages/another-empty/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/packages/another-empty/package.json rename to crates/vite_task/tests/fixtures/empty-package-test/packages/another-empty/package.json diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/packages/another-empty/vite.config.json b/crates/vite_task/tests/fixtures/empty-package-test/packages/another-empty/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/packages/another-empty/vite.config.json rename to crates/vite_task/tests/fixtures/empty-package-test/packages/another-empty/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/packages/empty-name/package.json b/crates/vite_task/tests/fixtures/empty-package-test/packages/empty-name/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/packages/empty-name/package.json rename to crates/vite_task/tests/fixtures/empty-package-test/packages/empty-name/package.json diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/packages/empty-name/vite.config.json b/crates/vite_task/tests/fixtures/empty-package-test/packages/empty-name/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/packages/empty-name/vite.config.json rename to crates/vite_task/tests/fixtures/empty-package-test/packages/empty-name/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/packages/normal-package/package.json b/crates/vite_task/tests/fixtures/empty-package-test/packages/normal-package/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/packages/normal-package/package.json rename to crates/vite_task/tests/fixtures/empty-package-test/packages/normal-package/package.json diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/packages/normal-package/vite.config.json b/crates/vite_task/tests/fixtures/empty-package-test/packages/normal-package/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/packages/normal-package/vite.config.json rename to crates/vite_task/tests/fixtures/empty-package-test/packages/normal-package/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/empty-package-test/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/empty-package-test/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/empty-package-test/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/empty-package-test/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/package.json b/crates/vite_task/tests/fixtures/explicit-deps-workspace/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/package.json rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/package.json diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/app/package.json b/crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/app/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/app/package.json rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/app/package.json diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/app/vite.config.json b/crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/app/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/app/vite.config.json rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/app/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/core/package.json b/crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/core/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/core/package.json rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/core/package.json diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/core/vite.config.json b/crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/core/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/core/vite.config.json rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/core/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/utils/package.json b/crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/utils/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/utils/package.json rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/utils/package.json diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/utils/vite.config.json b/crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/utils/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/packages/utils/vite.config.json rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/packages/utils/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/explicit-deps-workspace/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/explicit-deps-workspace/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/explicit-deps-workspace/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/fixtures/fingerprint-ignore-test/README.md b/crates/vite_task/tests/fixtures/fingerprint-ignore-test/README.md similarity index 100% rename from crates/vite_task_graph/tests/fixtures/fingerprint-ignore-test/README.md rename to crates/vite_task/tests/fixtures/fingerprint-ignore-test/README.md diff --git a/crates/vite_task_graph/tests/fixtures/fingerprint-ignore-test/package.json b/crates/vite_task/tests/fixtures/fingerprint-ignore-test/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/fingerprint-ignore-test/package.json rename to crates/vite_task/tests/fixtures/fingerprint-ignore-test/package.json diff --git a/crates/vite_task_graph/tests/fixtures/fingerprint-ignore-test/vite.config.json b/crates/vite_task/tests/fixtures/fingerprint-ignore-test/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/fingerprint-ignore-test/vite.config.json rename to crates/vite_task/tests/fixtures/fingerprint-ignore-test/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/apps/web/package.json b/crates/vite_task/tests/fixtures/recursive-topological-workspace/apps/web/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/apps/web/package.json rename to crates/vite_task/tests/fixtures/recursive-topological-workspace/apps/web/package.json diff --git a/crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/package.json b/crates/vite_task/tests/fixtures/recursive-topological-workspace/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/package.json rename to crates/vite_task/tests/fixtures/recursive-topological-workspace/package.json diff --git a/crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/packages/app/package.json b/crates/vite_task/tests/fixtures/recursive-topological-workspace/packages/app/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/packages/app/package.json rename to crates/vite_task/tests/fixtures/recursive-topological-workspace/packages/app/package.json diff --git a/crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/packages/core/package.json b/crates/vite_task/tests/fixtures/recursive-topological-workspace/packages/core/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/packages/core/package.json rename to crates/vite_task/tests/fixtures/recursive-topological-workspace/packages/core/package.json diff --git a/crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/packages/utils/package.json b/crates/vite_task/tests/fixtures/recursive-topological-workspace/packages/utils/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/packages/utils/package.json rename to crates/vite_task/tests/fixtures/recursive-topological-workspace/packages/utils/package.json diff --git a/crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/recursive-topological-workspace/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/recursive-topological-workspace/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/recursive-topological-workspace/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/cli-queries.toml b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/cli-queries.toml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/cli-queries.toml rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/cli-queries.toml diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/a/package.json b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/a/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/a/package.json rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/a/package.json diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/a/src/.gitkeep b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/a/src/.gitkeep similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/a/src/.gitkeep rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/a/src/.gitkeep diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/a/vite.config.json b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/a/vite.config.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/a/vite.config.json rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/a/vite.config.json diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/another-a/package.json b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/another-a/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/another-a/package.json rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/another-a/package.json diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/b1/package.json b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/b1/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/b1/package.json rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/b1/package.json diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/b2/package.json b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/b2/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/b2/package.json rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/b2/package.json diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/c/package.json b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/c/package.json similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/packages/c/package.json rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/packages/c/package.json diff --git a/crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/pnpm-workspace.yaml b/crates/vite_task/tests/fixtures/transitive-dependency-workspace/pnpm-workspace.yaml similarity index 100% rename from crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace/pnpm-workspace.yaml rename to crates/vite_task/tests/fixtures/transitive-dependency-workspace/pnpm-workspace.yaml diff --git a/crates/vite_task_graph/tests/snapshots.rs b/crates/vite_task/tests/snapshots.rs similarity index 63% rename from crates/vite_task_graph/tests/snapshots.rs rename to crates/vite_task/tests/snapshots.rs index 6f29798f..e003ca7d 100644 --- a/crates/vite_task_graph/tests/snapshots.rs +++ b/crates/vite_task/tests/snapshots.rs @@ -5,34 +5,26 @@ use clap::Parser; use copy_dir::copy_dir; use petgraph::visit::EdgeRef as _; use tokio::runtime::Runtime; -use vite_path::{AbsolutePath, RelativePathBuf}; +use vite_path::{AbsolutePath, RelativePathBuf, redaction::redact_absolute_paths}; use vite_str::Str; use vite_task_graph::{ - IndexedTaskGraph, SpecifierLookupError, TaskDependencyType, TaskNodeIndex, + IndexedTaskGraph, TaskDependencyType, TaskNodeIndex, loader::JsonUserConfigLoader, - query::{PackageUnknownError, TaskExecutionGraph, TaskQueryError, cli::CLITaskQuery}, + query::{TaskExecutionGraph, cli::CLITaskQuery}, }; use vite_workspace::find_workspace_root; #[derive(serde::Serialize, PartialEq, PartialOrd, Eq, Ord)] struct TaskIdSnapshot { - package_dir: RelativePathBuf, + package_dir: Arc, task_name: Str, } impl TaskIdSnapshot { - fn new( - task_index: TaskNodeIndex, - base_dir: &AbsolutePath, - indexed_task_graph: &IndexedTaskGraph, - ) -> Self { + fn new(task_index: TaskNodeIndex, indexed_task_graph: &IndexedTaskGraph) -> Self { let task_id = &indexed_task_graph.task_graph()[task_index].task_id; Self { task_name: task_id.task_name.clone(), - package_dir: indexed_task_graph - .get_package_path(task_id.package_index) - .strip_prefix(base_dir) - .unwrap() - .unwrap(), + package_dir: Arc::clone(&indexed_task_graph.get_package_path(task_id.package_index)), } } } @@ -40,15 +32,12 @@ impl TaskIdSnapshot { /// Create a stable json representation of the task graph for snapshot testing. /// /// All paths are relative to `base_dir`. -fn snapshot_task_graph( - indexed_task_graph: &IndexedTaskGraph, - base_dir: &AbsolutePath, -) -> impl serde::Serialize { +fn snapshot_task_graph(indexed_task_graph: &IndexedTaskGraph) -> impl serde::Serialize { #[derive(serde::Serialize)] struct TaskNodeSnapshot { id: TaskIdSnapshot, command: Str, - cwd: RelativePathBuf, + cwd: Arc, depends_on: Vec<(TaskIdSnapshot, TaskDependencyType)>, } @@ -58,21 +47,13 @@ fn snapshot_task_graph( let task_node = &task_graph[task_index]; let mut depends_on: Vec<(TaskIdSnapshot, TaskDependencyType)> = task_graph .edges_directed(task_index, petgraph::Direction::Outgoing) - .map(|edge| { - (TaskIdSnapshot::new(edge.target(), base_dir, indexed_task_graph), *edge.weight()) - }) + .map(|edge| (TaskIdSnapshot::new(edge.target(), indexed_task_graph), *edge.weight())) .collect(); depends_on.sort_unstable_by(|a, b| a.0.cmp(&b.0)); node_snapshots.push(TaskNodeSnapshot { - id: TaskIdSnapshot::new(task_index, base_dir, indexed_task_graph), + id: TaskIdSnapshot::new(task_index, indexed_task_graph), command: task_node.resolved_config.command.clone(), - cwd: task_node - .resolved_config - .resolved_options - .cwd - .strip_prefix(base_dir) - .unwrap() - .unwrap(), + cwd: Arc::clone(&task_node.resolved_config.resolved_options.cwd), depends_on, }); } @@ -87,7 +68,6 @@ fn snapshot_task_graph( fn snapshot_execution_graph( execution_graph: &TaskExecutionGraph, indexed_task_graph: &IndexedTaskGraph, - base_dir: &AbsolutePath, ) -> impl serde::Serialize { #[derive(serde::Serialize, PartialEq)] struct ExecutionNodeSnapshot { @@ -99,12 +79,12 @@ fn snapshot_execution_graph( for task_index in execution_graph.nodes() { let mut deps = execution_graph .neighbors(task_index) - .map(|dep_index| TaskIdSnapshot::new(dep_index, base_dir, indexed_task_graph)) + .map(|dep_index| TaskIdSnapshot::new(dep_index, indexed_task_graph)) .collect::>(); deps.sort_unstable(); execution_node_snapshots.push(ExecutionNodeSnapshot { - task: TaskIdSnapshot::new(task_index, base_dir, indexed_task_graph), + task: TaskIdSnapshot::new(task_index, indexed_task_graph), deps, }); } @@ -112,35 +92,6 @@ fn snapshot_execution_graph( execution_node_snapshots } -/// Modify absolute paths to be stable across different tmpdir locations. -fn stabilize_absolute_path(path: &mut Arc, base_dir: &AbsolutePath) { - let relative_path = path.strip_prefix(base_dir).unwrap().unwrap(); - // this path is considered absolute on all platforms - let new_base_dir = AbsolutePath::new("//?/workspace/").unwrap(); - *path = new_base_dir.join(relative_path).into(); -} - -/// Modify absolute paths in the SpecifierLookupError to be stable across different tmpdir locations. -fn stabilize_specifier_lookup_error( - err: &mut SpecifierLookupError, - base_dir: &AbsolutePath, -) { - match err { - SpecifierLookupError::AmbiguousPackageName { package_paths, .. } => { - for path in package_paths.iter_mut() { - stabilize_absolute_path(path, base_dir); - } - } - SpecifierLookupError::PackageNameNotFound { .. } => {} - SpecifierLookupError::TaskNameNotFound { package_index, .. } => { - *package_index = Default::default() - } - SpecifierLookupError::PackageUnknown { unspecifier_package_error, .. } => { - stabilize_absolute_path(&mut unspecifier_package_error.cwd, base_dir); - } - } -} - #[derive(serde::Deserialize)] struct CLIQuery { pub name: Str, @@ -180,14 +131,16 @@ fn run_case(runtime: &Runtime, tmpdir: &AbsolutePath, case_path: &Path) { }; runtime.block_on(async { + let _redaction_guard = redact_absolute_paths(&workspace_root.path); + let indexed_task_graph = vite_task_graph::IndexedTaskGraph::load( - workspace_root, - JsonUserConfigLoader::default(), + &workspace_root, + &JsonUserConfigLoader::default(), ) .await .expect(&format!("Failed to load task graph for case {case_name}")); - let task_graph_snapshot = snapshot_task_graph(&indexed_task_graph, &case_stage_path); + let task_graph_snapshot = snapshot_task_graph(&indexed_task_graph); insta::assert_json_snapshot!("task graph", task_graph_snapshot); for cli_query in cli_queries_file.queries { @@ -206,26 +159,21 @@ fn run_case(runtime: &Runtime, tmpdir: &AbsolutePath, case_path: &Path) { let task_query = match cli_task_query.into_task_query(&cwd) { Ok(ok) => ok, Err(err) => { - insta::assert_debug_snapshot!(snapshot_name, err); + insta::assert_json_snapshot!(snapshot_name, err); continue; } }; let execution_graph = match indexed_task_graph.query_tasks(task_query) { Ok(ok) => ok, - Err(mut err) => { - match &mut err { - TaskQueryError::SpecifierLookupError { lookup_error, .. } => { - stabilize_specifier_lookup_error(lookup_error, &case_stage_path); - } - } - insta::assert_debug_snapshot!(snapshot_name, err); + Err(err) => { + insta::assert_json_snapshot!(snapshot_name, err); continue; } }; let execution_graph_snapshot = - snapshot_execution_graph(&execution_graph, &indexed_task_graph, &case_stage_path); + snapshot_execution_graph(&execution_graph, &indexed_task_graph); insta::assert_json_snapshot!(snapshot_name, execution_graph_snapshot); } }); @@ -236,5 +184,6 @@ fn test_snapshots() { let tokio_runtime = Runtime::new().unwrap(); let tmp_dir = tempfile::tempdir().unwrap(); let tmp_dir_path = AbsolutePath::new(tmp_dir.path()).unwrap(); + insta::glob!("fixtures/*", |case_path| run_case(&tokio_runtime, tmp_dir_path, case_path)); } diff --git a/crates/vite_task/tests/snapshots/snapshots__query - ambiguous task name@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - ambiguous task name@transitive-dependency-workspace.snap new file mode 100644 index 00000000..eafd86a2 --- /dev/null +++ b/crates/vite_task/tests/snapshots/snapshots__query - ambiguous task name@transitive-dependency-workspace.snap @@ -0,0 +1,22 @@ +--- +source: crates/vite_task/tests/snapshots.rs +expression: err +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace +--- +{ + "SpecifierLookupError": { + "specifier": { + "package_name": "@test/a", + "task_name": "build" + }, + "lookup_error": { + "AmbiguousPackageName": { + "package_name": "@test/a", + "package_paths": [ + "packages/a", + "packages/another-a" + ] + } + } + } +} diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - explicit package name under different package@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - explicit package name under different package@transitive-dependency-workspace.snap similarity index 54% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - explicit package name under different package@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - explicit package name under different package@transitive-dependency-workspace.snap index f5e5cacc..3ff92394 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - explicit package name under different package@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - explicit package name under different package@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - explicit package name under non-package cwd@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - explicit package name under non-package cwd@transitive-dependency-workspace.snap similarity index 54% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - explicit package name under non-package cwd@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - explicit package name under non-package cwd@transitive-dependency-workspace.snap index f5e5cacc..3ff92394 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - explicit package name under non-package cwd@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - explicit package name under non-package cwd@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - ignore depends on@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - ignore depends on@transitive-dependency-workspace.snap similarity index 54% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - ignore depends on@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - ignore depends on@transitive-dependency-workspace.snap index 32511355..5a65e8f5 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - ignore depends on@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - ignore depends on@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task/tests/snapshots/snapshots__query - recursive and transitive@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - recursive and transitive@transitive-dependency-workspace.snap new file mode 100644 index 00000000..c267178d --- /dev/null +++ b/crates/vite_task/tests/snapshots/snapshots__query - recursive and transitive@transitive-dependency-workspace.snap @@ -0,0 +1,6 @@ +--- +source: crates/vite_task/tests/snapshots.rs +expression: err +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace +--- +"RecursiveTransitiveConflict" diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - recursive@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - recursive@transitive-dependency-workspace.snap similarity index 87% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - recursive@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - recursive@transitive-dependency-workspace.snap index b438fcb0..fdc5c1a5 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - recursive@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - recursive@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - simple task by name@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - simple task by name@transitive-dependency-workspace.snap similarity index 72% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - simple task by name@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - simple task by name@transitive-dependency-workspace.snap index 71d68865..41fc332c 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - simple task by name@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - simple task by name@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - transitive in package without the task@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - transitive in package without the task@transitive-dependency-workspace.snap similarity index 72% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - transitive in package without the task@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - transitive in package without the task@transitive-dependency-workspace.snap index e01dc8dd..95c858b1 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - transitive in package without the task@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - transitive in package without the task@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task/tests/snapshots/snapshots__query - transitive non existent task@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - transitive non existent task@transitive-dependency-workspace.snap new file mode 100644 index 00000000..3e61cf81 --- /dev/null +++ b/crates/vite_task/tests/snapshots/snapshots__query - transitive non existent task@transitive-dependency-workspace.snap @@ -0,0 +1,19 @@ +--- +source: crates/vite_task/tests/snapshots.rs +expression: err +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace +--- +{ + "SpecifierLookupError": { + "specifier": { + "package_name": null, + "task_name": "non-existent-task" + }, + "lookup_error": { + "TaskNameNotFound": { + "package_name": "@test/a", + "task_name": "non-existent-task" + } + } + } +} diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - transitive@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - transitive@transitive-dependency-workspace.snap similarity index 86% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - transitive@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - transitive@transitive-dependency-workspace.snap index 5036dfa5..826bebad 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - transitive@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - transitive@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - under subfolder of package@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__query - under subfolder of package@transitive-dependency-workspace.snap similarity index 72% rename from crates/vite_task_graph/tests/snapshots/snapshots__query - under subfolder of package@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__query - under subfolder of package@transitive-dependency-workspace.snap index 71d68865..41fc332c 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - under subfolder of package@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__query - under subfolder of package@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: execution_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@cache-sharing.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@cache-sharing.snap similarity index 80% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@cache-sharing.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@cache-sharing.snap index 684053b5..2f23f391 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@cache-sharing.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@cache-sharing.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/cache-sharing +input_file: crates/vite_task/tests/fixtures/cache-sharing --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@comprehensive-task-graph.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@comprehensive-task-graph.snap similarity index 98% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@comprehensive-task-graph.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@comprehensive-task-graph.snap index 18d8e441..d0e44840 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@comprehensive-task-graph.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@comprehensive-task-graph.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/comprehensive-task-graph +input_file: crates/vite_task/tests/fixtures/comprehensive-task-graph --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@conflict-test.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@conflict-test.snap similarity index 86% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@conflict-test.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@conflict-test.snap index ad54a4dd..80e5603f 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@conflict-test.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@conflict-test.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/conflict-test +input_file: crates/vite_task/tests/fixtures/conflict-test --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@dependency-both-topo-and-explicit.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@dependency-both-topo-and-explicit.snap similarity index 78% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@dependency-both-topo-and-explicit.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@dependency-both-topo-and-explicit.snap index 71a4231f..b609a8d2 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@dependency-both-topo-and-explicit.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@dependency-both-topo-and-explicit.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/dependency-both-topo-and-explicit +input_file: crates/vite_task/tests/fixtures/dependency-both-topo-and-explicit --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@empty-package-test.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@empty-package-test.snap similarity index 96% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@empty-package-test.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@empty-package-test.snap index b1414a3a..5508e88e 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@empty-package-test.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@empty-package-test.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/empty-package-test +input_file: crates/vite_task/tests/fixtures/empty-package-test --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@explicit-deps-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@explicit-deps-workspace.snap similarity index 96% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@explicit-deps-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@explicit-deps-workspace.snap index a4c34726..f2e12dd0 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@explicit-deps-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@explicit-deps-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/explicit-deps-workspace +input_file: crates/vite_task/tests/fixtures/explicit-deps-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@fingerprint-ignore-test.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@fingerprint-ignore-test.snap similarity index 75% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@fingerprint-ignore-test.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@fingerprint-ignore-test.snap index 6e6714cd..67c9f908 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@fingerprint-ignore-test.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@fingerprint-ignore-test.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/fingerprint-ignore-test +input_file: crates/vite_task/tests/fixtures/fingerprint-ignore-test --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@recursive-topological-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@recursive-topological-workspace.snap similarity index 94% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@recursive-topological-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@recursive-topological-workspace.snap index 941231f8..fef43080 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@recursive-topological-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@recursive-topological-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/recursive-topological-workspace +input_file: crates/vite_task/tests/fixtures/recursive-topological-workspace --- [ { diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@transitive-dependency-workspace.snap b/crates/vite_task/tests/snapshots/snapshots__task graph@transitive-dependency-workspace.snap similarity index 93% rename from crates/vite_task_graph/tests/snapshots/snapshots__task graph@transitive-dependency-workspace.snap rename to crates/vite_task/tests/snapshots/snapshots__task graph@transitive-dependency-workspace.snap index 62952fda..98b23222 100644 --- a/crates/vite_task_graph/tests/snapshots/snapshots__task graph@transitive-dependency-workspace.snap +++ b/crates/vite_task/tests/snapshots/snapshots__task graph@transitive-dependency-workspace.snap @@ -1,7 +1,7 @@ --- -source: crates/vite_task_graph/tests/snapshots.rs +source: crates/vite_task/tests/snapshots.rs expression: task_graph_snapshot -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace +input_file: crates/vite_task/tests/fixtures/transitive-dependency-workspace --- [ { diff --git a/crates/vite_task_bin/Cargo.toml b/crates/vite_task_bin/Cargo.toml deleted file mode 100644 index 58b13455..00000000 --- a/crates/vite_task_bin/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "vite_task_bin" -version = "0.1.0" -authors.workspace = true -edition.workspace = true -license.workspace = true -rust-version.workspace = true - -[[bin]] -name = "vite" -path = "src/vite.rs" - -[dependencies] -clap = { workspace = true, features = ["derive"] } -vite_str = { workspace = true } -vite_task_graph = { path = "../vite_task_graph" } - -[lints] -workspace = true diff --git a/crates/vite_task_bin/src/vite.rs b/crates/vite_task_bin/src/vite.rs deleted file mode 100644 index 9b675bfa..00000000 --- a/crates/vite_task_bin/src/vite.rs +++ /dev/null @@ -1,19 +0,0 @@ -use clap::Parser; -use vite_str::Str; - -#[derive(Parser)] -enum SubCommand { - /// Run tasks - Run { - #[clap(flatten)] - query: vite_task_graph::query::cli::CLITaskQuery, - - /// Additional arguments to pass to the tasks - #[clap(last = true)] - args: Vec, - }, -} - -fn main() { - let _subcommand = SubCommand::parse(); -} diff --git a/crates/vite_task_graph/Cargo.toml b/crates/vite_task_graph/Cargo.toml index 15ebfb2a..9df01208 100644 --- a/crates/vite_task_graph/Cargo.toml +++ b/crates/vite_task_graph/Cargo.toml @@ -8,6 +8,7 @@ rust-version.workspace = true [dependencies] anyhow = { workspace = true } +async-trait = { workspace = true } clap = { workspace = true, features = ["derive"] } monostate = "1.0.2" petgraph = { workspace = true } @@ -21,11 +22,7 @@ vite_str = { workspace = true } vite_workspace = { workspace = true } [dev-dependencies] -copy_dir = { workspace = true } -insta = { workspace = true, features = ["glob", "json"] } -tempfile = { workspace = true } tokio = { workspace = true, features = ["fs", "rt-multi-thread"] } -toml = { workspace = true } [lints] workspace = true diff --git a/crates/vite_task_graph/src/lib.rs b/crates/vite_task_graph/src/lib.rs index a159cd3f..755929a2 100644 --- a/crates/vite_task_graph/src/lib.rs +++ b/crates/vite_task_graph/src/lib.rs @@ -18,7 +18,7 @@ use petgraph::{ visit::{Control, DfsEvent, depth_first_search}, }; use serde::Serialize; -use specifier::TaskSpecifier; +pub use specifier::TaskSpecifier; use vec1::smallvec_v1::SmallVec1; use vite_path::AbsolutePath; use vite_str::Str; @@ -116,7 +116,7 @@ pub enum TaskGraphLoadError { /// /// - When the specifier is from `dependOn` of a known task, `UnknownPackageError` is `Infallible` because the origin package is always known. /// - When the specifier is from a CLI command, `UnknownPackageError` can be a real error type in case cwd is not in any package. -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, Serialize)] pub enum SpecifierLookupError { #[error("Package '{package_name}' is ambiguous among multiple packages: {package_paths:?}")] AmbiguousPackageName { package_name: Str, package_paths: Box<[Arc]> }, @@ -125,7 +125,12 @@ pub enum SpecifierLookupError { PackageNameNotFound { package_name: Str }, #[error("Task '{task_name}' not found in package {package_name}")] - TaskNameNotFound { package_name: Str, task_name: Str, package_index: PackageNodeIndex }, + TaskNameNotFound { + package_name: Str, + task_name: Str, + #[serde(skip)] + package_index: PackageNodeIndex, + }, #[error( "Nowhere to look for task '{task_name}' because the package is unknown: {unspecifier_package_error}" @@ -175,12 +180,12 @@ pub type TaskGraph = DiGraph; impl IndexedTaskGraph { /// Load the task graph from a discovered workspace using the provided config loader. pub async fn load( - workspace_root: WorkspaceRoot, - config_loader: impl loader::UserConfigLoader, + workspace_root: &WorkspaceRoot, + config_loader: &dyn loader::UserConfigLoader, ) -> Result { let mut task_graph = DiGraph::::default(); - let package_graph = vite_workspace::load_package_graph(&workspace_root)?; + let package_graph = vite_workspace::load_package_graph(workspace_root)?; // Record dependency specifiers for each task node to add explicit dependencies later let mut dependency_specifiers_with_task_node_indices: Vec<(Arc<[Str]>, TaskNodeIndex)> = diff --git a/crates/vite_task_graph/src/loader.rs b/crates/vite_task_graph/src/loader.rs index 7a3c932b..0b699bb7 100644 --- a/crates/vite_task_graph/src/loader.rs +++ b/crates/vite_task_graph/src/loader.rs @@ -1,13 +1,16 @@ +use std::fmt::Debug; + use vite_path::AbsolutePath; use crate::config::UserConfigFile; /// Loader trait for loading user configuration files (vite.config.*). -pub trait UserConfigLoader { - fn load_user_config_file( +#[async_trait::async_trait(?Send)] +pub trait UserConfigLoader: Debug + Send + Sync { + async fn load_user_config_file( &self, package_path: &AbsolutePath, - ) -> impl std::future::Future> + Send; + ) -> anyhow::Result; } /// A `UserConfigLoader` implementation that only loads `vite.config.json`. @@ -16,22 +19,21 @@ pub trait UserConfigLoader { #[derive(Default, Debug)] pub struct JsonUserConfigLoader(()); +#[async_trait::async_trait(?Send)] impl UserConfigLoader for JsonUserConfigLoader { - fn load_user_config_file( + async fn load_user_config_file( &self, package_path: &AbsolutePath, - ) -> impl std::future::Future> + Send { - async move { - let config_path = package_path.join("vite.config.json"); - let config_content = match tokio::fs::read_to_string(&config_path).await { - Ok(content) => content, - Err(err) if err.kind() == std::io::ErrorKind::NotFound => { - return Ok(UserConfigFile { tasks: Default::default() }); - } - Err(err) => return Err(err.into()), - }; - let user_config: UserConfigFile = serde_json::from_str(&config_content)?; - Ok(user_config) - } + ) -> anyhow::Result { + let config_path = package_path.join("vite.config.json"); + let config_content = match tokio::fs::read_to_string(&config_path).await { + Ok(content) => content, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + return Ok(UserConfigFile { tasks: Default::default() }); + } + Err(err) => return Err(err.into()), + }; + let user_config: UserConfigFile = serde_json::from_str(&config_content)?; + Ok(user_config) } } diff --git a/crates/vite_task_graph/src/query/cli.rs b/crates/vite_task_graph/src/query/cli.rs index cb5e6e41..6824a5f9 100644 --- a/crates/vite_task_graph/src/query/cli.rs +++ b/crates/vite_task_graph/src/query/cli.rs @@ -1,5 +1,6 @@ use std::{collections::HashSet, sync::Arc}; +use serde::Serialize; use vite_path::AbsolutePath; use vite_str::Str; @@ -27,7 +28,7 @@ pub struct CLITaskQuery { ignore_depends_on: bool, } -#[derive(thiserror::Error, Debug)] +#[derive(thiserror::Error, Debug, Serialize)] pub enum CLITaskQueryError { #[error("--recursive and --transitive cannot be used together")] RecursiveTransitiveConflict, diff --git a/crates/vite_task_graph/src/query/mod.rs b/crates/vite_task_graph/src/query/mod.rs index eebcc9cc..b5c41519 100644 --- a/crates/vite_task_graph/src/query/mod.rs +++ b/crates/vite_task_graph/src/query/mod.rs @@ -3,6 +3,7 @@ pub mod cli; use std::{collections::HashSet, sync::Arc}; use petgraph::{prelude::DiGraphMap, visit::EdgeRef}; +use serde::Serialize; use vite_path::AbsolutePath; use vite_str::Str; @@ -45,13 +46,13 @@ pub struct TaskQuery { /// The edges represent the final dependency relationships between tasks. No edge weights. pub type TaskExecutionGraph = DiGraphMap; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, Serialize)] #[error("The current working directory {cwd:?} is in not any package")] pub struct PackageUnknownError { pub cwd: Arc, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, Serialize)] pub enum TaskQueryError { #[error("Failed to look up task from specifier: {specifier}")] SpecifierLookupError { diff --git a/crates/vite_task_graph/src/specifier.rs b/crates/vite_task_graph/src/specifier.rs index 5bb2d586..c69241ff 100644 --- a/crates/vite_task_graph/src/specifier.rs +++ b/crates/vite_task_graph/src/specifier.rs @@ -1,12 +1,13 @@ use std::{convert::Infallible, fmt::Display, str::FromStr}; +use serde::Serialize; use vite_str::Str; /// Parsed task specifier (`"packageName#taskName"` or `"taskName"`) /// /// For `taskName`, `package_name` will be `None`. /// For `#taskName`, `package_name` will be `Some("")`. It's valid to have an empty package name. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)] pub struct TaskSpecifier { pub package_name: Option, pub task_name: Str, diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - ambiguous task name@transitive-dependency-workspace.snap b/crates/vite_task_graph/tests/snapshots/snapshots__query - ambiguous task name@transitive-dependency-workspace.snap deleted file mode 100644 index 0fab07dd..00000000 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - ambiguous task name@transitive-dependency-workspace.snap +++ /dev/null @@ -1,24 +0,0 @@ ---- -source: crates/vite_task_graph/tests/snapshots.rs -expression: err -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace ---- -SpecifierLookupError { - specifier: TaskSpecifier { - package_name: Some( - "@test/a", - ), - task_name: "build", - }, - lookup_error: AmbiguousPackageName { - package_name: "@test/a", - package_paths: [ - AbsolutePath( - "//?/workspace/packages/a", - ), - AbsolutePath( - "//?/workspace/packages/another-a", - ), - ], - }, -} diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - recursive and transitive@transitive-dependency-workspace.snap b/crates/vite_task_graph/tests/snapshots/snapshots__query - recursive and transitive@transitive-dependency-workspace.snap deleted file mode 100644 index 662f385a..00000000 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - recursive and transitive@transitive-dependency-workspace.snap +++ /dev/null @@ -1,6 +0,0 @@ ---- -source: crates/vite_task_graph/tests/snapshots.rs -expression: err -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace ---- -RecursiveTransitiveConflict diff --git a/crates/vite_task_graph/tests/snapshots/snapshots__query - transitive non existent task@transitive-dependency-workspace.snap b/crates/vite_task_graph/tests/snapshots/snapshots__query - transitive non existent task@transitive-dependency-workspace.snap deleted file mode 100644 index c2d9b7b7..00000000 --- a/crates/vite_task_graph/tests/snapshots/snapshots__query - transitive non existent task@transitive-dependency-workspace.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: crates/vite_task_graph/tests/snapshots.rs -expression: err -input_file: crates/vite_task_graph/tests/fixtures/transitive-dependency-workspace ---- -SpecifierLookupError { - specifier: TaskSpecifier { - package_name: None, - task_name: "non-existent-task", - }, - lookup_error: TaskNameNotFound { - package_name: "@test/a", - task_name: "non-existent-task", - package_index: NodeIndex(PackageIx(0)), - }, -} diff --git a/crates/vite_task_plan/Cargo.toml b/crates/vite_task_plan/Cargo.toml index ccbc124b..b3ebad6a 100644 --- a/crates/vite_task_plan/Cargo.toml +++ b/crates/vite_task_plan/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] anyhow = { workspace = true } -futures-core = { workspace = true } +async-trait = { workspace = true } futures-util = { workspace = true } petgraph = { workspace = true } sha2 = { workspace = true } diff --git a/crates/vite_task_plan/src/context.rs b/crates/vite_task_plan/src/context.rs index a15462bc..d50803a5 100644 --- a/crates/vite_task_plan/src/context.rs +++ b/crates/vite_task_plan/src/context.rs @@ -5,7 +5,7 @@ use std::{ use vite_path::AbsolutePath; use vite_task_graph::{IndexedTaskGraph, TaskNodeIndex, display::TaskDisplay}; -use crate::{PlanCallbacks, path_env::prepend_path_env}; +use crate::{PlanRequestParser, path_env::prepend_path_env}; #[derive(Debug, thiserror::Error)] #[error( @@ -20,18 +20,18 @@ pub struct TaskRecursionError { #[derive(Debug)] pub struct PlanContext<'a> { /// The current working directory. - pub cwd: Arc, + cwd: Arc, /// The environment variables for the current execution context. - pub envs: HashMap, Arc>, + envs: HashMap, Arc>, /// The callbacks for loading task graphs and parsing commands. - pub callbacks: &'a mut (dyn PlanCallbacks + 'a), + callbacks: &'a mut (dyn PlanRequestParser + 'a), /// The current call stack of task index nodes being planned. - pub task_call_stack: Vec<(TaskNodeIndex, Range)>, + task_call_stack: Vec<(TaskNodeIndex, Range)>, - pub indexed_task_graph: &'a IndexedTaskGraph, + indexed_task_graph: &'a IndexedTaskGraph, } /// A human-readable frame in the task call stack. @@ -69,6 +69,15 @@ impl Display for TaskCallStackDisplay { } impl<'a> PlanContext<'a> { + pub fn new( + cwd: Arc, + envs: HashMap, Arc>, + callbacks: &'a mut (dyn PlanRequestParser + 'a), + indexed_task_graph: &'a IndexedTaskGraph, + ) -> Self { + Self { cwd, envs, callbacks, task_call_stack: Vec::new(), indexed_task_graph } + } + pub fn cwd(&self) -> &Arc { &self.cwd } @@ -113,7 +122,7 @@ impl<'a> PlanContext<'a> { self.task_call_stack.push((task_node_index, command_span)); } - pub fn callbacks(&mut self) -> &mut (dyn PlanCallbacks + '_) { + pub fn callbacks(&mut self) -> &mut (dyn PlanRequestParser + '_) { self.callbacks } diff --git a/crates/vite_task_plan/src/error.rs b/crates/vite_task_plan/src/error.rs index b656c232..45e00a30 100644 --- a/crates/vite_task_plan/src/error.rs +++ b/crates/vite_task_plan/src/error.rs @@ -1,7 +1,5 @@ use std::env::JoinPathsError; -use vite_task_graph::display::TaskDisplay; - use crate::{ context::{PlanContext, TaskCallStackDisplay, TaskRecursionError}, envs::ResolveEnvError, @@ -35,10 +33,6 @@ pub enum TaskPlanErrorKind { #[error("Failed to add node_modules/.bin to PATH environment variable")] AddNodeModulesBinPathError { - /// This error occurred before parse the command of the task, - /// so the task call stack doesn't contain the current task (no command_span yet). - /// This field is where the error occurred, while the task call stack is the stack leading to it.s - task_display: TaskDisplay, #[source] join_paths_error: JoinPathsError, }, @@ -56,6 +50,12 @@ pub struct Error { kind: TaskPlanErrorKind, } +impl TaskPlanErrorKind { + pub fn with_empty_call_stack(self) -> Error { + Error { task_call_stack: TaskCallStackDisplay::default(), kind: self } + } +} + pub(crate) trait TaskPlanErrorKindResultExt { type Ok; /// Attach the current task call stack from the planning context to the error. @@ -82,10 +82,7 @@ impl TaskPlanErrorKindResultExt for Result { fn with_empty_call_stack(self) -> Result { match self { Ok(value) => Ok(value), - Err(kind) => { - let task_call_stack = TaskCallStackDisplay::default(); - Err(Error { task_call_stack, kind }) - } + Err(kind) => Err(kind.with_empty_call_stack()), } } } diff --git a/crates/vite_task_plan/src/lib.rs b/crates/vite_task_plan/src/lib.rs index 9247b55f..15aef1c8 100644 --- a/crates/vite_task_plan/src/lib.rs +++ b/crates/vite_task_plan/src/lib.rs @@ -11,15 +11,17 @@ use std::{collections::HashMap, ffi::OsStr, fmt::Debug, ops::Range, sync::Arc}; use context::PlanContext; use envs::ResolvedEnvs; -use error::{Error, TaskPlanErrorKind, TaskPlanErrorKindResultExt}; +use error::TaskPlanErrorKindResultExt; +pub use error::{Error, TaskPlanErrorKind}; use execution_graph::ExecutionGraph; -use futures_core::future::BoxFuture; use in_process::InProcessExecution; use plan::{plan_query_request, plan_synthetic_request}; use plan_request::PlanRequest; use vite_path::AbsolutePath; use vite_str::Str; -use vite_task_graph::{TaskGraphLoadError, TaskNodeIndex, query::TaskQuery}; +use vite_task_graph::{TaskGraphLoadError, display::TaskDisplay, query::TaskQuery}; + +use crate::path_env::prepend_path_env; /// Resolved cache configuration for a spawn execution. #[derive(Debug)] @@ -58,8 +60,8 @@ pub enum SpawnCommandKind { /// Represents how a task should be executed. It's the node type for the execution graph. Each node corresponds to a task. #[derive(Debug)] pub struct TaskExecution { - /// The task index in the task graph - pub task_node_index: TaskNodeIndex, + /// The task this execution corresponds to + pub task_display: TaskDisplay, /// A task's command is split by `&&` and expanded into multiple execution items. /// @@ -98,14 +100,10 @@ pub enum ExecutionItemKind { Leaf(LeafExecutionKind), } -/// Callbackes needed during planning. -/// See each method for details. -pub trait PlanCallbacks: Debug { - fn load_task_graph( - &mut self, - cwd: &AbsolutePath, - ) -> BoxFuture<'_, Result, TaskGraphLoadError>>; - +/// The callback trait for parsing plan requests from cli args. +/// See the method for details. +#[async_trait::async_trait(?Send)] +pub trait PlanRequestParser: Debug { /// This is called for every parsable command in the task graph in order to determine how to execute it. /// /// `vite_task_plan` doesn't have the knowledge of how cli args should be parsed. It relies on this callback. @@ -114,11 +112,19 @@ pub trait PlanCallbacks: Debug { /// - If it returns `Ok(None)`, the command will be spawned as a normal process. /// - If it returns `Ok(Some(ParsedArgs::TaskQuery)`, the command will be expanded as a `ExpandedExecution` with a task graph queried from the returned `TaskQuery`. /// - If it returns `Ok(Some(ParsedArgs::Synthetic)`, the command will become a `SpawnExecution` with the synthetic task. - fn get_plan_request( - &self, + async fn get_plan_request( + &mut self, program: &str, args: &[Str], - ) -> BoxFuture<'_, anyhow::Result>>; + cwd: &Arc, + ) -> anyhow::Result>; +} + +#[async_trait::async_trait(?Send)] +pub trait TaskGraphLoader { + async fn load_task_graph( + &mut self, + ) -> Result<&vite_task_graph::IndexedTaskGraph, TaskGraphLoadError>; } #[derive(Debug)] @@ -137,32 +143,39 @@ impl ExecutionPlan { pub async fn plan( plan_request: PlanRequest, + workspace_path: &AbsolutePath, cwd: &Arc, envs: &HashMap, Arc>, - callbacks: &mut (dyn PlanCallbacks + '_), + plan_request_parser: &mut (dyn PlanRequestParser + '_), + task_graph_loader: &mut (dyn TaskGraphLoader + '_), ) -> Result { + let workspace_node_modules_bin = workspace_path.join("node_modules").join(".bin"); + let mut envs = envs.clone(); + prepend_path_env(&mut envs, &workspace_node_modules_bin) + .map_err(|join_paths_error| TaskPlanErrorKind::AddNodeModulesBinPathError { + join_paths_error, + }) + .with_empty_call_stack()?; let root_node = match plan_request { PlanRequest::Query(query_plan_request) => { - let indexed_task_graph = callbacks - .load_task_graph(cwd) + let indexed_task_graph = task_graph_loader + .load_task_graph() .await .map_err(|load_error| TaskPlanErrorKind::TaskGraphLoadError(load_error)) .with_empty_call_stack()?; - let context = PlanContext { - cwd: Arc::clone(cwd), - envs: envs.clone(), - callbacks, - task_call_stack: Vec::new(), - indexed_task_graph: &indexed_task_graph, - }; - + let context = PlanContext::new( + Arc::clone(cwd), + envs.clone(), + plan_request_parser, + &indexed_task_graph, + ); let execution_graph = plan_query_request(query_plan_request, context).await?; ExecutionItemKind::Expanded(execution_graph) } PlanRequest::Synthetic(synthetic_plan_request) => { let execution = - plan_synthetic_request(&Default::default(), synthetic_plan_request, cwd, envs) + plan_synthetic_request(&Default::default(), synthetic_plan_request, cwd, &envs) .with_empty_call_stack()?; ExecutionItemKind::Leaf(LeafExecutionKind::Spawn(execution)) diff --git a/crates/vite_task_plan/src/plan.rs b/crates/vite_task_plan/src/plan.rs index 5c6bf44f..4f83a709 100644 --- a/crates/vite_task_plan/src/plan.rs +++ b/crates/vite_task_plan/src/plan.rs @@ -30,27 +30,25 @@ async fn plan_task_as_execution_node( .map_err(TaskPlanErrorKind::TaskRecursionDetected) .with_plan_context(&context)?; + let task_node = &context.indexed_task_graph().task_graph()[task_node_index]; + let command_str = task_node.resolved_config.command.as_str(); + // Prepend {package_path}/node_modules/.bin to PATH let package_node_modules_bin_path = context .indexed_task_graph() .get_package_path_for_task(task_node_index) .join("node_modules") .join(".bin"); - context - .prepend_path(&package_node_modules_bin_path) - .map_err(|join_paths_error| TaskPlanErrorKind::AddNodeModulesBinPathError { - task_display: context.indexed_task_graph().display_task(task_node_index), - join_paths_error, - }) - .with_plan_context(&context)?; - - let task_node = &context.indexed_task_graph().task_graph()[task_node_index]; - - // TODO: variable expansion (https://crates.io/crates/shellexpand) BEFORE parsing - let command_str = task_node.resolved_config.command.as_str(); + if let Err(join_paths_error) = context.prepend_path(&package_node_modules_bin_path) { + // Push the current task frame with full command span (the path was added for every and_item of the command) before returning the error + context.push_stack_frame(task_node_index, 0..command_str.len()); + return Err(TaskPlanErrorKind::AddNodeModulesBinPathError { join_paths_error }) + .with_plan_context(&context); + } let mut items = Vec::::new(); + // TODO: variable expansion (https://crates.io/crates/shellexpand) BEFORE parsing // Try to parse the command string as a list of subcommands separated by `&&` if let Some(parsed_subcommands) = try_parse_as_and_list(command_str) { for (and_item, add_item_span) in parsed_subcommands { @@ -70,9 +68,10 @@ async fn plan_task_as_execution_node( } // Try to parse the args of an and_item to a task request like `run -r build` + let cwd = Arc::clone(context.cwd()); let task_request = context .callbacks() - .get_plan_request(&and_item.program, &and_item.args) + .get_plan_request(&and_item.program, &and_item.args, &cwd) .await .map_err(|error| TaskPlanErrorKind::ParsePlanRequestError { error }) .with_plan_context(&context)?; @@ -127,7 +126,10 @@ async fn plan_task_as_execution_node( }); } - Ok(TaskExecution { task_node_index, items }) + Ok(TaskExecution { + task_display: context.indexed_task_graph().display_task(task_node_index), + items, + }) } pub fn plan_synthetic_request(