Skip to content

Commit 5fc5893

Browse files
egithinjiEric Githinji
andauthored
Support setting language and output directory in cargo xtask (#2776)
In addition to simplifying building locally (no need to set an environment variable), this makes it possible to use the `cargo xtask build` command in the CI and specify any output location, rather than relying on the build.sh script. --------- Co-authored-by: Eric Githinji <[email protected]>
1 parent 16d25db commit 5fc5893

File tree

2 files changed

+73
-30
lines changed

2 files changed

+73
-30
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ cargo xtask install-tools
7575

7676
Here is a summary of the various commands you can run in the project.
7777

78-
| Command | Description |
79-
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
80-
| `cargo install-tools` | Install all the tools the project depends on. |
81-
| `cargo serve` | Start a web server with the course. You'll find the content on http://localhost:3000. |
82-
| `cargo rust-tests` | Test the included Rust snippets. |
83-
| `cargo web-tests` | Run the web driver tests in the tests directory. |
84-
| `cargo build-book` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, run MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx where xx is the ISO 639 language code (e.g. da for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. |
78+
| Command | Description |
79+
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
80+
| `cargo install-tools` | Install all the tools the project depends on. |
81+
| `cargo serve` | Start a web server with the course. You'll find the content on http://localhost:3000. To serve any of the translated versions of the course, add the language flag (`--language` or `-l`) followed by xx, where xx is the ISO 639 language code (e.g. `cargo xtask serve -l da` for the Danish translation). |
82+
| `cargo rust-tests` | Test the included Rust snippets. |
83+
| `cargo web-tests` | Run the web driver tests in the tests directory. |
84+
| `cargo build-book` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, add the language flag (`--language` or `-l`) followed by xx, where xx is the ISO 639 language code (e.g. `cargo xtask build -l da` for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. |
8585

8686
> **Note** On Windows, you need to enable symlinks
8787
> (`git config --global core.symlinks true`) and Developer Mode.

xtask/src/main.rs

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
//! the tools.
2121
2222
use anyhow::{Ok, Result, anyhow};
23-
use clap::{Parser, ValueEnum};
24-
use std::path::Path;
23+
use clap::{Parser, Subcommand};
24+
use std::path::{Path, PathBuf};
2525
use std::{env, process::Command};
2626

2727
fn main() -> Result<()> {
@@ -38,11 +38,11 @@ fn main() -> Result<()> {
3838
)]
3939
struct Cli {
4040
/// The task to execute
41-
#[arg(value_enum)]
41+
#[command(subcommand)]
4242
task: Task,
4343
}
4444

45-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
45+
#[derive(Subcommand)]
4646
enum Task {
4747
/// Installs the tools the project depends on.
4848
InstallTools,
@@ -51,9 +51,25 @@ enum Task {
5151
/// Tests all included Rust snippets.
5252
RustTests,
5353
/// Starts a web server with the course.
54-
Serve,
55-
/// Create a static version of the course in the `book/` directory.
56-
Build,
54+
Serve {
55+
/// ISO 639 language code (e.g. da for the Danish translation).
56+
#[arg(short, long)]
57+
language: Option<String>,
58+
59+
/// Directory to place the build. If not provided, defaults to the book/ directory (or the book/xx directory if a language is provided).
60+
#[arg(short, long)]
61+
output: Option<PathBuf>,
62+
},
63+
/// Create a static version of the course.
64+
Build {
65+
/// ISO 639 language code (e.g. da for the Danish translation).
66+
#[arg(short, long)]
67+
language: Option<String>,
68+
69+
/// Directory to place the build. If not provided, defaults to the book/ directory (or the book/xx directory if a language is provided).
70+
#[arg(short, long)]
71+
output: Option<PathBuf>,
72+
},
5773
}
5874

5975
fn execute_task() -> Result<()> {
@@ -62,15 +78,14 @@ fn execute_task() -> Result<()> {
6278
Task::InstallTools => install_tools()?,
6379
Task::WebTests => run_web_tests()?,
6480
Task::RustTests => run_rust_tests()?,
65-
Task::Serve => start_web_server()?,
66-
Task::Build => build()?,
81+
Task::Serve { language, output } => start_web_server(language, output)?,
82+
Task::Build { language, output } => build(language, output)?,
6783
}
6884
Ok(())
6985
}
7086

7187
fn install_tools() -> Result<()> {
7288
println!("Installing project tools...");
73-
7489
let path_to_mdbook_exerciser =
7590
Path::new(env!("CARGO_WORKSPACE_DIR")).join("mdbook-exerciser");
7691
let path_to_mdbook_course =
@@ -136,7 +151,6 @@ fn run_web_tests() -> Result<()> {
136151

137152
fn run_rust_tests() -> Result<()> {
138153
println!("Running rust tests...");
139-
140154
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
141155

142156
let status = Command::new("mdbook")
@@ -156,15 +170,26 @@ fn run_rust_tests() -> Result<()> {
156170
Ok(())
157171
}
158172

159-
fn start_web_server() -> Result<()> {
173+
fn start_web_server(
174+
language: Option<String>,
175+
output_arg: Option<PathBuf>,
176+
) -> Result<()> {
160177
println!("Starting web server ...");
161178
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
162179

163-
let status = Command::new("mdbook")
164-
.current_dir(path_to_workspace_root.to_str().unwrap())
165-
.arg("serve")
166-
.status()
167-
.expect("Failed to execute mdbook serve");
180+
let mut command = Command::new("mdbook");
181+
command.current_dir(path_to_workspace_root.to_str().unwrap());
182+
command.arg("serve");
183+
184+
if let Some(language) = &language {
185+
println!("Language: {}", &language);
186+
command.env("MDBOOK_BOOK__LANGUAGE", &language);
187+
}
188+
189+
command.arg("-d");
190+
command.arg(get_output_dir(language, output_arg));
191+
192+
let status = command.status().expect("Failed to execute mdbook serve");
168193

169194
if !status.success() {
170195
let error_message = format!(
@@ -176,15 +201,23 @@ fn start_web_server() -> Result<()> {
176201
Ok(())
177202
}
178203

179-
fn build() -> Result<()> {
204+
fn build(language: Option<String>, output_arg: Option<PathBuf>) -> Result<()> {
180205
println!("Building course...");
181206
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
182207

183-
let status = Command::new("mdbook")
184-
.current_dir(path_to_workspace_root.to_str().unwrap())
185-
.arg("build")
186-
.status()
187-
.expect("Failed to execute mdbook build");
208+
let mut command = Command::new("mdbook");
209+
command.current_dir(path_to_workspace_root.to_str().unwrap());
210+
command.arg("build");
211+
212+
if let Some(language) = &language {
213+
println!("Language: {}", &language);
214+
command.env("MDBOOK_BOOK__LANGUAGE", language);
215+
}
216+
217+
command.arg("-d");
218+
command.arg(get_output_dir(language, output_arg));
219+
220+
let status = command.status().expect("Failed to execute mdbook build");
188221

189222
if !status.success() {
190223
let error_message = format!(
@@ -195,3 +228,13 @@ fn build() -> Result<()> {
195228
}
196229
Ok(())
197230
}
231+
232+
fn get_output_dir(language: Option<String>, output_arg: Option<PathBuf>) -> PathBuf {
233+
// If the 'output' arg is specified by the caller, use that, otherwise output to the 'book/' directory
234+
// (or the 'book/xx' directory if a language was specified).
235+
if let Some(d) = output_arg {
236+
d
237+
} else {
238+
Path::new("book").join(language.unwrap_or("".to_string()))
239+
}
240+
}

0 commit comments

Comments
 (0)