Skip to content

Commit 0085748

Browse files
egithinjiEric Githinji
andauthored
Xtask improvements (#2707)
Some minor improvements to an already-merged PR (#2688) on the task automation via xtask. Main ones being: - Adding more explanatory comments about what the xtask package is and what it does - Using Clap for CLI arg parsing - Using Anyhow for error handling --------- Co-authored-by: Eric Githinji <egithinji@google.com>
1 parent 43cf3fb commit 0085748

File tree

5 files changed

+87
-23
lines changed

5 files changed

+87
-23
lines changed

.cargo/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
[alias]
2+
# We use this alias for task automation in the project.
3+
# See README in xtask directory.
24
xtask = "run --package xtask --"

Cargo.lock

Lines changed: 27 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

xtask/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@
22
name = "xtask"
33
version = "0.1.0"
44
edition = "2021"
5+
publish = false
56

67
[dependencies]
8+
anyhow = "1.0.97"
9+
clap = { version = "4.5.35", features = ["derive"] }

xtask/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# xtask
2+
3+
The purpose of the xtask binary is to enable cross platform task automation
4+
within the project (somewhat similar to how `npm run` is used in Node.js
5+
projects to run scripts). Please see
6+
[cargo xtask](https://github.com/matklad/cargo-xtask) for more information.
7+
8+
To add support for a new task, add a new arm to the `match` in the
9+
`execute_task` function, and add a new handler function that contains the logic.

xtask/src/main.rs

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,60 @@
1-
use std::{env, process::Command};
1+
// Copyright 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//! This binary allows us to execute tasks within the project by running
16+
//! `cargo xtask <task>`. It can thus be used as a task automation tool.
17+
//! For example instead of repeatedly running `cargo install` from the CLI
18+
//! to install all the necessary tools for the project we can just run
19+
//! `cargo xtask install-tools` and the logic defined here will install
20+
//! the tools.
221
3-
type DynError = Box<dyn std::error::Error>;
22+
use anyhow::{anyhow, Ok, Result};
23+
use clap::Parser;
24+
use std::{env, process::Command};
425

5-
fn main() {
26+
fn main() -> Result<()> {
627
if let Err(e) = execute_task() {
728
eprintln!("{e}");
829
std::process::exit(-1);
930
}
31+
Ok(())
1032
}
1133

12-
fn execute_task() -> Result<(), DynError> {
13-
let task = env::args().nth(1);
14-
match task.as_deref() {
15-
Some("install-tools") => install_tools()?,
34+
#[derive(Parser, Debug)]
35+
#[command(
36+
about = "Binary for executing tasks within the Comprehensive Rust project"
37+
)]
38+
struct Args {
39+
#[arg(required = true, help = "The task to execute")]
40+
task: String,
41+
}
42+
43+
fn execute_task() -> Result<()> {
44+
let task = Args::parse().task;
45+
match task.as_str() {
46+
"install-tools" => install_tools()?,
1647
_ => {
17-
return Err(Box::from(get_help_string(task.as_deref())));
48+
return Err(anyhow!(unrecognized_task_string(task.as_str())));
1849
}
1950
}
2051
Ok(())
2152
}
2253

23-
fn install_tools() -> Result<(), DynError> {
54+
fn install_tools() -> Result<()> {
2455
println!("Installing project tools...");
2556

26-
let install_args: Vec<Vec<&str>> = vec![
57+
let install_args = vec![
2758
// The --locked flag is important for reproducible builds. It also
2859
// avoids breakage due to skews between mdbook and mdbook-svgbob.
2960
vec!["mdbook", "--locked", "--version", "0.4.44"],
@@ -49,21 +80,17 @@ fn install_tools() -> Result<(), DynError> {
4980
args.join(" "),
5081
status.code().unwrap()
5182
);
52-
return Err(Box::from(error_message));
83+
return Err(anyhow!(error_message));
5384
}
5485
}
5586

5687
Ok(())
5788
}
5889

59-
fn get_help_string(task: Option<&str>) -> String {
60-
if let Some(t) = task {
61-
format!(
62-
"Unrecognized task '{t}'. Available tasks:
90+
fn unrecognized_task_string(task: &str) -> String {
91+
format!(
92+
"Unrecognized task '{task}'. Available tasks:
6393
6494
install-tools Installs the tools the project depends on."
65-
)
66-
} else {
67-
"Missing task. To execute a task run `cargo xtask [task]`.".to_string()
68-
}
95+
)
6996
}

0 commit comments

Comments
 (0)