Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/cli/src/bin/code/legacy_args.rs
3320 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
use std::collections::HashMap;
7
8
use cli::commands::args::{
9
CliCore, Commands, DesktopCodeOptions, ExtensionArgs, ExtensionSubcommand,
10
InstallExtensionArgs, ListExtensionArgs, UninstallExtensionArgs,
11
};
12
13
/// Tries to parse the argv using the legacy CLI interface, looking for its
14
/// flags and generating a CLI with subcommands if those don't exist.
15
pub fn try_parse_legacy(
16
iter: impl IntoIterator<Item = impl Into<std::ffi::OsString>>,
17
) -> Option<CliCore> {
18
let raw = clap_lex::RawArgs::new(iter);
19
let mut cursor = raw.cursor();
20
raw.next(&mut cursor); // Skip the bin
21
22
// First make a hashmap of all flags and capture positional arguments.
23
let mut args: HashMap<String, Vec<String>> = HashMap::new();
24
let mut last_arg = None;
25
while let Some(arg) = raw.next(&mut cursor) {
26
if let Some((long, value)) = arg.to_long() {
27
if let Ok(long) = long {
28
last_arg = Some(long.to_string());
29
match args.get_mut(long) {
30
Some(prev) => {
31
if let Some(v) = value {
32
prev.push(v.to_string_lossy().to_string());
33
}
34
}
35
None => {
36
if let Some(v) = value {
37
args.insert(long.to_string(), vec![v.to_string_lossy().to_string()]);
38
} else {
39
args.insert(long.to_string(), vec![]);
40
}
41
}
42
}
43
}
44
} else if let Ok(value) = arg.to_value() {
45
if value == "tunnel" {
46
return None;
47
}
48
if let Some(last_arg) = &last_arg {
49
args.get_mut(last_arg)
50
.expect("expected to have last arg")
51
.push(value.to_string());
52
}
53
}
54
}
55
56
let get_first_arg_value =
57
|key: &str| args.get(key).and_then(|v| v.first()).map(|s| s.to_string());
58
let desktop_code_options = DesktopCodeOptions {
59
extensions_dir: get_first_arg_value("extensions-dir"),
60
user_data_dir: get_first_arg_value("user-data-dir"),
61
use_version: None,
62
};
63
64
// Now translate them to subcommands.
65
// --list-extensions -> ext list
66
// --update-extensions -> update
67
// --install-extension=id -> ext install <id>
68
// --uninstall-extension=id -> ext uninstall <id>
69
// --status -> status
70
71
if args.contains_key("list-extensions") {
72
Some(CliCore {
73
subcommand: Some(Commands::Extension(ExtensionArgs {
74
subcommand: ExtensionSubcommand::List(ListExtensionArgs {
75
category: get_first_arg_value("category"),
76
show_versions: args.contains_key("show-versions"),
77
}),
78
desktop_code_options,
79
})),
80
..Default::default()
81
})
82
} else if let Some(exts) = args.remove("install-extension") {
83
Some(CliCore {
84
subcommand: Some(Commands::Extension(ExtensionArgs {
85
subcommand: ExtensionSubcommand::Install(InstallExtensionArgs {
86
id_or_path: exts,
87
pre_release: args.contains_key("pre-release"),
88
donot_include_pack_and_dependencies: args
89
.contains_key("do-not-include-pack-dependencies"),
90
force: args.contains_key("force"),
91
}),
92
desktop_code_options,
93
})),
94
..Default::default()
95
})
96
} else if let Some(_exts) = args.remove("update-extensions") {
97
Some(CliCore {
98
subcommand: Some(Commands::Extension(ExtensionArgs {
99
subcommand: ExtensionSubcommand::Update,
100
desktop_code_options,
101
})),
102
..Default::default()
103
})
104
} else if let Some(exts) = args.remove("uninstall-extension") {
105
Some(CliCore {
106
subcommand: Some(Commands::Extension(ExtensionArgs {
107
subcommand: ExtensionSubcommand::Uninstall(UninstallExtensionArgs { id: exts }),
108
desktop_code_options,
109
})),
110
..Default::default()
111
})
112
} else if args.contains_key("status") {
113
Some(CliCore {
114
subcommand: Some(Commands::Status),
115
..Default::default()
116
})
117
} else {
118
None
119
}
120
}
121
122
#[cfg(test)]
123
mod tests {
124
use super::*;
125
126
#[test]
127
fn test_parses_list_extensions() {
128
let args = vec![
129
"code",
130
"--list-extensions",
131
"--category",
132
"themes",
133
"--show-versions",
134
];
135
let cli = try_parse_legacy(args).unwrap();
136
137
if let Some(Commands::Extension(extension_args)) = cli.subcommand {
138
if let ExtensionSubcommand::List(list_args) = extension_args.subcommand {
139
assert_eq!(list_args.category, Some("themes".to_string()));
140
assert!(list_args.show_versions);
141
} else {
142
panic!(
143
"Expected list subcommand, got {:?}",
144
extension_args.subcommand
145
);
146
}
147
} else {
148
panic!("Expected extension subcommand, got {:?}", cli.subcommand);
149
}
150
}
151
152
#[test]
153
fn test_parses_install_extension() {
154
let args = vec![
155
"code",
156
"--install-extension",
157
"connor4312.codesong",
158
"connor4312.hello-world",
159
"--pre-release",
160
"--force",
161
];
162
let cli = try_parse_legacy(args).unwrap();
163
164
if let Some(Commands::Extension(extension_args)) = cli.subcommand {
165
if let ExtensionSubcommand::Install(install_args) = extension_args.subcommand {
166
assert_eq!(
167
install_args.id_or_path,
168
vec!["connor4312.codesong", "connor4312.hello-world"]
169
);
170
assert!(install_args.pre_release);
171
assert!(install_args.force);
172
} else {
173
panic!(
174
"Expected install subcommand, got {:?}",
175
extension_args.subcommand
176
);
177
}
178
} else {
179
panic!("Expected extension subcommand, got {:?}", cli.subcommand);
180
}
181
}
182
183
#[test]
184
fn test_parses_uninstall_extension() {
185
let args = vec!["code", "--uninstall-extension", "connor4312.codesong"];
186
let cli = try_parse_legacy(args).unwrap();
187
188
if let Some(Commands::Extension(extension_args)) = cli.subcommand {
189
if let ExtensionSubcommand::Uninstall(uninstall_args) = extension_args.subcommand {
190
assert_eq!(uninstall_args.id, vec!["connor4312.codesong"]);
191
} else {
192
panic!(
193
"Expected uninstall subcommand, got {:?}",
194
extension_args.subcommand
195
);
196
}
197
} else {
198
panic!("Expected extension subcommand, got {:?}", cli.subcommand);
199
}
200
}
201
202
#[test]
203
fn test_parses_user_data_dir_and_extensions_dir() {
204
let args = vec![
205
"code",
206
"--uninstall-extension",
207
"connor4312.codesong",
208
"--user-data-dir",
209
"foo",
210
"--extensions-dir",
211
"bar",
212
];
213
let cli = try_parse_legacy(args).unwrap();
214
215
if let Some(Commands::Extension(extension_args)) = cli.subcommand {
216
assert_eq!(
217
extension_args.desktop_code_options.user_data_dir,
218
Some("foo".to_string())
219
);
220
assert_eq!(
221
extension_args.desktop_code_options.extensions_dir,
222
Some("bar".to_string())
223
);
224
if let ExtensionSubcommand::Uninstall(uninstall_args) = extension_args.subcommand {
225
assert_eq!(uninstall_args.id, vec!["connor4312.codesong"]);
226
} else {
227
panic!(
228
"Expected uninstall subcommand, got {:?}",
229
extension_args.subcommand
230
);
231
}
232
} else {
233
panic!("Expected extension subcommand, got {:?}", cli.subcommand);
234
}
235
}
236
237
#[test]
238
fn test_status() {
239
let args = vec!["code", "--status"];
240
let cli = try_parse_legacy(args).unwrap();
241
242
if let Some(Commands::Status) = cli.subcommand {
243
// no-op
244
} else {
245
panic!("Expected extension subcommand, got {:?}", cli.subcommand);
246
}
247
}
248
}
249
250