-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathmod.rs
More file actions
166 lines (148 loc) · 6.67 KB
/
mod.rs
File metadata and controls
166 lines (148 loc) · 6.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use std::{ffi::OsStr, sync::Arc};
use clap::{Parser, 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};
/// Represents the CLI arguments handled by vite-task, including both built-in (like run) and custom subcommands (like lint).
#[derive(Debug)]
pub struct TaskCLIArgs<CustomSubcommand: Subcommand> {
pub(crate) original: Arc<[Str]>,
pub(crate) parsed: ParsedTaskCLIArgs<CustomSubcommand>,
}
impl<CustomSubcommand: Subcommand> TaskCLIArgs<CustomSubcommand> {
/// Inspect the custom subcommand (like lint/install). Returns `None` if it's built-in subcommand
/// The caller should not use this method to actually handle the custom subcommand. Instead, it should
/// private TaskSynthesizer to Session so that vite-task can handle custom subcommands consistently from
/// both direct CLI invocations and invocations in task scripts.
///
/// This method is provided only to make it possible for the caller to behave differently BEFORE and AFTER the session.
/// For example, vite+ needs this method to skip auto-install when the custom subcommand is already `install`.
pub fn custom_subcommand(&self) -> Option<&CustomSubcommand> {
match &self.parsed {
ParsedTaskCLIArgs::BuiltIn(_) => None,
ParsedTaskCLIArgs::Custom(custom) => Some(custom),
}
}
}
/// Represents the overall CLI arguments, containing three kinds of subcommands:
/// 1. Built-in subcommands handled by vite-task (like run)
/// 2. Custom subcommands handled by vite-task with the help of TaskSyntheizer (like lint)
/// 3. Custom subcommands not handled by vite-task (like vite+ commands without cache)
pub enum CLIArgs<CustomSubcommand: Subcommand, NonTaskSubcommand: Subcommand> {
/// Subcommands handled by vite task, including built-in (like run) and custom (like lint)
Task(TaskCLIArgs<CustomSubcommand>),
/// Custom subcommands not handled by vite task (like vite+ commands without cache)
NonTask(NonTaskSubcommand),
}
impl<CustomSubcommand: Subcommand, NonTaskSubcommand: Subcommand>
CLIArgs<CustomSubcommand, NonTaskSubcommand>
{
/// Get the original CLI arguments
pub fn try_parse_from(
args: impl Iterator<Item = impl AsRef<str>>,
) -> Result<Self, clap::Error> {
#[derive(Debug, clap::Parser)]
enum ParsedCLIArgs<CustomSubcommand: Subcommand, NonTaskSubcommand: Subcommand> {
/// subcommands handled by vite task
#[command(flatten)]
Task(ParsedTaskCLIArgs<CustomSubcommand>),
/// subcommands that are not handled by vite task
#[command(flatten)]
NonTask(NonTaskSubcommand),
}
let args = args.map(|arg| Str::from(arg.as_ref())).collect::<Arc<[Str]>>();
let parsed_cli_args = ParsedCLIArgs::<CustomSubcommand, NonTaskSubcommand>::try_parse_from(
args.iter().map(|s| OsStr::new(s.as_str())),
)?;
Ok(match parsed_cli_args {
ParsedCLIArgs::Task(parsed_task_cli_args) => {
Self::Task(TaskCLIArgs { original: args, parsed: parsed_task_cli_args })
}
ParsedCLIArgs::NonTask(non_task_subcommand) => Self::NonTask(non_task_subcommand),
})
}
}
#[derive(Debug, Parser)]
pub(crate) enum ParsedTaskCLIArgs<CustomSubcommand: Subcommand> {
/// subcommands provided by vite task, like `run`
#[clap(flatten)]
BuiltIn(BuiltInCommand),
/// custom subcommands provided by vite+, like `lint`
#[clap(flatten)]
Custom(CustomSubcommand),
}
/// vite task CLI subcommands
#[derive(Debug, Subcommand)]
pub(crate) enum BuiltInCommand {
/// 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, allow_hyphen_values = true)]
additional_args: Vec<Str>,
},
}
#[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 BuiltInCommand {
/// Convert to `TaskQuery`, or return an error if invalid.
pub fn into_plan_request(
self,
cwd: &Arc<AbsolutePath>,
) -> Result<PlanRequest, CLITaskQueryError> {
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() },
}))
}
}
}
}