summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShreyas <shreyass.ranganatha@gmail.com>2023-09-18 23:18:54 +0530
committerGitHub <noreply@github.com>2023-09-18 17:48:54 +0000
commitd72f5d573a59fc20ba465dffd1698984c7dde024 (patch)
tree8c6672fdac010faa3b1dd9133bd4e0f1c13e0c47
parent87ddd1f04d2b71aadb3a8a5fb3e4ac15988947c1 (diff)
fix: `Deno.Command` - improve error message when `cwd` is not a directory (#20460)
-rw-r--r--cli/tests/unit/command_test.ts29
-rw-r--r--runtime/ops/process.rs55
2 files changed, 75 insertions, 9 deletions
diff --git a/cli/tests/unit/command_test.ts b/cli/tests/unit/command_test.ts
index ce3af08fb..5f56a0c22 100644
--- a/cli/tests/unit/command_test.ts
+++ b/cli/tests/unit/command_test.ts
@@ -424,6 +424,31 @@ Deno.test({ permissions: { run: true } }, function commandSyncNotFound() {
);
});
+Deno.test({ permissions: { run: true, read: true } }, function cwdNotFound() {
+ assertThrows(
+ () =>
+ new Deno.Command(Deno.execPath(), {
+ cwd: Deno.cwd() + "/non-existent-directory",
+ }).output(),
+ Deno.errors.NotFound,
+ "No such cwd",
+ );
+});
+
+Deno.test(
+ { permissions: { run: true, read: true } },
+ function cwdNotDirectory() {
+ assertThrows(
+ () =>
+ new Deno.Command(Deno.execPath(), {
+ cwd: Deno.execPath(),
+ }).output(),
+ Deno.errors.NotFound,
+ "cwd is not a directory",
+ );
+ },
+);
+
Deno.test(
{ permissions: { run: true, read: true } },
async function commandFailedWithCode() {
@@ -892,12 +917,12 @@ Deno.test(
assertThrows(
() => new Deno.Command("doesntexist").outputSync(),
Error,
- "Failed to spawn: doesntexist",
+ "Failed to spawn 'doesntexist'",
);
await assertRejects(
async () => await new Deno.Command("doesntexist").output(),
Error,
- "Failed to spawn: doesntexist",
+ "Failed to spawn 'doesntexist'",
);
},
);
diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs
index a5150950e..51c9f961a 100644
--- a/runtime/ops/process.rs
+++ b/runtime/ops/process.rs
@@ -286,12 +286,53 @@ fn spawn_child(
// We want to kill child when it's closed
command.kill_on_drop(true);
- let mut child = command.spawn().with_context(|| {
- format!(
- "Failed to spawn: {}",
- command.as_std().get_program().to_string_lossy()
- )
- })?;
+ let mut child = match command.spawn() {
+ Ok(child) => child,
+ Err(err) => {
+ let command = command.as_std();
+ let command_name = command.get_program().to_string_lossy();
+
+ if let Some(cwd) = command.get_current_dir() {
+ // launching a sub process always depends on the real
+ // file system so using these methods directly is ok
+ #[allow(clippy::disallowed_methods)]
+ if !cwd.exists() {
+ return Err(
+ std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ format!(
+ "Failed to spawn '{}': No such cwd '{}'",
+ command_name,
+ cwd.to_string_lossy()
+ ),
+ )
+ .into(),
+ );
+ }
+
+ #[allow(clippy::disallowed_methods)]
+ if !cwd.is_dir() {
+ return Err(
+ std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ format!(
+ "Failed to spawn '{}': cwd is not a directory '{}'",
+ command_name,
+ cwd.to_string_lossy()
+ ),
+ )
+ .into(),
+ );
+ }
+ }
+
+ return Err(AnyError::from(err).context(format!(
+ "Failed to spawn '{}'",
+ command.get_program().to_string_lossy()
+ )));
+ }
+ };
+
let pid = child.id().expect("Process ID should be set.");
let stdin_rid = child
@@ -362,7 +403,7 @@ fn op_spawn_sync(
let mut command = create_command(state, args, "Deno.Command().outputSync()")?;
let output = command.output().with_context(|| {
format!(
- "Failed to spawn: {}",
+ "Failed to spawn '{}'",
command.get_program().to_string_lossy()
)
})?;