summaryrefslogtreecommitdiffstats
path: root/vendor/mdbook/src/cmd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /vendor/mdbook/src/cmd
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/mdbook/src/cmd')
-rw-r--r--vendor/mdbook/src/cmd/build.rs30
-rw-r--r--vendor/mdbook/src/cmd/clean.rs26
-rw-r--r--vendor/mdbook/src/cmd/command_prelude.rs45
-rw-r--r--vendor/mdbook/src/cmd/init.rs44
-rw-r--r--vendor/mdbook/src/cmd/mod.rs1
-rw-r--r--vendor/mdbook/src/cmd/serve.rs47
-rw-r--r--vendor/mdbook/src/cmd/test.rs66
-rw-r--r--vendor/mdbook/src/cmd/watch.rs81
8 files changed, 175 insertions, 165 deletions
diff --git a/vendor/mdbook/src/cmd/build.rs b/vendor/mdbook/src/cmd/build.rs
index 5fe73236c..14a9fec6e 100644
--- a/vendor/mdbook/src/cmd/build.rs
+++ b/vendor/mdbook/src/cmd/build.rs
@@ -1,28 +1,16 @@
+use super::command_prelude::*;
use crate::{get_book_dir, open};
-use clap::{arg, App, Arg, ArgMatches};
use mdbook::errors::Result;
use mdbook::MDBook;
+use std::path::PathBuf;
// Create clap subcommand arguments
-pub fn make_subcommand<'help>() -> App<'help> {
- App::new("build")
+pub fn make_subcommand() -> Command {
+ Command::new("build")
.about("Builds a book from its markdown files")
- .arg(
- Arg::new("dest-dir")
- .short('d')
- .long("dest-dir")
- .value_name("dest-dir")
- .help(
- "Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
- ),
- )
- .arg(arg!([dir]
- "Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)"
- ))
- .arg(arg!(-o --open "Opens the compiled book in a web browser"))
+ .arg_dest_dir()
+ .arg_root_dir()
+ .arg_open()
}
// Build command implementation
@@ -30,13 +18,13 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let book_dir = get_book_dir(args);
let mut book = MDBook::load(&book_dir)?;
- if let Some(dest_dir) = args.value_of("dest-dir") {
+ if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") {
book.config.build.build_dir = dest_dir.into();
}
book.build()?;
- if args.is_present("open") {
+ if args.get_flag("open") {
// FIXME: What's the right behaviour if we don't use the HTML renderer?
let path = book.build_dir_for("html").join("index.html");
if !path.exists() {
diff --git a/vendor/mdbook/src/cmd/clean.rs b/vendor/mdbook/src/cmd/clean.rs
index 0569726e1..3ec605fea 100644
--- a/vendor/mdbook/src/cmd/clean.rs
+++ b/vendor/mdbook/src/cmd/clean.rs
@@ -1,28 +1,16 @@
+use super::command_prelude::*;
use crate::get_book_dir;
use anyhow::Context;
-use clap::{arg, App, Arg, ArgMatches};
use mdbook::MDBook;
use std::fs;
+use std::path::PathBuf;
// Create clap subcommand arguments
-pub fn make_subcommand<'help>() -> App<'help> {
- App::new("clean")
+pub fn make_subcommand() -> Command {
+ Command::new("clean")
.about("Deletes a built book")
- .arg(
- Arg::new("dest-dir")
- .short('d')
- .long("dest-dir")
- .value_name("dest-dir")
- .help(
- "Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
- ),
- )
- .arg(arg!([dir]
- "Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)"
- ))
+ .arg_dest_dir()
+ .arg_root_dir()
}
// Clean command implementation
@@ -30,7 +18,7 @@ pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> {
let book_dir = get_book_dir(args);
let book = MDBook::load(&book_dir)?;
- let dir_to_remove = match args.value_of("dest-dir") {
+ let dir_to_remove = match args.get_one::<PathBuf>("dest-dir") {
Some(dest_dir) => dest_dir.into(),
None => book.root.join(&book.config.build.build_dir),
};
diff --git a/vendor/mdbook/src/cmd/command_prelude.rs b/vendor/mdbook/src/cmd/command_prelude.rs
new file mode 100644
index 000000000..b6362e603
--- /dev/null
+++ b/vendor/mdbook/src/cmd/command_prelude.rs
@@ -0,0 +1,45 @@
+//! Helpers for building the command-line arguments for commands.
+
+pub use clap::{arg, Arg, ArgMatches, Command};
+use std::path::PathBuf;
+
+pub trait CommandExt: Sized {
+ fn _arg(self, arg: Arg) -> Self;
+
+ fn arg_dest_dir(self) -> Self {
+ self._arg(
+ Arg::new("dest-dir")
+ .short('d')
+ .long("dest-dir")
+ .value_name("dest-dir")
+ .value_parser(clap::value_parser!(PathBuf))
+ .help(
+ "Output directory for the book\n\
+ Relative paths are interpreted relative to the book's root directory.\n\
+ If omitted, mdBook uses build.build-dir from book.toml \
+ or defaults to `./book`.",
+ ),
+ )
+ }
+
+ fn arg_root_dir(self) -> Self {
+ self._arg(
+ Arg::new("dir")
+ .help(
+ "Root directory for the book\n\
+ (Defaults to the current directory when omitted)",
+ )
+ .value_parser(clap::value_parser!(PathBuf)),
+ )
+ }
+
+ fn arg_open(self) -> Self {
+ self._arg(arg!(-o --open "Opens the compiled book in a web browser"))
+ }
+}
+
+impl CommandExt for Command {
+ fn _arg(self, arg: Arg) -> Self {
+ self.arg(arg)
+ }
+}
diff --git a/vendor/mdbook/src/cmd/init.rs b/vendor/mdbook/src/cmd/init.rs
index c964dcc13..d8ce93d16 100644
--- a/vendor/mdbook/src/cmd/init.rs
+++ b/vendor/mdbook/src/cmd/init.rs
@@ -1,5 +1,5 @@
use crate::get_book_dir;
-use clap::{arg, App, Arg, ArgMatches};
+use clap::{arg, ArgMatches, Command as ClapCommand};
use mdbook::config;
use mdbook::errors::Result;
use mdbook::MDBook;
@@ -8,30 +8,22 @@ use std::io::Write;
use std::process::Command;
// Create clap subcommand arguments
-pub fn make_subcommand<'help>() -> App<'help> {
- App::new("init")
+pub fn make_subcommand() -> ClapCommand {
+ ClapCommand::new("init")
.about("Creates the boilerplate structure and files for a new book")
- // the {n} denotes a newline which will properly aligned in all help messages
- .arg(arg!([dir]
- "Directory to create the book in{n}\
- (Defaults to the Current Directory when omitted)"
- ))
- .arg(arg!(--theme "Copies the default theme into your source folder"))
- .arg(arg!(--force "Skips confirmation prompts"))
.arg(
- Arg::new("title")
- .long("title")
- .takes_value(true)
- .help("Sets the book title")
- .required(false),
+ arg!([dir]
+ "Directory to create the book in\n\
+ (Defaults to the current directory when omitted)"
+ )
+ .value_parser(clap::value_parser!(std::path::PathBuf)),
)
+ .arg(arg!(--theme "Copies the default theme into your source folder"))
+ .arg(arg!(--force "Skips confirmation prompts"))
+ .arg(arg!(--title <title> "Sets the book title"))
.arg(
- Arg::new("ignore")
- .long("ignore")
- .takes_value(true)
- .possible_values(&["none", "git"])
- .help("Creates a VCS ignore file (i.e. .gitignore)")
- .required(false),
+ arg!(--ignore <ignore> "Creates a VCS ignore file (i.e. .gitignore)")
+ .value_parser(["none", "git"]),
)
}
@@ -41,12 +33,12 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let mut builder = MDBook::init(&book_dir);
let mut config = config::Config::default();
// If flag `--theme` is present, copy theme to src
- if args.is_present("theme") {
+ if args.get_flag("theme") {
let theme_dir = book_dir.join("theme");
println!();
println!("Copying the default theme to {}", theme_dir.display());
// Skip this if `--force` is present
- if !args.is_present("force") && theme_dir.exists() {
+ if !args.get_flag("force") && theme_dir.exists() {
println!("This could potentially overwrite files already present in that directory.");
print!("\nAre you sure you want to continue? (y/n) ");
@@ -59,7 +51,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
}
}
- if let Some(ignore) = args.value_of("ignore") {
+ if let Some(ignore) = args.get_one::<String>("ignore").map(|s| s.as_str()) {
match ignore {
"git" => builder.create_gitignore(true),
_ => builder.create_gitignore(false),
@@ -71,8 +63,8 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
}
}
- config.book.title = if args.is_present("title") {
- args.value_of("title").map(String::from)
+ config.book.title = if args.contains_id("title") {
+ args.get_one::<String>("title").map(String::from)
} else {
request_book_title()
};
diff --git a/vendor/mdbook/src/cmd/mod.rs b/vendor/mdbook/src/cmd/mod.rs
index c5b6730f1..b21979b27 100644
--- a/vendor/mdbook/src/cmd/mod.rs
+++ b/vendor/mdbook/src/cmd/mod.rs
@@ -2,6 +2,7 @@
pub mod build;
pub mod clean;
+pub mod command_prelude;
pub mod init;
#[cfg(feature = "serve")]
pub mod serve;
diff --git a/vendor/mdbook/src/cmd/serve.rs b/vendor/mdbook/src/cmd/serve.rs
index bafbfd52e..88898567e 100644
--- a/vendor/mdbook/src/cmd/serve.rs
+++ b/vendor/mdbook/src/cmd/serve.rs
@@ -1,7 +1,8 @@
+use super::command_prelude::*;
#[cfg(feature = "watch")]
use super::watch;
use crate::{get_book_dir, open};
-use clap::{arg, App, Arg, ArgMatches};
+use clap::builder::NonEmptyStringValueParser;
use futures_util::sink::SinkExt;
use futures_util::StreamExt;
use mdbook::errors::*;
@@ -18,43 +19,30 @@ use warp::Filter;
const LIVE_RELOAD_ENDPOINT: &str = "__livereload";
// Create clap subcommand arguments
-pub fn make_subcommand<'help>() -> App<'help> {
- App::new("serve")
+pub fn make_subcommand() -> Command {
+ Command::new("serve")
.about("Serves a book at http://localhost:3000, and rebuilds it on changes")
- .arg(
- Arg::new("dest-dir")
- .short('d')
- .long("dest-dir")
- .value_name("dest-dir")
- .help(
- "Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
- ),
- )
- .arg(arg!([dir]
- "Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)"
- ))
+ .arg_dest_dir()
+ .arg_root_dir()
.arg(
Arg::new("hostname")
.short('n')
.long("hostname")
- .takes_value(true)
+ .num_args(1)
.default_value("localhost")
- .forbid_empty_values(true)
+ .value_parser(NonEmptyStringValueParser::new())
.help("Hostname to listen on for HTTP connections"),
)
.arg(
Arg::new("port")
.short('p')
.long("port")
- .takes_value(true)
+ .num_args(1)
.default_value("3000")
- .forbid_empty_values(true)
+ .value_parser(NonEmptyStringValueParser::new())
.help("Port to use for HTTP connections"),
)
- .arg(arg!(-o --open "Opens the compiled book in a web browser"))
+ .arg_open()
}
// Serve command implementation
@@ -62,17 +50,17 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let book_dir = get_book_dir(args);
let mut book = MDBook::load(&book_dir)?;
- let port = args.value_of("port").unwrap();
- let hostname = args.value_of("hostname").unwrap();
- let open_browser = args.is_present("open");
+ let port = args.get_one::<String>("port").unwrap();
+ let hostname = args.get_one::<String>("hostname").unwrap();
+ let open_browser = args.get_flag("open");
let address = format!("{}:{}", hostname, port);
let update_config = |book: &mut MDBook| {
book.config
- .set("output.html.live-reload-endpoint", &LIVE_RELOAD_ENDPOINT)
+ .set("output.html.live-reload-endpoint", LIVE_RELOAD_ENDPOINT)
.expect("live-reload-endpoint update failed");
- if let Some(dest_dir) = args.value_of("dest-dir") {
+ if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") {
book.config.build.build_dir = dest_dir.into();
}
// Override site-url for local serving of the 404 file
@@ -89,8 +77,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let input_404 = book
.config
.get("output.html.input-404")
- .map(toml::Value::as_str)
- .and_then(std::convert::identity) // flatten
+ .and_then(toml::Value::as_str)
.map(ToString::to_string);
let file_404 = get_404_output_file(&input_404);
diff --git a/vendor/mdbook/src/cmd/test.rs b/vendor/mdbook/src/cmd/test.rs
index 02f982a49..3efe130b1 100644
--- a/vendor/mdbook/src/cmd/test.rs
+++ b/vendor/mdbook/src/cmd/test.rs
@@ -1,54 +1,58 @@
+use super::command_prelude::*;
use crate::get_book_dir;
-use clap::{arg, App, Arg, ArgMatches};
+use clap::builder::NonEmptyStringValueParser;
+use clap::{Arg, ArgAction, ArgMatches, Command};
use mdbook::errors::Result;
use mdbook::MDBook;
+use std::path::PathBuf;
// Create clap subcommand arguments
-pub fn make_subcommand<'help>() -> App<'help> {
- App::new("test")
+pub fn make_subcommand() -> Command {
+ Command::new("test")
.about("Tests that a book's Rust code samples compile")
+ // FIXME: --dest-dir is unused by the test command, it should be removed
+ .arg_dest_dir()
+ .arg_root_dir()
.arg(
- Arg::new("dest-dir")
- .short('d')
- .long("dest-dir")
- .value_name("dest-dir")
+ Arg::new("chapter")
+ .short('c')
+ .long("chapter")
+ .value_name("chapter"),
+ )
+ .arg(
+ Arg::new("library-path")
+ .short('L')
+ .long("library-path")
+ .value_name("dir")
+ .value_delimiter(',')
+ .value_parser(NonEmptyStringValueParser::new())
+ .action(ArgAction::Append)
.help(
- "Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
+ "A comma-separated list of directories to add to the crate \
+ search path when building tests",
),
)
- .arg(arg!([dir]
- "Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)"
- ))
- .arg(Arg::new("library-path")
- .short('L')
- .long("library-path")
- .value_name("dir")
- .takes_value(true)
- .use_delimiter(true)
- .require_delimiter(true)
- .multiple_values(true)
- .multiple_occurrences(true)
- .forbid_empty_values(true)
- .help("A comma-separated list of directories to add to {n}the crate search path when building tests"))
}
// test command implementation
pub fn execute(args: &ArgMatches) -> Result<()> {
let library_paths: Vec<&str> = args
- .values_of("library-path")
- .map(std::iter::Iterator::collect)
+ .get_many("library-path")
+ .map(|it| it.map(String::as_str).collect())
.unwrap_or_default();
+
+ let chapter: Option<&str> = args.get_one::<String>("chapter").map(|s| s.as_str());
+
let book_dir = get_book_dir(args);
let mut book = MDBook::load(&book_dir)?;
- if let Some(dest_dir) = args.value_of("dest-dir") {
- book.config.build.build_dir = dest_dir.into();
+ if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") {
+ book.config.build.build_dir = dest_dir.to_path_buf();
}
-
- book.test(library_paths)?;
+ match chapter {
+ Some(_) => book.test_chapter(library_paths, chapter),
+ None => book.test(library_paths),
+ }?;
Ok(())
}
diff --git a/vendor/mdbook/src/cmd/watch.rs b/vendor/mdbook/src/cmd/watch.rs
index 9336af779..bbc6bde71 100644
--- a/vendor/mdbook/src/cmd/watch.rs
+++ b/vendor/mdbook/src/cmd/watch.rs
@@ -1,34 +1,20 @@
+use super::command_prelude::*;
use crate::{get_book_dir, open};
-use clap::{arg, App, Arg, ArgMatches};
use mdbook::errors::Result;
use mdbook::utils;
use mdbook::MDBook;
-use notify::Watcher;
use std::path::{Path, PathBuf};
use std::sync::mpsc::channel;
use std::thread::sleep;
use std::time::Duration;
// Create clap subcommand arguments
-pub fn make_subcommand<'help>() -> App<'help> {
- App::new("watch")
+pub fn make_subcommand() -> Command {
+ Command::new("watch")
.about("Watches a book's files and rebuilds it on changes")
- .arg(
- Arg::new("dest-dir")
- .short('d')
- .long("dest-dir")
- .value_name("dest-dir")
- .help(
- "Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
- ),
- )
- .arg(arg!([dir]
- "Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)"
- ))
- .arg(arg!(-o --open "Opens the compiled book in a web browser"))
+ .arg_dest_dir()
+ .arg_root_dir()
+ .arg_open()
}
// Watch command implementation
@@ -37,13 +23,13 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let mut book = MDBook::load(&book_dir)?;
let update_config = |book: &mut MDBook| {
- if let Some(dest_dir) = args.value_of("dest-dir") {
+ if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") {
book.config.build.build_dir = dest_dir.into();
}
};
update_config(&mut book);
- if args.is_present("open") {
+ if args.get_flag("open") {
book.build()?;
let path = book.build_dir_for("html").join("index.html");
if !path.exists() {
@@ -121,30 +107,42 @@ pub fn trigger_on_change<F>(book: &MDBook, closure: F)
where
F: Fn(Vec<PathBuf>, &Path),
{
- use notify::DebouncedEvent::*;
use notify::RecursiveMode::*;
// Create a channel to receive the events.
let (tx, rx) = channel();
- let mut watcher = match notify::watcher(tx, Duration::from_secs(1)) {
- Ok(w) => w,
+ let mut debouncer = match notify_debouncer_mini::new_debouncer(Duration::from_secs(1), None, tx)
+ {
+ Ok(d) => d,
Err(e) => {
error!("Error while trying to watch the files:\n\n\t{:?}", e);
std::process::exit(1)
}
};
+ let watcher = debouncer.watcher();
// Add the source directory to the watcher
- if let Err(e) = watcher.watch(book.source_dir(), Recursive) {
+ if let Err(e) = watcher.watch(&book.source_dir(), Recursive) {
error!("Error while watching {:?}:\n {:?}", book.source_dir(), e);
std::process::exit(1);
};
- let _ = watcher.watch(book.theme_dir(), Recursive);
+ let _ = watcher.watch(&book.theme_dir(), Recursive);
// Add the book.toml file to the watcher if it exists
- let _ = watcher.watch(book.root.join("book.toml"), NonRecursive);
+ let _ = watcher.watch(&book.root.join("book.toml"), NonRecursive);
+
+ for dir in &book.config.build.extra_watch_dirs {
+ let path = dir.canonicalize().unwrap();
+ if let Err(e) = watcher.watch(&path, Recursive) {
+ error!(
+ "Error while watching extra directory {:?}:\n {:?}",
+ path, e
+ );
+ std::process::exit(1);
+ }
+ }
info!("Listening for changes...");
@@ -155,18 +153,25 @@ where
let all_events = std::iter::once(first_event).chain(other_events);
- let paths = all_events
- .filter_map(|event| {
- debug!("Received filesystem event: {:?}", event);
-
- match event {
- Create(path) | Write(path) | Remove(path) | Rename(_, path) => Some(path),
- _ => None,
+ let paths: Vec<_> = all_events
+ .filter_map(|event| match event {
+ Ok(events) => Some(events),
+ Err(errors) => {
+ for error in errors {
+ log::warn!("error while watching for changes: {error}");
+ }
+ None
}
})
- .collect::<Vec<_>>();
-
- let paths = remove_ignored_files(&book.root, &paths[..]);
+ .flatten()
+ .map(|event| event.path)
+ .collect();
+
+ // If we are watching files outside the current repository (via extra-watch-dirs), then they are definitionally
+ // ignored by gitignore. So we handle this case by including such files into the watched paths list.
+ let any_external_paths = paths.iter().filter(|p| !p.starts_with(&book.root)).cloned();
+ let mut paths = remove_ignored_files(&book.root, &paths[..]);
+ paths.extend(any_external_paths);
if !paths.is_empty() {
closure(paths, &book.root);