summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/args/config_file.rs58
-rw-r--r--cli/args/mod.rs164
-rw-r--r--cli/graph_util.rs6
-rw-r--r--cli/lsp/language_server.rs26
-rw-r--r--cli/proc_state.rs24
-rw-r--r--cli/tests/integration/run_tests.rs15
-rw-r--r--cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.js2
-rw-r--r--cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.out7
-rw-r--r--cli/tools/info.rs2
-rw-r--r--cli/tools/repl/session.rs2
-rw-r--r--cli/worker.rs4
-rw-r--r--test_util/src/lib.rs50
12 files changed, 219 insertions, 141 deletions
diff --git a/cli/args/config_file.rs b/cli/args/config_file.rs
index 0d84de2e4..154692376 100644
--- a/cli/args/config_file.rs
+++ b/cli/args/config_file.rs
@@ -18,6 +18,7 @@ use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::ModuleSpecifier;
+use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::HashSet;
@@ -483,10 +484,21 @@ pub struct ConfigFile {
}
impl ConfigFile {
- pub fn discover(flags: &Flags) -> Result<Option<ConfigFile>, AnyError> {
+ pub fn discover(
+ flags: &Flags,
+ cwd: &Path,
+ ) -> Result<Option<ConfigFile>, AnyError> {
match &flags.config_flag {
ConfigFlag::Disabled => Ok(None),
- ConfigFlag::Path(config_path) => Ok(Some(ConfigFile::read(config_path)?)),
+ ConfigFlag::Path(config_path) => {
+ let config_path = PathBuf::from(config_path);
+ let config_path = if config_path.is_absolute() {
+ config_path
+ } else {
+ cwd.join(config_path)
+ };
+ Ok(Some(ConfigFile::read(&config_path)?))
+ }
ConfigFlag::Discover => {
if let Some(config_path_args) = flags.config_path_args() {
let mut checked = HashSet::new();
@@ -508,8 +520,7 @@ impl ConfigFile {
}
};
// From CWD walk up to root looking for deno.json or deno.jsonc
- let cwd = std::env::current_dir()?;
- Self::discover_from(&cwd, &mut checked)
+ Self::discover_from(cwd, &mut checked)
} else {
Ok(None)
}
@@ -524,6 +535,14 @@ impl ConfigFile {
/// Filenames that Deno will recognize when discovering config.
const CONFIG_FILE_NAMES: [&str; 2] = ["deno.json", "deno.jsonc"];
+ // todo(dsherret): in the future, we should force all callers
+ // to provide a resolved path
+ let start = if start.is_absolute() {
+ Cow::Borrowed(start)
+ } else {
+ Cow::Owned(std::env::current_dir()?.join(start))
+ };
+
for ancestor in start.ancestors() {
if checked.insert(ancestor.to_path_buf()) {
for config_filename in CONFIG_FILE_NAMES {
@@ -556,34 +575,29 @@ impl ConfigFile {
Ok(None)
}
- pub fn read(path_ref: impl AsRef<Path>) -> Result<Self, AnyError> {
- let path = Path::new(path_ref.as_ref());
- let config_file = if path.is_absolute() {
- path.to_path_buf()
- } else {
- std::env::current_dir()?.join(path_ref)
- };
+ pub fn read(config_path: &Path) -> Result<Self, AnyError> {
+ debug_assert!(config_path.is_absolute());
// perf: Check if the config file exists before canonicalizing path.
- if !config_file.exists() {
+ if !config_path.exists() {
return Err(
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!(
"Could not find the config file: {}",
- config_file.to_string_lossy()
+ config_path.to_string_lossy()
),
)
.into(),
);
}
- let config_path = canonicalize_path(&config_file).map_err(|_| {
+ let config_path = canonicalize_path(config_path).map_err(|_| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!(
"Could not find the config file: {}",
- config_file.to_string_lossy()
+ config_path.to_string_lossy()
),
)
})?;
@@ -991,24 +1005,16 @@ mod tests {
use pretty_assertions::assert_eq;
#[test]
- fn read_config_file_relative() {
- let config_file =
- ConfigFile::read("tests/testdata/module_graph/tsconfig.json")
- .expect("Failed to load config file");
- assert!(config_file.json.compiler_options.is_some());
- }
-
- #[test]
fn read_config_file_absolute() {
let path = test_util::testdata_path().join("module_graph/tsconfig.json");
- let config_file = ConfigFile::read(path.to_str().unwrap())
- .expect("Failed to load config file");
+ let config_file = ConfigFile::read(&path).unwrap();
assert!(config_file.json.compiler_options.is_some());
}
#[test]
fn include_config_path_on_error() {
- let error = ConfigFile::read("404.json").err().unwrap();
+ let path = test_util::testdata_path().join("404.json");
+ let error = ConfigFile::read(&path).err().unwrap();
assert!(error.to_string().contains("404.json"));
}
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 7cb2213e9..3d8a29fe7 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -51,7 +51,6 @@ use deno_runtime::permissions::PermissionsOptions;
use once_cell::sync::Lazy;
use std::collections::BTreeMap;
use std::collections::HashMap;
-use std::collections::HashSet;
use std::env;
use std::io::BufReader;
use std::io::Cursor;
@@ -393,38 +392,35 @@ fn discover_package_json(
flags: &Flags,
maybe_stop_at: Option<PathBuf>,
) -> Result<Option<PackageJson>, AnyError> {
- pub fn discover_from(
+ fn discover_from(
start: &Path,
- checked: &mut HashSet<PathBuf>,
maybe_stop_at: Option<PathBuf>,
) -> Result<Option<PackageJson>, AnyError> {
const PACKAGE_JSON_NAME: &str = "package.json";
for ancestor in start.ancestors() {
- if checked.insert(ancestor.to_path_buf()) {
- let path = ancestor.join(PACKAGE_JSON_NAME);
-
- let source = match std::fs::read_to_string(&path) {
- Ok(source) => source,
- Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
- if let Some(stop_at) = maybe_stop_at.as_ref() {
- if ancestor == stop_at {
- break;
- }
+ let path = ancestor.join(PACKAGE_JSON_NAME);
+
+ let source = match std::fs::read_to_string(&path) {
+ Ok(source) => source,
+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
+ if let Some(stop_at) = maybe_stop_at.as_ref() {
+ if ancestor == stop_at {
+ break;
}
- continue;
}
- Err(err) => bail!(
- "Error loading package.json at {}. {:#}",
- path.display(),
- err
- ),
- };
+ continue;
+ }
+ Err(err) => bail!(
+ "Error loading package.json at {}. {:#}",
+ path.display(),
+ err
+ ),
+ };
- let package_json = PackageJson::load_from_string(path.clone(), source)?;
- log::debug!("package.json file found at '{}'", path.display());
- return Ok(Some(package_json));
- }
+ let package_json = PackageJson::load_from_string(path.clone(), source)?;
+ log::debug!("package.json file found at '{}'", path.display());
+ return Ok(Some(package_json));
}
// No config file found.
log::debug!("No package.json file found");
@@ -434,21 +430,17 @@ fn discover_package_json(
// TODO(bartlomieju): discover for all subcommands, but print warnings that
// `package.json` is ignored in bundle/compile/etc.
- if let Some(package_json_arg) = flags.package_json_arg() {
- return discover_from(
- &package_json_arg,
- &mut HashSet::new(),
- maybe_stop_at,
- );
- } else if let crate::args::DenoSubcommand::Task(TaskFlags {
- cwd: Some(path),
- ..
+ if let crate::args::DenoSubcommand::Task(TaskFlags {
+ cwd: Some(path), ..
}) = &flags.subcommand
{
// attempt to resolve the config file from the task subcommand's
// `--cwd` when specified
let task_cwd = canonicalize_path(&PathBuf::from(path))?;
- return discover_from(&task_cwd, &mut HashSet::new(), None);
+ return discover_from(&task_cwd, None);
+ } else if let Some(package_json_arg) = flags.package_json_arg() {
+ let package_json_arg = canonicalize_path(&package_json_arg)?;
+ return discover_from(&package_json_arg, maybe_stop_at);
}
log::debug!("No package.json file found");
@@ -542,9 +534,6 @@ pub fn get_root_cert_store(
const RESOLUTION_STATE_ENV_VAR_NAME: &str =
"DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE";
-static IS_NPM_MAIN: Lazy<bool> =
- Lazy::new(|| std::env::var(RESOLUTION_STATE_ENV_VAR_NAME).is_ok());
-
static NPM_PROCESS_STATE: Lazy<Option<NpmProcessState>> = Lazy::new(|| {
let state = std::env::var(RESOLUTION_STATE_ENV_VAR_NAME).ok()?;
let state: NpmProcessState = serde_json::from_str(&state).ok()?;
@@ -568,6 +557,7 @@ pub struct CliOptions {
// the source of the options is a detail the rest of the
// application need not concern itself with, so keep these private
flags: Flags,
+ maybe_node_modules_folder: Option<PathBuf>,
maybe_config_file: Option<ConfigFile>,
maybe_package_json: Option<PackageJson>,
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
@@ -577,10 +567,11 @@ pub struct CliOptions {
impl CliOptions {
pub fn new(
flags: Flags,
+ initial_cwd: PathBuf,
maybe_config_file: Option<ConfigFile>,
maybe_lockfile: Option<Lockfile>,
maybe_package_json: Option<PackageJson>,
- ) -> Self {
+ ) -> Result<Self, AnyError> {
if let Some(insecure_allowlist) =
flags.unsafely_ignore_certificate_errors.as_ref()
{
@@ -596,18 +587,28 @@ impl CliOptions {
}
let maybe_lockfile = maybe_lockfile.map(|l| Arc::new(Mutex::new(l)));
+ let maybe_node_modules_folder = resolve_local_node_modules_folder(
+ &initial_cwd,
+ &flags,
+ maybe_config_file.as_ref(),
+ maybe_package_json.as_ref(),
+ )
+ .with_context(|| "Resolving node_modules folder.")?;
- Self {
+ Ok(Self {
+ flags,
maybe_config_file,
maybe_lockfile,
maybe_package_json,
- flags,
+ maybe_node_modules_folder,
overrides: Default::default(),
- }
+ })
}
pub fn from_flags(flags: Flags) -> Result<Self, AnyError> {
- let maybe_config_file = ConfigFile::discover(&flags)?;
+ let initial_cwd =
+ std::env::current_dir().with_context(|| "Failed getting cwd.")?;
+ let maybe_config_file = ConfigFile::discover(&flags, &initial_cwd)?;
let mut maybe_package_json = None;
if let Some(config_file) = &maybe_config_file {
@@ -626,12 +627,13 @@ impl CliOptions {
}
let maybe_lock_file =
lockfile::discover(&flags, maybe_config_file.as_ref())?;
- Ok(Self::new(
+ Self::new(
flags,
+ initial_cwd,
maybe_config_file,
maybe_lock_file,
maybe_package_json,
- ))
+ )
}
pub fn maybe_config_file_specifier(&self) -> Option<ModuleSpecifier> {
@@ -705,16 +707,8 @@ impl CliOptions {
.map(Some)
}
- fn get_npm_process_state(&self) -> Option<&NpmProcessState> {
- if !self.is_npm_main() {
- return None;
- }
-
- (*NPM_PROCESS_STATE).as_ref()
- }
-
pub fn get_npm_resolution_snapshot(&self) -> Option<NpmResolutionSnapshot> {
- if let Some(state) = self.get_npm_process_state() {
+ if let Some(state) = &*NPM_PROCESS_STATE {
// TODO(bartlomieju): remove this clone
return Some(state.snapshot.clone());
}
@@ -727,7 +721,7 @@ impl CliOptions {
// for functionality like child_process.fork. Users should NOT depend
// on this functionality.
pub fn is_npm_main(&self) -> bool {
- *IS_NPM_MAIN
+ NPM_PROCESS_STATE.is_some()
}
/// Overrides the import map specifier to use.
@@ -735,36 +729,19 @@ impl CliOptions {
self.overrides.import_map_specifier = Some(path);
}
- pub fn node_modules_dir(&self) -> bool {
- if let Some(node_modules_dir) = self.flags.node_modules_dir {
- return node_modules_dir;
- }
-
- if let Some(npm_process_state) = self.get_npm_process_state() {
- return npm_process_state.local_node_modules_path.is_some();
- }
+ pub fn has_node_modules_dir(&self) -> bool {
+ self.maybe_node_modules_folder.is_some()
+ }
- self.maybe_package_json.is_some()
+ pub fn node_modules_dir_path(&self) -> Option<PathBuf> {
+ self.maybe_node_modules_folder.clone()
}
- /// Resolves the path to use for a local node_modules folder.
- pub fn resolve_local_node_modules_folder(
- &self,
- ) -> Result<Option<PathBuf>, AnyError> {
- let path = if !self.node_modules_dir() {
- return Ok(None);
- } else if let Some(state) = self.get_npm_process_state() {
- return Ok(state.local_node_modules_path.as_ref().map(PathBuf::from));
- } else if let Some(config_path) = self
- .maybe_config_file
+ pub fn node_modules_dir_specifier(&self) -> Option<ModuleSpecifier> {
+ self
+ .maybe_node_modules_folder
.as_ref()
- .and_then(|c| c.specifier.to_file_path().ok())
- {
- config_path.parent().unwrap().join("node_modules")
- } else {
- std::env::current_dir()?.join("node_modules")
- };
- Ok(Some(canonicalize_path_maybe_not_exists(&path)?))
+ .map(|path| ModuleSpecifier::from_directory_path(path).unwrap())
}
pub fn resolve_root_cert_store(&self) -> Result<RootCertStore, AnyError> {
@@ -1081,6 +1058,33 @@ impl CliOptions {
}
}
+/// Resolves the path to use for a local node_modules folder.
+fn resolve_local_node_modules_folder(
+ cwd: &Path,
+ flags: &Flags,
+ maybe_config_file: Option<&ConfigFile>,
+ maybe_package_json: Option<&PackageJson>,
+) -> Result<Option<PathBuf>, AnyError> {
+ let path = if flags.node_modules_dir == Some(false) {
+ return Ok(None);
+ } else if let Some(state) = &*NPM_PROCESS_STATE {
+ return Ok(state.local_node_modules_path.as_ref().map(PathBuf::from));
+ } else if let Some(package_json_path) = maybe_package_json.map(|c| &c.path) {
+ // always auto-discover the local_node_modules_folder when a package.json exists
+ package_json_path.parent().unwrap().join("node_modules")
+ } else if flags.node_modules_dir.is_none() {
+ return Ok(None);
+ } else if let Some(config_path) = maybe_config_file
+ .as_ref()
+ .and_then(|c| c.specifier.to_file_path().ok())
+ {
+ config_path.parent().unwrap().join("node_modules")
+ } else {
+ cwd.join("node_modules")
+ };
+ Ok(Some(canonicalize_path_maybe_not_exists(&path)?))
+}
+
fn resolve_import_map_specifier(
maybe_import_map_path: Option<&str>,
maybe_config_file: Option<&ConfigFile>,
diff --git a/cli/graph_util.rs b/cli/graph_util.rs
index b5726b943..148ab1cee 100644
--- a/cli/graph_util.rs
+++ b/cli/graph_util.rs
@@ -14,7 +14,6 @@ use crate::resolver::CliGraphResolver;
use crate::tools::check;
use deno_core::anyhow::bail;
-use deno_core::anyhow::Context;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::ModuleSpecifier;
@@ -153,10 +152,7 @@ pub async fn create_graph_and_maybe_check(
ps.file_fetcher.clone(),
PermissionsContainer::allow_all(),
PermissionsContainer::allow_all(),
- ps.options
- .resolve_local_node_modules_folder()
- .with_context(|| "Resolving local node_modules folder.")?
- .map(|path| ModuleSpecifier::from_file_path(path).unwrap()),
+ ps.options.node_modules_dir_specifier(),
);
let maybe_imports = ps.options.to_maybe_imports()?;
let maybe_package_json_deps = ps.options.maybe_package_json_deps()?;
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index d056afbc0..808a98a2c 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -2,6 +2,7 @@
use deno_ast::MediaType;
use deno_core::anyhow::anyhow;
+use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::resolve_url;
use deno_core::serde_json;
@@ -168,7 +169,7 @@ impl LanguageServer {
.map(|d| (d.specifier().clone(), d))
.collect::<HashMap<_, _>>();
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
- let mut inner_loader = ps.create_graph_loader()?;
+ let mut inner_loader = ps.create_graph_loader();
let mut loader = crate::lsp::documents::OpenDocumentsGraphLoader {
inner_loader: &mut inner_loader,
open_docs: &open_docs,
@@ -191,11 +192,23 @@ impl LanguageServer {
match params.map(serde_json::from_value) {
Some(Ok(params)) => {
// do as much as possible in a read, then do a write outside
- let result = {
+ let maybe_cache_result = {
let inner = self.0.read().await; // ensure dropped
- inner.prepare_cache(params)?
+ match inner.prepare_cache(params) {
+ Ok(maybe_cache_result) => maybe_cache_result,
+ Err(err) => {
+ self
+ .0
+ .read()
+ .await
+ .client
+ .show_message(MessageType::WARNING, err)
+ .await;
+ return Err(LspError::internal_error());
+ }
+ }
};
- if let Some(result) = result {
+ if let Some(result) = maybe_cache_result {
let cli_options = result.cli_options;
let roots = result.roots;
let open_docs = result.open_docs;
@@ -2993,7 +3006,7 @@ impl Inner {
fn prepare_cache(
&self,
params: lsp_custom::CacheParams,
- ) -> LspResult<Option<PrepareCacheResult>> {
+ ) -> Result<Option<PrepareCacheResult>, AnyError> {
let referrer = self.url_map.normalize_url(&params.referrer.uri);
if !self.is_diagnosable(&referrer) {
return Ok(None);
@@ -3021,12 +3034,13 @@ impl Inner {
unstable: true,
..Default::default()
},
+ std::env::current_dir().with_context(|| "Failed getting cwd.")?,
self.maybe_config_file.clone(),
// TODO(#16510): add support for lockfile
None,
// TODO(bartlomieju): handle package.json dependencies here
None,
- );
+ )?;
cli_options.set_import_map_specifier(self.maybe_import_map_uri.clone());
let open_docs = self.documents.documents(true, true);
diff --git a/cli/proc_state.rs b/cli/proc_state.rs
index 9f1e7320c..2070b14c6 100644
--- a/cli/proc_state.rs
+++ b/cli/proc_state.rs
@@ -224,9 +224,7 @@ impl ProcState {
let npm_resolver = NpmPackageResolver::new_with_maybe_lockfile(
npm_cache.clone(),
api,
- cli_options
- .resolve_local_node_modules_folder()
- .with_context(|| "Resolving local node_modules folder.")?,
+ cli_options.node_modules_dir_path(),
cli_options.get_npm_resolution_snapshot(),
lockfile.as_ref().cloned(),
)
@@ -329,11 +327,7 @@ impl ProcState {
self.file_fetcher.clone(),
root_permissions,
dynamic_permissions,
- self
- .options
- .resolve_local_node_modules_folder()
- .with_context(|| "Resolving local node_modules folder.")?
- .map(|path| ModuleSpecifier::from_file_path(path).unwrap()),
+ self.options.node_modules_dir_specifier(),
);
let maybe_imports = self.options.to_maybe_imports()?;
let graph_resolver = self.resolver.as_graph_resolver();
@@ -632,25 +626,21 @@ impl ProcState {
}
/// Creates the default loader used for creating a graph.
- pub fn create_graph_loader(&self) -> Result<cache::FetchCacher, AnyError> {
- Ok(cache::FetchCacher::new(
+ pub fn create_graph_loader(&self) -> cache::FetchCacher {
+ cache::FetchCacher::new(
self.emit_cache.clone(),
self.file_fetcher.clone(),
PermissionsContainer::allow_all(),
PermissionsContainer::allow_all(),
- self
- .options
- .resolve_local_node_modules_folder()
- .with_context(|| "Resolving local node_modules folder.")?
- .map(|path| ModuleSpecifier::from_file_path(path).unwrap()),
- ))
+ self.options.node_modules_dir_specifier(),
+ )
}
pub async fn create_graph(
&self,
roots: Vec<ModuleSpecifier>,
) -> Result<deno_graph::ModuleGraph, AnyError> {
- let mut cache = self.create_graph_loader()?;
+ let mut cache = self.create_graph_loader();
self.create_graph_with_loader(roots, &mut cache).await
}
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index f30e7ce69..7dbf9c74c 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -2753,6 +2753,8 @@ itest!(package_json_auto_discovered_for_local_script_log {
args: "run -L debug -A no_deno_json/main.ts",
output: "run/with_package_json/no_deno_json/main.out",
maybe_cwd: Some("run/with_package_json/"),
+ // prevent creating a node_modules dir in the code directory
+ copy_temp_dir: Some("run/with_package_json/"),
envs: env_vars_for_npm_tests_no_sync_download(),
http_server: true,
});
@@ -2764,16 +2766,29 @@ itest!(
args: "run -L debug with_stop/some/nested/dir/main.ts",
output: "run/with_package_json/with_stop/main.out",
maybe_cwd: Some("run/with_package_json/"),
+ copy_temp_dir: Some("run/with_package_json/"),
envs: env_vars_for_npm_tests_no_sync_download(),
http_server: true,
exit_code: 1,
}
);
+itest!(
+ package_json_auto_discovered_node_modules_relative_package_json {
+ args: "run -A main.js",
+ output: "run/with_package_json/no_deno_json/sub_dir/main.out",
+ maybe_cwd: Some("run/with_package_json/no_deno_json/sub_dir"),
+ copy_temp_dir: Some("run/with_package_json/"),
+ envs: env_vars_for_npm_tests_no_sync_download(),
+ http_server: true,
+ }
+);
+
itest!(package_json_auto_discovered_for_npm_binary {
args: "run -L debug -A npm:@denotest/bin/cli-esm this is a test",
output: "run/with_package_json/npm_binary/main.out",
maybe_cwd: Some("run/with_package_json/npm_binary/"),
+ copy_temp_dir: Some("run/with_package_json/"),
envs: env_vars_for_npm_tests_no_sync_download(),
http_server: true,
});
diff --git a/cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.js b/cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.js
new file mode 100644
index 000000000..297653211
--- /dev/null
+++ b/cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.js
@@ -0,0 +1,2 @@
+console.log(Deno.cwd());
+console.log(Deno.statSync("../node_modules"));
diff --git a/cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.out b/cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.out
new file mode 100644
index 000000000..0ec791960
--- /dev/null
+++ b/cli/tests/testdata/run/with_package_json/no_deno_json/sub_dir/main.out
@@ -0,0 +1,7 @@
+Download http://[WILDCARD]
+[WILDCARD]sub_dir
+{
+ [WILDCARD]
+ isDirectory: true,
+ [WILDCARD]
+}
diff --git a/cli/tools/info.rs b/cli/tools/info.rs
index d120cb89f..8a7f4b6b9 100644
--- a/cli/tools/info.rs
+++ b/cli/tools/info.rs
@@ -34,7 +34,7 @@ pub async fn info(flags: Flags, info_flags: InfoFlags) -> Result<(), AnyError> {
let ps = ProcState::build(flags).await?;
if let Some(specifier) = info_flags.file {
let specifier = resolve_url_or_path(&specifier)?;
- let mut loader = ps.create_graph_loader()?;
+ let mut loader = ps.create_graph_loader();
loader.enable_loading_cache_info(); // for displaying the cache information
let graph = ps
.create_graph_with_loader(vec![specifier], &mut loader)
diff --git a/cli/tools/repl/session.rs b/cli/tools/repl/session.rs
index cb3862a63..e9ddd09b1 100644
--- a/cli/tools/repl/session.rs
+++ b/cli/tools/repl/session.rs
@@ -463,7 +463,7 @@ impl ReplSession {
if !self.has_initialized_node_runtime {
deno_node::initialize_runtime(
&mut self.worker.js_runtime,
- self.proc_state.options.node_modules_dir(),
+ self.proc_state.options.has_node_modules_dir(),
)
.await?;
self.has_initialized_node_runtime = true;
diff --git a/cli/worker.rs b/cli/worker.rs
index f8a9f54bb..000216102 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -304,7 +304,7 @@ impl CliMainWorker {
async fn initialize_main_module_for_node(&mut self) -> Result<(), AnyError> {
deno_node::initialize_runtime(
&mut self.worker.js_runtime,
- self.ps.options.node_modules_dir(),
+ self.ps.options.has_node_modules_dir(),
)
.await?;
if let DenoSubcommand::Run(flags) = self.ps.options.sub_command() {
@@ -631,7 +631,7 @@ fn create_web_worker_pre_execute_module_callback(
if ps.npm_resolver.has_packages() {
deno_node::initialize_runtime(
&mut worker.js_runtime,
- ps.options.node_modules_dir(),
+ ps.options.has_node_modules_dir(),
)
.await?;
}
diff --git a/test_util/src/lib.rs b/test_util/src/lib.rs
index 555c26ffe..25faa1633 100644
--- a/test_util/src/lib.rs
+++ b/test_util/src/lib.rs
@@ -31,6 +31,7 @@ use std::mem::replace;
use std::net::SocketAddr;
use std::ops::Deref;
use std::ops::DerefMut;
+use std::path::Path;
use std::path::PathBuf;
use std::pin::Pin;
use std::process::Child;
@@ -1923,12 +1924,17 @@ pub struct CheckOutputIntegrationTest<'a> {
pub envs: Vec<(String, String)>,
pub env_clear: bool,
pub temp_cwd: bool,
- // Relative to "testdata" directory
+ /// Copies the files at the specified directory in the "testdata" directory
+ /// to the temp folder and runs the test from there. This is useful when
+ /// the test creates files in the testdata directory (ex. a node_modules folder)
+ pub copy_temp_dir: Option<&'a str>,
+ /// Relative to "testdata" directory
pub maybe_cwd: Option<&'a str>,
}
impl<'a> CheckOutputIntegrationTest<'a> {
pub fn run(&self) {
+ let deno_dir = new_deno_dir(); // keep this alive for the test
let args = if self.args_vec.is_empty() {
std::borrow::Cow::Owned(self.args.split_whitespace().collect::<Vec<_>>())
} else {
@@ -1938,7 +1944,15 @@ impl<'a> CheckOutputIntegrationTest<'a> {
);
std::borrow::Cow::Borrowed(&self.args_vec)
};
- let testdata_dir = testdata_path();
+ let testdata_dir = if let Some(temp_copy_dir) = &self.copy_temp_dir {
+ let test_data_path = testdata_path().join(temp_copy_dir);
+ let temp_copy_dir = deno_dir.path().join(temp_copy_dir);
+ std::fs::create_dir_all(&temp_copy_dir).unwrap();
+ copy_dir_recursive(&test_data_path, &temp_copy_dir).unwrap();
+ deno_dir.path().to_owned()
+ } else {
+ testdata_path()
+ };
let args = args
.iter()
.map(|arg| arg.replace("$TESTDATA", &testdata_dir.to_string_lossy()))
@@ -1953,7 +1967,6 @@ impl<'a> CheckOutputIntegrationTest<'a> {
};
let (mut reader, writer) = pipe().unwrap();
- let deno_dir = new_deno_dir(); // keep this alive for the test
let mut command = deno_cmd_with_deno_dir(&deno_dir);
let cwd = if self.temp_cwd {
deno_dir.path().to_owned()
@@ -2328,6 +2341,37 @@ pub fn parse_max_mem(output: &str) -> Option<u64> {
None
}
+/// Copies a directory to another directory.
+///
+/// Note: Does not handle symlinks.
+pub fn copy_dir_recursive(from: &Path, to: &Path) -> Result<(), anyhow::Error> {
+ use anyhow::Context;
+
+ std::fs::create_dir_all(to)
+ .with_context(|| format!("Creating {}", to.display()))?;
+ let read_dir = std::fs::read_dir(from)
+ .with_context(|| format!("Reading {}", from.display()))?;
+
+ for entry in read_dir {
+ let entry = entry?;
+ let file_type = entry.file_type()?;
+ let new_from = from.join(entry.file_name());
+ let new_to = to.join(entry.file_name());
+
+ if file_type.is_dir() {
+ copy_dir_recursive(&new_from, &new_to).with_context(|| {
+ format!("Dir {} to {}", new_from.display(), new_to.display())
+ })?;
+ } else if file_type.is_file() {
+ std::fs::copy(&new_from, &new_to).with_context(|| {
+ format!("Copying {} to {}", new_from.display(), new_to.display())
+ })?;
+ }
+ }
+
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use super::*;