diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index 117595ef1..7357dc8e6 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -399,7 +399,11 @@ fn execute_subcommand(config: &mut Config, cmd: &str, subcommand_args: &ArgMatch .unwrap_or_default() .map(OsString::as_os_str), ); - super::execute_external_subcommand(config, cmd, &ext_args) + if commands::run::is_manifest_command(cmd) { + commands::run::exec_manifest_command(config, cmd, &ext_args) + } else { + super::execute_external_subcommand(config, cmd, &ext_args) + } } #[derive(Default)] diff --git a/src/bin/cargo/commands/run.rs b/src/bin/cargo/commands/run.rs index cde754c7a..0414d8e9b 100644 --- a/src/bin/cargo/commands/run.rs +++ b/src/bin/cargo/commands/run.rs @@ -1,3 +1,7 @@ +use std::ffi::OsStr; +use std::ffi::OsString; +use std::path::Path; + use crate::command_prelude::*; use crate::util::restricted_names::is_glob_pattern; use cargo::core::Verbosity; @@ -13,7 +17,7 @@ pub fn cli() -> Command { .arg( Arg::new("args") .help("Arguments for the binary or example to run") - .value_parser(value_parser!(std::ffi::OsString)) + .value_parser(value_parser!(OsString)) .num_args(0..) .trailing_var_arg(true), ) @@ -101,3 +105,16 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { } }) } + +pub fn is_manifest_command(arg: &str) -> bool { + let path = Path::new(arg); + 1 < path.components().count() || path.extension() == Some(OsStr::new("rs")) +} + +pub fn exec_manifest_command(config: &Config, cmd: &str, _args: &[&OsStr]) -> CliResult { + if !config.cli_unstable().script { + return Err(anyhow::anyhow!("running `{cmd}` requires `-Zscript`").into()); + } + + todo!("support for running manifest-commands is not yet implemented") +} diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index 170a22667..2c282c0a3 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -123,6 +123,7 @@ mod rustdoc_extern_html; mod rustdocflags; mod rustflags; mod rustup; +mod script; mod search; mod shell_quoting; mod source_replacement; diff --git a/tests/testsuite/script.rs b/tests/testsuite/script.rs new file mode 100644 index 000000000..c20a9c33c --- /dev/null +++ b/tests/testsuite/script.rs @@ -0,0 +1,106 @@ +const ECHO_SCRIPT: &str = r#"#!/usr/bin/env cargo + +fn main() { + let mut args = std::env::args_os(); + let bin = args.next().unwrap().to_str().unwrap().to_owned(); + let args = args.collect::>(); + println!("bin: {bin}"); + println!("args: {args:?}"); +} +"#; + +#[cargo_test] +fn basic_rs() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript echo.rs") + .arg("--help") // An arg that, if processed by cargo, will cause problems + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout("") + .with_stderr("\ +thread 'main' panicked at 'not yet implemented: support for running manifest-commands is not yet implemented', [..] +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +") + .run(); +} + +#[cargo_test] +fn basic_path() { + let p = cargo_test_support::project() + .file("echo", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript ./echo") + .arg("--help") // An arg that, if processed by cargo, will cause problems + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout("") + .with_stderr("\ +thread 'main' panicked at 'not yet implemented: support for running manifest-commands is not yet implemented', [..] +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +") + .run(); +} + +#[cargo_test] +fn path_required() { + let p = cargo_test_support::project() + .file("echo", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript echo") + .arg("--help") // An arg that, if processed by cargo, will cause problems + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout("") + .with_stderr( + "\ +error: no such command: `echo` + +Did you mean `bench`? + +View all installed commands with `cargo --list` +", + ) + .run(); +} + +#[cargo_test] +fn requires_nightly() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .build(); + + p.cargo("echo.rs") + .arg("--help") // An arg that, if processed by cargo, will cause problems + .with_status(101) + .with_stdout("") + .with_stderr( + "\ +error: running `echo.rs` requires `-Zscript` +", + ) + .run(); +} + +#[cargo_test] +fn requires_z_flag() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .build(); + + p.cargo("echo.rs") + .arg("--help") // An arg that, if processed by cargo, will cause problems + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout("") + .with_stderr( + "\ +error: running `echo.rs` requires `-Zscript` +", + ) + .run(); +}