Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow xtasks to have more dependencies #4268

Merged
merged 2 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[alias]
xtask = "run --manifest-path xtask/Cargo.toml --"
xtask = "run --manifest-path xtask/Cargo.toml"

[build]
rustflags = [
Expand Down
94 changes: 0 additions & 94 deletions xtask/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 16 additions & 5 deletions xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@ version = "0.1.0"
edition = "2021"
publish = false

[features]
run-wasm = ["cargo-run-wasm"]

[dependencies]
# The dependencies in this config have no transitive dependencies.
anyhow = "1.0.71"
# Current contents filed as a PR here:
# <https://github.com/rukai/cargo-run-wasm/pull/37>
cargo-run-wasm = { version = "0.3.2", git = "https://github.com/ErichDonGubler/cargo-run-wasm", branch = "expose-args" }
env_logger = "0.10.0"
env_logger = { version = "0.10.0", default-features = false }
log = "0.4.18"
pico-args = { version = "0.5.0", features = ["eq-separator", "short-space-opt", "combined-flags"] }
pico-args = { version = "0.5.0", features = [
"eq-separator",
"short-space-opt",
"combined-flags",
] }
xshell = "0.2.3"

# Feature: run-wasm

# Current contents filed as a PR here:
# <https://github.com/rukai/cargo-run-wasm/pull/37>
cargo-run-wasm = { version = "0.3.2", git = "https://github.com/ErichDonGubler/cargo-run-wasm", branch = "expose-args", optional = true }

[workspace]
52 changes: 41 additions & 11 deletions xtask/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,26 @@ Options:
-h, --help Print help
";

pub(crate) struct Args {
pub(crate) subcommand: Subcommand,
pub struct Args {
pub subcommand: Subcommand,
pub command_args: Arguments,
}

impl Args {
pub fn parse() -> Self {
let mut args = Arguments::from_env();
log::debug!("parsing args: {args:?}");
if args.contains("--help") {
eprint!("{HELP}");
// Emulate Cargo exit status:
// <https://doc.rust-lang.org/cargo/commands/cargo.html#exit-status>
let cargo_like_exit_code = 101;
exit(cargo_like_exit_code);
}
match Subcommand::parse(args).map(|subcommand| Self { subcommand }) {
Ok(this) => this,
match Subcommand::parse(&mut args) {
Ok(subcommand) => Self {
subcommand,
command_args: args,
},
Err(e) => {
eprintln!("{:?}", anyhow!(e));
exit(1)
Expand All @@ -40,20 +43,47 @@ impl Args {
}
}

pub(crate) enum Subcommand {
RunWasm { args: Arguments },
Test { args: Arguments },
pub enum Subcommand {
RunWasm,
Test,
}

impl Subcommand {
fn parse(mut args: Arguments) -> anyhow::Result<Subcommand> {
/// Returns the name of the subcommand as a string.
///
/// Opposite of [`Self::parse`].
pub fn to_str(&self) -> &'static str {
match self {
Self::RunWasm => "run-wasm",
Self::Test => "test",
}
}

/// Returns true if all required features are enabled for this subcommand.
pub fn required_features_enabled(&self) -> bool {
match self {
Self::RunWasm => cfg!(feature = "run-wasm"),
Self::Test => true,
}
}

/// Comma separated list of features required by this subcommand.
pub fn features(&self) -> &'static str {
match self {
Self::RunWasm => "run-wasm",
// We will never ask for the features if required_features_enabled always returns true.
Self::Test => unreachable!(),
}
}

fn parse(args: &mut Arguments) -> anyhow::Result<Subcommand> {
let subcmd = args
.subcommand()
.context("failed to parse subcommand")?
.context("no subcommand specified; see `--help` for more details")?;
match &*subcmd {
"run-wasm" => Ok(Self::RunWasm { args }),
"test" => Ok(Self::Test { args }),
"run-wasm" => Ok(Self::RunWasm),
"test" => Ok(Self::Test),
other => {
bail!("unrecognized subcommand {other:?}; see `--help` for more details")
}
Expand Down
53 changes: 37 additions & 16 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::process::ExitCode;
use std::process::Command;

use anyhow::Context;
use cli::{Args, Subcommand};
use pico_args::Arguments;
use cli::Args;

mod cli;
mod test;

fn main() -> ExitCode {
fn main() -> anyhow::Result<()> {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.parse_default_env()
Expand All @@ -16,27 +15,48 @@ fn main() -> ExitCode {

let args = Args::parse();

match run(args) {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
log::error!("{e:?}");
ExitCode::FAILURE
if !args.subcommand.required_features_enabled() {
let features = args.subcommand.features();
log::info!(
"Required features \"{features}\" are not enabled, recursing with features enabled"
);

let subcommand_args = args.command_args.finish();
let iter = subcommand_args
.iter()
.map(|os| os.as_os_str().to_str().unwrap());

let status = Command::new("cargo")
.args(["xtask", "--features", features, args.subcommand.to_str()])
.args(iter)
.status()
.context("Failed to execute recursive cargo xtask")?;

if status.success() {
return Ok(());
} else {
return Err(anyhow::anyhow!("subcommand failed"));
}
}

run(args)
}

fn run(args: Args) -> anyhow::Result<()> {
let Args { subcommand } = args;
match subcommand {
Subcommand::RunWasm { mut args } => {
#[allow(unused_mut, unreachable_patterns)]
fn run(mut args: Args) -> anyhow::Result<()> {
match args.subcommand {
#[cfg(feature = "run-wasm")]
cli::Subcommand::RunWasm => {
log::info!("Running wasm example");
// Use top-level Cargo.toml instead of xtask/Cargo.toml by default
let manifest_path = args
.command_args
.value_from_str("--manifest-path")
.unwrap_or_else(|_| "../Cargo.toml".to_string());
let mut arg_vec = args.finish();
let mut arg_vec = args.command_args.finish();
arg_vec.push("--manifest-path".into());
arg_vec.push(manifest_path.into());
let args = Arguments::from_vec(arg_vec);
let args = pico_args::Arguments::from_vec(arg_vec);

cargo_run_wasm::run_wasm_with_css_and_args(
"body { margin: 0px; }",
Expand All @@ -46,6 +66,7 @@ fn run(args: Args) -> anyhow::Result<()> {
);
Ok(())
}
Subcommand::Test { args } => test::run_tests(args),
cli::Subcommand::Test => test::run_tests(args.command_args),
_ => unreachable!(),
}
}