1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -05:00

feat(cli/installer): Add missing flags for deno install (#7601)

This commit adds support for following flags:
- deno install --importmap
- deno install --no-remote
- deno install --lock
- deno install --lock-write
- deno install --cached-only
- deno install --v8-flags
- deno install --seed
This commit is contained in:
Nayeem Rahman 2020-10-19 20:19:20 +01:00 committed by GitHub
parent 9d664f8375
commit 3f5513758d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 110 additions and 167 deletions

View file

@ -110,7 +110,7 @@ pub struct Flags {
pub import_map_path: Option<String>,
pub inspect: Option<SocketAddr>,
pub inspect_brk: Option<SocketAddr>,
pub lock: Option<String>,
pub lock: Option<PathBuf>,
pub lock_write: bool,
pub log_level: Option<Level>,
pub net_allowlist: Vec<String>,
@ -372,11 +372,7 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
}
fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
permission_args_parse(flags, matches);
config_arg_parse(flags, matches);
reload_arg_parse(flags, matches);
ca_file_arg_parse(flags, matches);
no_check_arg_parse(flags, matches);
runtime_args_parse(flags, matches, true);
let root = if matches.is_present("root") {
let install_root = matches.value_of("root").unwrap();
@ -501,7 +497,7 @@ fn cache_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
fn lock_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
if matches.is_present("lock") {
let lockfile = matches.value_of("lock").unwrap();
flags.lock = Some(lockfile.to_string());
flags.lock = Some(PathBuf::from(lockfile));
}
if matches.is_present("lock-write") {
flags.lock_write = true;
@ -725,7 +721,7 @@ fn repl_subcommand<'a, 'b>() -> App<'a, 'b> {
}
fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
permission_args(SubCommand::with_name("install"))
runtime_args(SubCommand::with_name("install"), true)
.setting(AppSettings::TrailingVarArg)
.arg(
Arg::with_name("cmd")
@ -751,10 +747,6 @@ fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
.short("f")
.help("Forcefully overwrite existing installation")
.takes_value(false))
.arg(no_check_arg())
.arg(reload_arg())
.arg(ca_file_arg())
.arg(config_arg())
.about("Install script as an executable")
.long_about(
"Installs a script as an executable in the installation root's bin directory.
@ -1348,6 +1340,7 @@ fn importmap_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name("importmap")
.long("importmap")
.value_name("FILE")
.requires("unstable")
.help("UNSTABLE: Load import map file")
.long_help(
"UNSTABLE:
@ -2120,7 +2113,7 @@ mod tests {
config_path: Some("tsconfig.json".to_string()),
no_check: true,
reload: true,
lock: Some("lock.json".to_string()),
lock: Some(PathBuf::from("lock.json")),
lock_write: true,
ca_file: Some("example.crt".to_string()),
cached_only: true,
@ -2174,7 +2167,7 @@ mod tests {
config_path: Some("tsconfig.json".to_string()),
no_check: true,
reload: true,
lock: Some("lock.json".to_string()),
lock: Some(PathBuf::from("lock.json")),
lock_write: true,
ca_file: Some("example.crt".to_string()),
cached_only: true,
@ -2337,7 +2330,7 @@ mod tests {
out_file: None,
},
lock_write: true,
lock: Some("lock.json".to_string()),
lock: Some(PathBuf::from("lock.json")),
..Flags::default()
}
);
@ -2365,6 +2358,7 @@ mod tests {
let r = flags_from_vec_safe(svec![
"deno",
"run",
"--unstable",
"--importmap=importmap.json",
"script.ts"
]);
@ -2374,6 +2368,7 @@ mod tests {
subcommand: DenoSubcommand::Run {
script: "script.ts".to_string(),
},
unstable: true,
import_map_path: Some("importmap.json".to_owned()),
..Flags::default()
}
@ -2385,6 +2380,7 @@ mod tests {
let r = flags_from_vec_safe(svec![
"deno",
"info",
"--unstable",
"--importmap=importmap.json",
"script.ts"
]);
@ -2395,6 +2391,7 @@ mod tests {
file: Some("script.ts".to_string()),
json: false,
},
unstable: true,
import_map_path: Some("importmap.json".to_owned()),
..Flags::default()
}
@ -2406,6 +2403,7 @@ mod tests {
let r = flags_from_vec_safe(svec![
"deno",
"cache",
"--unstable",
"--importmap=importmap.json",
"script.ts"
]);
@ -2415,6 +2413,7 @@ mod tests {
subcommand: DenoSubcommand::Cache {
files: svec!["script.ts"],
},
unstable: true,
import_map_path: Some("importmap.json".to_owned()),
..Flags::default()
}
@ -2426,6 +2425,7 @@ mod tests {
let r = flags_from_vec_safe(svec![
"deno",
"doc",
"--unstable",
"--importmap=importmap.json",
"script.ts"
]);
@ -2438,6 +2438,7 @@ mod tests {
json: false,
filter: None,
},
unstable: true,
import_map_path: Some("importmap.json".to_owned()),
..Flags::default()
}
@ -2522,87 +2523,32 @@ mod tests {
}
#[test]
fn install_with_args() {
let r = flags_from_vec_safe(svec![
"deno",
"install",
"--reload",
"--allow-net",
"--allow-read",
"-n",
"file_server",
"https://deno.land/std/http/file_server.ts"
]);
fn install_with_flags() {
#[rustfmt::skip]
let r = flags_from_vec_safe(svec!["deno", "install", "--unstable", "--importmap", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--inspect=127.0.0.1:9229", "--name", "file_server", "--root", "/foo", "--force", "https://deno.land/std/http/file_server.ts", "foo", "bar"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
name: Some("file_server".to_string()),
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
args: vec![],
root: None,
force: false,
},
reload: true,
allow_net: true,
allow_read: true,
..Flags::default()
}
);
}
#[test]
fn install_with_config() {
let r = flags_from_vec_safe(svec![
"deno",
"install",
"--config",
"tsconfig.json",
"https://deno.land/std/examples/colors.ts"
]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
name: None,
module_url: "https://deno.land/std/examples/colors.ts".to_string(),
args: svec![],
root: None,
force: false,
},
config_path: Some("tsconfig.json".to_owned()),
..Flags::default()
}
)
}
#[test]
fn install_with_args_and_dir_and_force() {
let r = flags_from_vec_safe(svec![
"deno",
"install",
"--root",
"/usr/local",
"-f",
"--allow-net",
"--allow-read",
"-n",
"file_server",
"https://deno.land/std/http/file_server.ts",
"arg1",
"arg2"
]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
name: Some("file_server".to_string()),
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
args: svec!["arg1", "arg2"],
root: Some(PathBuf::from("/usr/local")),
args: svec!["foo", "bar"],
root: Some(PathBuf::from("/foo")),
force: true,
},
unstable: true,
import_map_path: Some("import_map.json".to_string()),
no_remote: true,
config_path: Some("tsconfig.json".to_string()),
no_check: true,
reload: true,
lock: Some(PathBuf::from("lock.json")),
lock_write: true,
ca_file: Some("example.crt".to_string()),
cached_only: true,
v8_flags: Some(svec!["--help", "--random-seed=1"]),
seed: Some(1),
inspect: Some("127.0.0.1:9229".parse().unwrap()),
allow_net: true,
allow_read: true,
..Flags::default()
@ -2858,7 +2804,7 @@ mod tests {
script: "script.ts".to_string(),
},
lock_write: true,
lock: Some("lock.json".to_string()),
lock: Some(PathBuf::from("lock.json")),
..Flags::default()
}
);
@ -3060,33 +3006,6 @@ mod tests {
);
}
#[test]
fn install_with_cafile() {
let r = flags_from_vec_safe(svec![
"deno",
"install",
"--cert",
"example.crt",
"-n",
"deno_colors",
"https://deno.land/std/examples/colors.ts"
]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
name: Some("deno_colors".to_string()),
module_url: "https://deno.land/std/examples/colors.ts".to_string(),
args: vec![],
root: None,
force: false,
},
ca_file: Some("example.crt".to_owned()),
..Flags::default()
}
);
}
#[test]
fn doc() {
let r =

View file

@ -81,17 +81,6 @@ deno {} "$@"
Ok(())
}
fn generate_config_file(
file_path: PathBuf,
config_file_name: String,
) -> Result<(), io::Error> {
let config_file_copy_path = get_config_file_path(&file_path);
let cwd = std::env::current_dir().unwrap();
let config_file_path = cwd.join(config_file_name);
fs::copy(config_file_path, config_file_copy_path)?;
Ok(())
}
fn get_installer_root() -> Result<PathBuf, io::Error> {
if let Ok(env_dir) = env::var("DENO_INSTALL_ROOT") {
if !env_dir.is_empty() {
@ -189,6 +178,8 @@ pub fn install(
));
};
let mut extra_files: Vec<(PathBuf, String)> = vec![];
let mut executable_args = vec!["run".to_string()];
executable_args.extend_from_slice(&flags.to_permission_args());
if let Some(ca_file) = flags.ca_file {
@ -219,21 +210,65 @@ pub fn install(
executable_args.push("--unstable".to_string());
}
if flags.config_path.is_some() {
let config_file_path = get_config_file_path(&file_path);
let config_file_path_option = config_file_path.to_str();
if let Some(config_file_path_string) = config_file_path_option {
executable_args.push("--config".to_string());
executable_args.push(config_file_path_string.to_string());
if flags.no_remote {
executable_args.push("--no-remote".to_string());
}
if flags.lock_write {
executable_args.push("--lock-write".to_string());
}
if flags.cached_only {
executable_args.push("--cached_only".to_string());
}
if let Some(v8_flags) = flags.v8_flags {
executable_args.push(format!("--v8-flags={}", v8_flags.join(",")));
}
if let Some(seed) = flags.seed {
executable_args.push("--seed".to_string());
executable_args.push(seed.to_string());
}
if let Some(inspect) = flags.inspect {
executable_args.push(format!("--inspect={}", inspect.to_string()));
}
if let Some(inspect_brk) = flags.inspect_brk {
executable_args.push(format!("--inspect-brk={}", inspect_brk.to_string()));
}
if let Some(import_map_path) = flags.import_map_path {
let mut copy_path = file_path.clone();
copy_path.set_extension("import_map.json");
executable_args.push("--importmap".to_string());
executable_args.push(copy_path.to_str().unwrap().to_string());
extra_files.push((copy_path, fs::read_to_string(import_map_path)?));
}
if let Some(config_path) = flags.config_path {
let mut copy_path = file_path.clone();
copy_path.set_extension("tsconfig.json");
executable_args.push("--config".to_string());
executable_args.push(copy_path.to_str().unwrap().to_string());
extra_files.push((copy_path, fs::read_to_string(config_path)?));
}
if let Some(lock_path) = flags.lock {
let mut copy_path = file_path.clone();
copy_path.set_extension("lock.json");
executable_args.push("--lock".to_string());
executable_args.push(copy_path.to_str().unwrap().to_string());
extra_files.push((copy_path, fs::read_to_string(lock_path)?));
}
executable_args.push(module_url.to_string());
executable_args.extend_from_slice(&args);
generate_executable_file(file_path.to_owned(), executable_args)?;
if let Some(config_path) = flags.config_path {
generate_config_file(file_path.to_owned(), config_path)?;
for (path, contents) in extra_files {
fs::write(path, contents)?;
}
println!("✅ Successfully installed {}", name);
@ -263,12 +298,6 @@ fn is_in_path(dir: &PathBuf) -> bool {
false
}
fn get_config_file_path(file_path: &PathBuf) -> PathBuf {
let mut config_file_copy_path = PathBuf::from(file_path);
config_file_copy_path.set_extension("tsconfig.json");
config_file_copy_path
}
#[cfg(test)]
mod tests {
use super::*;
@ -588,6 +617,7 @@ mod tests {
assert!(file_path.exists());
let content = fs::read_to_string(file_path).unwrap();
dbg!(&content);
assert!(content.contains(r#""run" "--allow-read" "--allow-net" "--quiet" "--no-check" "http://localhost:4545/cli/tests/echo_server.ts" "--foobar""#));
}

View file

@ -4,18 +4,17 @@ use deno_core::serde_json;
use deno_core::serde_json::json;
use std::collections::BTreeMap;
use std::io::Result;
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct Lockfile {
write: bool,
map: BTreeMap<String, String>,
pub filename: String,
pub filename: PathBuf,
}
impl Lockfile {
pub fn new(filename: String, write: bool) -> Result<Lockfile> {
debug!("lockfile \"{}\", write: {}", filename, write);
pub fn new(filename: PathBuf, write: bool) -> Result<Lockfile> {
let map = if write {
BTreeMap::new()
} else {
@ -46,7 +45,7 @@ impl Lockfile {
.open(&self.filename)?;
use std::io::Write;
f.write_all(s.as_bytes())?;
debug!("lockfile write {}", self.filename);
debug!("lockfile write {}", self.filename.display());
Ok(())
}
@ -93,7 +92,7 @@ mod tests {
use std::io::Write;
use tempfile::TempDir;
fn setup() -> (TempDir, String) {
fn setup() -> (TempDir, PathBuf) {
let temp_dir = TempDir::new().expect("could not create temp dir");
let file_path = temp_dir.path().join("valid_lockfile.json");
@ -106,8 +105,7 @@ mod tests {
file.write_all(value.to_string().as_bytes()).unwrap();
let file_path_buf = temp_dir.path().join("valid_lockfile.json");
let file_path = file_path_buf.to_str().expect("file path fail").to_string();
let file_path = temp_dir.path().join("valid_lockfile.json");
(temp_dir, file_path)
}
@ -118,7 +116,7 @@ mod tests {
#[test]
fn new_nonexistent_lockfile() {
let file_path = String::from("nonexistent_lock_file.json");
let file_path = PathBuf::from("nonexistent_lock_file.json");
assert!(Lockfile::new(file_path, false).is_err());
}

View file

@ -203,7 +203,10 @@ async fn install_command(
root: Option<PathBuf>,
force: bool,
) -> Result<(), AnyError> {
let program_state = ProgramState::new(flags.clone())?;
let mut preload_flags = flags.clone();
preload_flags.inspect = None;
preload_flags.inspect_brk = None;
let program_state = ProgramState::new(preload_flags)?;
let main_module = ModuleSpecifier::resolve_url_or_path(&module_url)?;
let mut worker = MainWorker::new(&program_state, main_module.clone());
// First, fetch and compile the module; this step ensures that the module exists.

View file

@ -615,7 +615,8 @@ impl Graph2 {
let valid = lockfile.check_or_insert(&specifier, &module.source);
if !valid {
return Err(
InvalidSource(ms.clone(), lockfile.filename.clone()).into(),
InvalidSource(ms.clone(), lockfile.filename.display().to_string())
.into(),
);
}
}
@ -1243,8 +1244,7 @@ pub mod tests {
let fixtures = c.join("tests/module_graph");
let lockfile_path = fixtures.join("lockfile.json");
let lockfile =
Lockfile::new(lockfile_path.to_string_lossy().to_string(), false)
.expect("could not load lockfile");
Lockfile::new(lockfile_path, false).expect("could not load lockfile");
let maybe_lockfile = Some(Mutex::new(lockfile));
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
fixtures,
@ -1269,8 +1269,7 @@ pub mod tests {
let fixtures = c.join("tests/module_graph");
let lockfile_path = fixtures.join("lockfile_fail.json");
let lockfile =
Lockfile::new(lockfile_path.to_string_lossy().to_string(), false)
.expect("could not load lockfile");
Lockfile::new(lockfile_path, false).expect("could not load lockfile");
let maybe_lockfile = Some(Mutex::new(lockfile));
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
fixtures,

View file

@ -175,7 +175,8 @@ impl ProgramState {
if !check_passed {
eprintln!(
"Subresource integrity check failed --lock={}\n{}",
g.filename, graph_file.url
g.filename.display(),
graph_file.url
);
std::process::exit(10);
}

View file

@ -1 +0,0 @@
Unstable API '--importmap'. The --unstable flag must be provided.

View file

@ -1812,13 +1812,6 @@ itest!(_033_import_map {
output: "033_import_map.out",
});
itest!(import_map_no_unstable {
args:
"run --quiet --reload --importmap=importmaps/import_map.json importmaps/test.ts",
output: "import_map_no_unstable.out",
exit_code: 70,
});
itest!(_034_onload {
args: "run --quiet --reload 034_onload/main.ts",
output: "034_onload.out",

View file

@ -586,7 +586,8 @@ impl TsCompiler {
if !check_passed {
eprintln!(
"Subresource integrity check failed --lock={}\n{}",
g.filename, graph_file.url
g.filename.display(),
graph_file.url
);
std::process::exit(10);
}