Merge pull request #2829 from ehuss/log-to-tracing

Switch from log to tracing
This commit is contained in:
Eric Huss 2025-09-12 13:20:49 +00:00 committed by GitHub
commit 8bb9a7ff42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
46 changed files with 320 additions and 292 deletions

166
Cargo.lock generated
View file

@ -559,29 +559,6 @@ dependencies = [
"serde_json", "serde_json",
] ]
[[package]]
name = "env_filter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"jiff",
"log",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.2" version = "1.0.2"
@ -1132,30 +1109,6 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
dependencies = [
"jiff-static",
"log",
"portable-atomic",
"portable-atomic-util",
"serde",
]
[[package]]
name = "jiff-static"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.104",
]
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.77" version = "0.3.77"
@ -1186,6 +1139,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.174" version = "0.2.174"
@ -1291,6 +1250,15 @@ dependencies = [
"syn 2.0.104", "syn 2.0.104",
] ]
[[package]]
name = "matchers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
dependencies = [
"regex-automata",
]
[[package]] [[package]]
name = "matchit" name = "matchit"
version = "0.8.4" version = "0.8.4"
@ -1306,11 +1274,9 @@ dependencies = [
"chrono", "chrono",
"clap", "clap",
"clap_complete", "clap_complete",
"env_logger",
"futures-util", "futures-util",
"glob", "glob",
"ignore", "ignore",
"log",
"mdbook-core", "mdbook-core",
"mdbook-driver", "mdbook-driver",
"mdbook-html", "mdbook-html",
@ -1331,6 +1297,8 @@ dependencies = [
"tokio", "tokio",
"toml", "toml",
"tower-http", "tower-http",
"tracing",
"tracing-subscriber",
"walkdir", "walkdir",
] ]
@ -1339,12 +1307,12 @@ name = "mdbook-core"
version = "0.5.0-alpha.1" version = "0.5.0-alpha.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"log",
"regex", "regex",
"serde", "serde",
"serde_json", "serde_json",
"tempfile", "tempfile",
"toml", "toml",
"tracing",
] ]
[[package]] [[package]]
@ -1353,7 +1321,6 @@ version = "0.5.0-alpha.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"indexmap", "indexmap",
"log",
"mdbook-core", "mdbook-core",
"mdbook-html", "mdbook-html",
"mdbook-markdown", "mdbook-markdown",
@ -1367,6 +1334,7 @@ dependencies = [
"tempfile", "tempfile",
"toml", "toml",
"topological-sort", "topological-sort",
"tracing",
] ]
[[package]] [[package]]
@ -1379,7 +1347,6 @@ dependencies = [
"font-awesome-as-a-crate", "font-awesome-as-a-crate",
"handlebars", "handlebars",
"hex", "hex",
"log",
"mdbook-core", "mdbook-core",
"mdbook-markdown", "mdbook-markdown",
"mdbook-renderer", "mdbook-renderer",
@ -1391,15 +1358,16 @@ dependencies = [
"sha2", "sha2",
"tempfile", "tempfile",
"toml", "toml",
"tracing",
] ]
[[package]] [[package]]
name = "mdbook-markdown" name = "mdbook-markdown"
version = "0.5.0-alpha.1" version = "0.5.0-alpha.1"
dependencies = [ dependencies = [
"log",
"pulldown-cmark", "pulldown-cmark",
"regex", "regex",
"tracing",
] ]
[[package]] [[package]]
@ -1437,11 +1405,11 @@ name = "mdbook-summary"
version = "0.5.0-alpha.1" version = "0.5.0-alpha.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"log",
"mdbook-core", "mdbook-core",
"memchr", "memchr",
"pulldown-cmark", "pulldown-cmark",
"serde", "serde",
"tracing",
] ]
[[package]] [[package]]
@ -1544,6 +1512,15 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
[[package]]
name = "nu-ansi-term"
version = "0.50.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
dependencies = [
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "num-modular" name = "num-modular"
version = "0.6.1" version = "0.6.1"
@ -1781,21 +1758,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "portable-atomic"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]
[[package]] [[package]]
name = "potential_utf" name = "potential_utf"
version = "0.1.2" version = "0.1.2"
@ -2126,6 +2088,15 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "1.3.0" version = "1.3.0"
@ -2333,6 +2304,15 @@ dependencies = [
"syn 2.0.104", "syn 2.0.104",
] ]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "tinystr" name = "tinystr"
version = "0.8.1" version = "0.8.1"
@ -2504,9 +2484,21 @@ checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [ dependencies = [
"log", "log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes",
"tracing-core", "tracing-core",
] ]
[[package]]
name = "tracing-attributes"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.104",
]
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.34" version = "0.1.34"
@ -2514,6 +2506,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex-automata",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
] ]
[[package]] [[package]]
@ -2598,6 +2620,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.5" version = "0.9.5"

View file

@ -32,7 +32,6 @@ chrono = { version = "0.4.41", default-features = false, features = ["clock"] }
clap = { version = "4.5.41", features = ["cargo", "wrap_help"] } clap = { version = "4.5.41", features = ["cargo", "wrap_help"] }
clap_complete = "4.5.55" clap_complete = "4.5.55"
elasticlunr-rs = "3.0.2" elasticlunr-rs = "3.0.2"
env_logger = "0.11.8"
font-awesome-as-a-crate = "0.3.0" font-awesome-as-a-crate = "0.3.0"
futures-util = "0.3.31" futures-util = "0.3.31"
glob = "0.3.3" glob = "0.3.3"
@ -40,7 +39,6 @@ handlebars = "6.3.2"
hex = "0.4.3" hex = "0.4.3"
indexmap = "2.10.0" indexmap = "2.10.0"
ignore = "0.4.23" ignore = "0.4.23"
log = "0.4.27"
mdbook-core = { path = "crates/mdbook-core" } mdbook-core = { path = "crates/mdbook-core" }
mdbook-driver = { path = "crates/mdbook-driver" } mdbook-driver = { path = "crates/mdbook-driver" }
mdbook-html = { path = "crates/mdbook-html" } mdbook-html = { path = "crates/mdbook-html" }
@ -68,6 +66,8 @@ tokio = "1.46.1"
toml = "0.9.2" toml = "0.9.2"
topological-sort = "0.2.2" topological-sort = "0.2.2"
tower-http = "0.6.6" tower-http = "0.6.6"
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
walkdir = "2.5.0" walkdir = "2.5.0"
[package] [package]
@ -93,8 +93,6 @@ anyhow.workspace = true
chrono.workspace = true chrono.workspace = true
clap.workspace = true clap.workspace = true
clap_complete.workspace = true clap_complete.workspace = true
env_logger.workspace = true
log.workspace = true
mdbook-core.workspace = true mdbook-core.workspace = true
mdbook-driver.workspace = true mdbook-driver.workspace = true
mdbook-html.workspace = true mdbook-html.workspace = true
@ -104,6 +102,8 @@ mdbook-renderer.workspace = true
mdbook-summary.workspace = true mdbook-summary.workspace = true
opener.workspace = true opener.workspace = true
toml.workspace = true toml.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
# Watch feature # Watch feature
ignore = { workspace = true, optional = true } ignore = { workspace = true, optional = true }

View file

@ -9,11 +9,11 @@ rust-version.workspace = true
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
log.workspace = true
regex.workspace = true regex.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
toml.workspace = true toml.workspace = true
tracing.workspace = true
[dev-dependencies] [dev-dependencies]
tempfile.workspace = true tempfile.workspace = true

View file

@ -46,7 +46,6 @@
use crate::utils::TomlExt; use crate::utils::TomlExt;
use crate::utils::log_backtrace; use crate::utils::log_backtrace;
use anyhow::{Context, Error, Result, bail}; use anyhow::{Context, Error, Result, bail};
use log::{debug, trace};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::env; use std::env;
@ -56,6 +55,7 @@ use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use toml::Value; use toml::Value;
use toml::value::Table; use toml::value::Table;
use tracing::{debug, trace};
/// The overall configuration object for MDBook, essentially an in-memory /// The overall configuration object for MDBook, essentially an in-memory
/// representation of `book.toml`. /// representation of `book.toml`.
@ -162,6 +162,10 @@ impl Config {
env::vars().filter_map(|(key, value)| parse_env(&key).map(|index| (index, value))); env::vars().filter_map(|(key, value)| parse_env(&key).map(|index| (index, value)));
for (key, value) in overrides { for (key, value) in overrides {
if key == "log" {
// MDBOOK_LOG is used to control logging.
continue;
}
trace!("{} => {}", key, value); trace!("{} => {}", key, value);
let parsed_value = serde_json::from_str(&value) let parsed_value = serde_json::from_str(&value)
.unwrap_or_else(|_| serde_json::Value::String(value.to_string())); .unwrap_or_else(|_| serde_json::Value::String(value.to_string()));

View file

@ -1,10 +1,10 @@
//! Filesystem utilities and helpers. //! Filesystem utilities and helpers.
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use log::{debug, trace};
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::Write; use std::io::Write;
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use tracing::{debug, trace};
/// Naively replaces any path separator with a forward-slash '/' /// Naively replaces any path separator with a forward-slash '/'
pub fn normalize_path(path: &str) -> String { pub fn normalize_path(path: &str) -> String {

View file

@ -1,11 +1,12 @@
//! Various helpers and utilities. //! Various helpers and utilities.
use anyhow::Error; use anyhow::Error;
use log::error;
use regex::Regex; use regex::Regex;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Write;
use std::sync::LazyLock; use std::sync::LazyLock;
use tracing::error;
pub mod fs; pub mod fs;
mod string; mod string;
@ -79,11 +80,13 @@ pub fn unique_id_from_content(content: &str, id_counter: &mut HashMap<String, us
/// Prints a "backtrace" of some `Error`. /// Prints a "backtrace" of some `Error`.
pub fn log_backtrace(e: &Error) { pub fn log_backtrace(e: &Error) {
error!("Error: {}", e); let mut message = format!("{e}");
for cause in e.chain().skip(1) { for cause in e.chain().skip(1) {
error!("\tCaused By: {}", cause); write!(message, "\n\tCaused by: {cause}").unwrap();
} }
error!("{message}");
} }
/// Escape `<` and `>` for HTML. /// Escape `<` and `>` for HTML.

View file

@ -10,7 +10,6 @@ rust-version.workspace = true
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
indexmap.workspace = true indexmap.workspace = true
log.workspace = true
mdbook-core.workspace = true mdbook-core.workspace = true
mdbook-html.workspace = true mdbook-html.workspace = true
mdbook-markdown.workspace = true mdbook-markdown.workspace = true
@ -24,6 +23,7 @@ shlex.workspace = true
tempfile.workspace = true tempfile.workspace = true
toml.workspace = true toml.workspace = true
topological-sort.workspace = true topological-sort.workspace = true
tracing.workspace = true
[lints] [lints]
workspace = true workspace = true

View file

@ -1,10 +1,10 @@
use anyhow::{Context, Result, ensure}; use anyhow::{Context, Result, ensure};
use log::{debug, trace, warn};
use mdbook_core::book::Book; use mdbook_core::book::Book;
use mdbook_preprocessor::{Preprocessor, PreprocessorContext}; use mdbook_preprocessor::{Preprocessor, PreprocessorContext};
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::{Child, Stdio}; use std::process::{Child, Stdio};
use tracing::{debug, trace, warn};
/// A custom preprocessor which will shell out to a 3rd-party program. /// A custom preprocessor which will shell out to a 3rd-party program.
/// ///

View file

@ -1,9 +1,9 @@
use anyhow::Result; use anyhow::Result;
use log::warn;
use mdbook_core::book::{Book, BookItem}; use mdbook_core::book::{Book, BookItem};
use mdbook_preprocessor::{Preprocessor, PreprocessorContext}; use mdbook_preprocessor::{Preprocessor, PreprocessorContext};
use regex::Regex; use regex::Regex;
use std::{path::Path, sync::LazyLock}; use std::{path::Path, sync::LazyLock};
use tracing::warn;
/// A preprocessor for converting file name `README.md` to `index.md` since /// A preprocessor for converting file name `README.md` to `index.md` since
/// `README.md` is the de facto index file in markdown-based documentation. /// `README.md` is the de facto index file in markdown-based documentation.

View file

@ -1,5 +1,4 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use log::{error, warn};
use mdbook_core::book::{Book, BookItem}; use mdbook_core::book::{Book, BookItem};
use mdbook_core::utils::{ use mdbook_core::utils::{
take_anchored_lines, take_lines, take_rustdoc_include_anchored_lines, take_anchored_lines, take_lines, take_rustdoc_include_anchored_lines,
@ -11,6 +10,7 @@ use std::fs;
use std::ops::{Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeTo}; use std::ops::{Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeTo};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::LazyLock; use std::sync::LazyLock;
use tracing::{error, warn};
const ESCAPE_CHAR: char = '\\'; const ESCAPE_CHAR: char = '\\';
const MAX_LINK_NESTED_DEPTH: usize = 10; const MAX_LINK_NESTED_DEPTH: usize = 10;

View file

@ -1,9 +1,9 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use log::trace;
use mdbook_core::book::BookItem; use mdbook_core::book::BookItem;
use mdbook_core::utils; use mdbook_core::utils;
use mdbook_renderer::{RenderContext, Renderer}; use mdbook_renderer::{RenderContext, Renderer};
use std::fs; use std::fs;
use tracing::trace;
/// A renderer to output the Markdown after the preprocessors have run. Mostly useful /// A renderer to output the Markdown after the preprocessors have run. Mostly useful
/// when debugging preprocessors. /// when debugging preprocessors.

View file

@ -3,10 +3,10 @@
//! The HTML renderer can be found in the [`mdbook_html`] crate. //! The HTML renderer can be found in the [`mdbook_html`] crate.
use anyhow::{Context, Result, bail}; use anyhow::{Context, Result, bail};
use log::{error, info, trace, warn};
use mdbook_renderer::{RenderContext, Renderer}; use mdbook_renderer::{RenderContext, Renderer};
use std::fs; use std::fs;
use std::process::Stdio; use std::process::Stdio;
use tracing::{error, info, trace, warn};
pub use self::markdown_renderer::MarkdownRenderer; pub use self::markdown_renderer::MarkdownRenderer;
@ -30,7 +30,7 @@ mod markdown_renderer;
/// whatever it wants, to avoid spamming users it is recommended to avoid /// whatever it wants, to avoid spamming users it is recommended to avoid
/// unnecessary output. /// unnecessary output.
/// ///
/// To help choose the appropriate output level, the `RUST_LOG` environment /// To help choose the appropriate output level, the `MDBOOK_LOG` environment
/// variable will be passed through to the subprocess, if set. /// variable will be passed through to the subprocess, if set.
/// ///
/// If the subprocess wishes to indicate that rendering failed, it should exit /// If the subprocess wishes to indicate that rendering failed, it should exit

View file

@ -6,10 +6,10 @@ use std::path::PathBuf;
use super::MDBook; use super::MDBook;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use log::{debug, error, info, trace};
use mdbook_core::config::Config; use mdbook_core::config::Config;
use mdbook_core::utils::fs::write_file; use mdbook_core::utils::fs::write_file;
use mdbook_html::theme; use mdbook_html::theme;
use tracing::{debug, error, info, trace};
/// A helper for setting up a new book and its directory structure. /// A helper for setting up a new book and its directory structure.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]

View file

@ -65,12 +65,12 @@ mod load;
mod mdbook; mod mdbook;
use anyhow::{Context, Result, bail}; use anyhow::{Context, Result, bail};
use log::{error, warn};
pub use mdbook::MDBook; pub use mdbook::MDBook;
pub use mdbook_core::{book, config, errors}; pub use mdbook_core::{book, config, errors};
use shlex::Shlex; use shlex::Shlex;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use tracing::{error, warn};
/// Creates a [`Command`] for command renderers and preprocessors. /// Creates a [`Command`] for command renderers and preprocessors.
fn compose_command(cmd: &str, root: &Path) -> Result<Command> { fn compose_command(cmd: &str, root: &Path) -> Result<Command> {

View file

@ -1,5 +1,4 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use log::debug;
use mdbook_core::book::{Book, BookItem, Chapter}; use mdbook_core::book::{Book, BookItem, Chapter};
use mdbook_core::config::BuildConfig; use mdbook_core::config::BuildConfig;
use mdbook_core::utils::bracket_escape; use mdbook_core::utils::bracket_escape;
@ -7,6 +6,7 @@ use mdbook_summary::{Link, Summary, SummaryItem, parse_summary};
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::Path; use std::path::Path;
use tracing::debug;
/// Load a book into memory from its `src/` directory. /// Load a book into memory from its `src/` directory.
pub(crate) fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book> { pub(crate) fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book> {

View file

@ -6,7 +6,6 @@ use crate::init::BookBuilder;
use crate::load::{load_book, load_book_from_disk}; use crate::load::{load_book, load_book_from_disk};
use anyhow::{Context, Error, Result, bail}; use anyhow::{Context, Error, Result, bail};
use indexmap::IndexMap; use indexmap::IndexMap;
use log::{debug, error, info, log_enabled, trace, warn};
use mdbook_core::book::{Book, BookItem, BookItems}; use mdbook_core::book::{Book, BookItem, BookItems};
use mdbook_core::config::{Config, RustEdition}; use mdbook_core::config::{Config, RustEdition};
use mdbook_core::utils; use mdbook_core::utils;
@ -21,6 +20,7 @@ use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use tempfile::Builder as TempFileBuilder; use tempfile::Builder as TempFileBuilder;
use topological_sort::TopologicalSort; use topological_sort::TopologicalSort;
use tracing::{debug, error, info, trace, warn};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -58,7 +58,7 @@ impl MDBook {
config.update_from_env(); config.update_from_env();
if log_enabled!(log::Level::Trace) { if tracing::enabled!(tracing::Level::TRACE) {
for line in format!("Config: {config:#?}").lines() { for line in format!("Config: {config:#?}").lines() {
trace!("{}", line); trace!("{}", line);
} }

View file

@ -14,7 +14,6 @@ elasticlunr-rs = { workspace = true, optional = true }
font-awesome-as-a-crate.workspace = true font-awesome-as-a-crate.workspace = true
handlebars.workspace = true handlebars.workspace = true
hex.workspace = true hex.workspace = true
log.workspace = true
mdbook-core.workspace = true mdbook-core.workspace = true
mdbook-markdown.workspace = true mdbook-markdown.workspace = true
mdbook-renderer.workspace = true mdbook-renderer.workspace = true
@ -23,6 +22,7 @@ regex.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
sha2.workspace = true sha2.workspace = true
tracing.workspace = true
[dev-dependencies] [dev-dependencies]
pretty_assertions.workspace = true pretty_assertions.workspace = true

View file

@ -3,7 +3,6 @@ use super::static_files::StaticFiles;
use crate::theme::Theme; use crate::theme::Theme;
use anyhow::{Context, Result, bail}; use anyhow::{Context, Result, bail};
use handlebars::Handlebars; use handlebars::Handlebars;
use log::{debug, info, trace, warn};
use mdbook_core::book::{Book, BookItem, Chapter}; use mdbook_core::book::{Book, BookItem, Chapter};
use mdbook_core::config::{BookConfig, Code, Config, HtmlConfig, Playground, RustEdition}; use mdbook_core::config::{BookConfig, Code, Config, HtmlConfig, Playground, RustEdition};
use mdbook_core::utils; use mdbook_core::utils;
@ -18,6 +17,8 @@ use std::collections::HashMap;
use std::fs::{self, File}; use std::fs::{self, File};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::LazyLock; use std::sync::LazyLock;
use tracing::error;
use tracing::{debug, info, trace, warn};
/// The HTML renderer for mdBook. /// The HTML renderer for mdBook.
#[derive(Default)] #[derive(Default)]
@ -286,7 +287,7 @@ impl HtmlHandlebars {
return Ok(()); return Ok(());
} }
log::debug!("Emitting redirects"); debug!("Emitting redirects");
let redirects = combine_fragment_redirects(redirects); let redirects = combine_fragment_redirects(redirects);
for (original, (dest, fragment_map)) in redirects { for (original, (dest, fragment_map)) in redirects {
@ -306,7 +307,7 @@ impl HtmlHandlebars {
destination." destination."
); );
} }
log::debug!("Redirecting \"{}\"\"{}\"", original, dest); debug!("Redirecting \"{}\"\"{}\"", original, dest);
self.emit_redirect(handlebars, &filename, &dest, &fragment_map)?; self.emit_redirect(handlebars, &filename, &dest, &fragment_map)?;
} }
@ -1034,7 +1035,7 @@ fn combine_fragment_redirects(redirects: &HashMap<String, String>) -> CombinedRe
if let Some((source_path, source_fragment)) = original.rsplit_once('#') { if let Some((source_path, source_fragment)) = original.rsplit_once('#') {
let e = combined.entry(source_path.to_string()).or_default(); let e = combined.entry(source_path.to_string()).or_default();
if let Some(old) = e.1.insert(format!("#{source_fragment}"), new.clone()) { if let Some(old) = e.1.insert(format!("#{source_fragment}"), new.clone()) {
log::error!( error!(
"internal error: found duplicate fragment redirect \ "internal error: found duplicate fragment redirect \
{old} for {source_path}#{source_fragment}" {old} for {source_path}#{source_fragment}"
); );

View file

@ -2,8 +2,8 @@ use font_awesome_as_a_crate as fa;
use handlebars::{ use handlebars::{
Context, Handlebars, Helper, Output, RenderContext, RenderError, RenderErrorReason, Context, Handlebars, Helper, Output, RenderContext, RenderError, RenderErrorReason,
}; };
use log::trace;
use std::str::FromStr; use std::str::FromStr;
use tracing::trace;
pub(crate) fn fa_helper( pub(crate) fn fa_helper(
h: &Helper<'_>, h: &Helper<'_>,

View file

@ -2,7 +2,6 @@ use super::static_files::StaticFiles;
use crate::theme::searcher; use crate::theme::searcher;
use anyhow::{Context, Result, bail}; use anyhow::{Context, Result, bail};
use elasticlunr::{Index, IndexBuilder}; use elasticlunr::{Index, IndexBuilder};
use log::{debug, warn};
use mdbook_core::book::{Book, BookItem, Chapter}; use mdbook_core::book::{Book, BookItem, Chapter};
use mdbook_core::config::{Search, SearchChapterSettings}; use mdbook_core::config::{Search, SearchChapterSettings};
use mdbook_core::utils; use mdbook_core::utils;
@ -14,6 +13,7 @@ use std::borrow::Cow;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::LazyLock; use std::sync::LazyLock;
use tracing::{debug, warn};
const MAX_WORD_LENGTH_TO_INDEX: usize = 80; const MAX_WORD_LENGTH_TO_INDEX: usize = 80;

View file

@ -3,7 +3,6 @@
use super::helpers::resources::ResourceHelper; use super::helpers::resources::ResourceHelper;
use crate::theme::{self, Theme, playground_editor}; use crate::theme::{self, Theme, playground_editor};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use log::debug;
use mdbook_core::config::HtmlConfig; use mdbook_core::config::HtmlConfig;
use mdbook_core::utils; use mdbook_core::utils;
use std::borrow::Cow; use std::borrow::Cow;
@ -11,6 +10,7 @@ use std::collections::HashMap;
use std::fs::{self, File}; use std::fs::{self, File};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::LazyLock; use std::sync::LazyLock;
use tracing::debug;
/// Map static files to their final names and contents. /// Map static files to their final names and contents.
/// ///

View file

@ -1,10 +1,10 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use anyhow::Result; use anyhow::Result;
use log::warn;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tracing::{info, warn};
pub mod fonts; pub mod fonts;
pub mod playground_editor; pub mod playground_editor;
@ -133,7 +133,7 @@ impl Theme {
if entry.file_name() == "fonts.css" { if entry.file_name() == "fonts.css" {
None None
} else if entry.file_type().ok()?.is_dir() { } else if entry.file_type().ok()?.is_dir() {
log::info!("skipping font directory {:?}", entry.path()); info!("skipping font directory {:?}", entry.path());
None None
} else { } else {
Some(entry.path()) Some(entry.path())

View file

@ -8,9 +8,9 @@ repository.workspace = true
rust-version.workspace = true rust-version.workspace = true
[dependencies] [dependencies]
log.workspace = true
pulldown-cmark.workspace = true pulldown-cmark.workspace = true
regex.workspace = true regex.workspace = true
tracing.workspace = true
[lints] [lints]
workspace = true workspace = true

View file

@ -15,6 +15,7 @@ use std::collections::HashMap;
use std::fmt::Write; use std::fmt::Write;
use std::path::Path; use std::path::Path;
use std::sync::LazyLock; use std::sync::LazyLock;
use tracing::warn;
#[doc(inline)] #[doc(inline)]
pub use pulldown_cmark; pub use pulldown_cmark;
@ -126,7 +127,7 @@ pub fn render_markdown(text: &str, options: &HtmlRenderOptions<'_>) -> String {
Event::Start(Tag::FootnoteDefinition(name)) => { Event::Start(Tag::FootnoteDefinition(name)) => {
prev_was_footnote = false; prev_was_footnote = false;
if !in_footnote.is_empty() { if !in_footnote.is_empty() {
log::warn!( warn!(
"internal bug: nested footnote not expected in {:?}", "internal bug: nested footnote not expected in {:?}",
options.path options.path
); );
@ -139,7 +140,7 @@ pub fn render_markdown(text: &str, options: &HtmlRenderOptions<'_>) -> String {
let name = std::mem::take(&mut in_footnote_name); let name = std::mem::take(&mut in_footnote_name);
if footnote_defs.contains_key(&name) { if footnote_defs.contains_key(&name) {
log::warn!( warn!(
"footnote `{name}` in {} defined multiple times - \ "footnote `{name}` in {} defined multiple times - \
not updating to new definition", not updating to new definition",
options.path.display() options.path.display()
@ -212,7 +213,7 @@ fn add_footnote_defs(
// Remove unused. // Remove unused.
defs.retain(|(name, _)| { defs.retain(|(name, _)| {
if !numbers.contains_key(name) { if !numbers.contains_key(name) {
log::warn!( warn!(
"footnote `{name}` in `{}` is defined but not referenced", "footnote `{name}` in `{}` is defined but not referenced",
options.path.display() options.path.display()
); );

View file

@ -9,11 +9,11 @@ rust-version.workspace = true
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
log.workspace = true
mdbook-core.workspace = true mdbook-core.workspace = true
memchr.workspace = true memchr.workspace = true
pulldown-cmark.workspace = true pulldown-cmark.workspace = true
serde.workspace = true serde.workspace = true
tracing.workspace = true
[lints] [lints]
workspace = true workspace = true

View file

@ -5,7 +5,6 @@
//! file structure for [mdBook](https://rust-lang.github.io/mdBook/). //! file structure for [mdBook](https://rust-lang.github.io/mdBook/).
use anyhow::{Context, Error, Result, bail}; use anyhow::{Context, Error, Result, bail};
use log::{debug, trace, warn};
pub use mdbook_core::book::SectionNumber; pub use mdbook_core::book::SectionNumber;
use memchr::Memchr; use memchr::Memchr;
use pulldown_cmark::{DefaultBrokenLinkCallback, Event, HeadingLevel, Tag, TagEnd}; use pulldown_cmark::{DefaultBrokenLinkCallback, Event, HeadingLevel, Tag, TagEnd};
@ -13,6 +12,7 @@ use serde::{Deserialize, Serialize};
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt::Display; use std::fmt::Display;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tracing::{debug, trace, warn};
/// Parse the text from a `SUMMARY.md` file into a sort of "recipe" to be /// Parse the text from a `SUMMARY.md` file into a sort of "recipe" to be
/// used when loading a book from disk. /// used when loading a book from disk.

View file

@ -317,7 +317,7 @@ the "rule of silence" and only generate output when necessary (e.g. an error in
generation or a warning). generation or a warning).
All environment variables are passed through to the backend, allowing you to use All environment variables are passed through to the backend, allowing you to use
the usual `RUST_LOG` to control logging verbosity. the usual `MDBOOK_LOG` to control logging verbosity.
## Wrapping up ## Wrapping up

View file

@ -2,6 +2,7 @@ use super::command_prelude::*;
use crate::{get_book_dir, open}; use crate::{get_book_dir, open};
use anyhow::Result; use anyhow::Result;
use mdbook_driver::MDBook; use mdbook_driver::MDBook;
use tracing::error;
// Create clap subcommand arguments // Create clap subcommand arguments
pub fn make_subcommand() -> Command { pub fn make_subcommand() -> Command {

View file

@ -6,6 +6,7 @@ use mdbook_driver::MDBook;
use std::io; use std::io;
use std::io::Write; use std::io::Write;
use std::process::Command; use std::process::Command;
use tracing::debug;
// Create clap subcommand arguments // Create clap subcommand arguments
pub fn make_subcommand() -> ClapCommand { pub fn make_subcommand() -> ClapCommand {

View file

@ -15,6 +15,7 @@ use std::net::{SocketAddr, ToSocketAddrs};
use std::path::PathBuf; use std::path::PathBuf;
use tokio::sync::broadcast; use tokio::sync::broadcast;
use tower_http::services::{ServeDir, ServeFile}; use tower_http::services::{ServeDir, ServeFile};
use tracing::{error, info, trace};
/// The HTTP endpoint for the websocket used to trigger reloads when a file changes. /// The HTTP endpoint for the websocket used to trigger reloads when a file changes.
const LIVE_RELOAD_ENDPOINT: &str = "__livereload"; const LIVE_RELOAD_ENDPOINT: &str = "__livereload";

View file

@ -3,6 +3,7 @@ use crate::{get_book_dir, open};
use anyhow::Result; use anyhow::Result;
use mdbook_driver::MDBook; use mdbook_driver::MDBook;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tracing::error;
mod native; mod native;
mod poller; mod poller;

View file

@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use tracing::{error, info, warn};
pub fn rebuild_on_change( pub fn rebuild_on_change(
book_dir: &Path, book_dir: &Path,
@ -71,7 +72,7 @@ pub fn rebuild_on_change(
.filter_map(|event| match event { .filter_map(|event| match event {
Ok(events) => Some(events), Ok(events) => Some(events),
Err(error) => { Err(error) => {
log::warn!("error while watching for changes: {error}"); warn!("error while watching for changes: {error}");
None None
} }
}) })

View file

@ -11,6 +11,7 @@ use std::collections::HashMap;
use std::fs::FileType; use std::fs::FileType;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::{Duration, Instant, SystemTime}; use std::time::{Duration, Instant, SystemTime};
use tracing::{debug, error, info, trace, warn};
use walkdir::WalkDir; use walkdir::WalkDir;
/// Calls the closure when a book source file is changed, blocking indefinitely. /// Calls the closure when a book source file is changed, blocking indefinitely.

View file

@ -4,20 +4,15 @@
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;
#[macro_use]
extern crate log;
use anyhow::anyhow; use anyhow::anyhow;
use chrono::Local;
use clap::{Arg, ArgMatches, Command}; use clap::{Arg, ArgMatches, Command};
use clap_complete::Shell; use clap_complete::Shell;
use env_logger::Builder;
use log::LevelFilter;
use mdbook_core::utils; use mdbook_core::utils;
use std::env; use std::env;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use tracing::{error, info};
mod cmd; mod cmd;
@ -99,29 +94,36 @@ fn create_clap_command() -> Command {
} }
fn init_logger() { fn init_logger() {
let mut builder = Builder::new(); let filter = tracing_subscriber::EnvFilter::builder()
.with_env_var("MDBOOK_LOG")
.with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into())
.from_env_lossy();
let log_env = std::env::var("MDBOOK_LOG");
// Silence some particularly noisy dependencies unless the user
// specifically asks for them.
let silence_unless_specified = |filter: tracing_subscriber::EnvFilter, target| {
if !log_env.as_ref().map_or(false, |s| {
s.split(',').any(|directive| directive.starts_with(target))
}) {
filter.add_directive(format!("{target}=warn").parse().unwrap())
} else {
filter
}
};
let filter = silence_unless_specified(filter, "handlebars");
let filter = silence_unless_specified(filter, "html5ever");
builder.format(|formatter, record| { // Don't show the target by default, since it generally isn't useful
writeln!( // unless you are overriding the level.
formatter, let with_target = log_env.is_ok();
"{} [{}] ({}): {}",
Local::now().format("%Y-%m-%d %H:%M:%S"),
record.level(),
record.target(),
record.args()
)
});
if let Ok(var) = env::var("RUST_LOG") { tracing_subscriber::fmt()
builder.parse_filters(&var); .without_time()
} else { .with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))
// if no RUST_LOG provided, default to logging at the Info level .with_writer(std::io::stderr)
builder.filter(None, LevelFilter::Info); .with_env_filter(filter)
// Filter extraneous html5ever not-implemented messages .with_target(with_target)
builder.filter(Some("html5ever"), LevelFilter::Error); .init();
}
builder.init();
} }
fn get_book_dir(args: &ArgMatches) -> PathBuf { fn get_book_dir(args: &ArgMatches) -> PathBuf {

View file

@ -360,7 +360,7 @@ impl BookCommand {
/// Use this to debug a command. /// Use this to debug a command.
/// ///
/// Pass the value that you would normally pass to `RUST_LOG`, and this /// Pass the value that you would normally pass to `MDBOOK_LOG`, and this
/// will enable logging, print the command that runs and its output. /// will enable logging, print the command that runs and its output.
/// ///
/// This will fail if you use it in CI. /// This will fail if you use it in CI.
@ -378,7 +378,7 @@ impl BookCommand {
let mut cmd = Command::new(env!("CARGO_BIN_EXE_mdbook")); let mut cmd = Command::new(env!("CARGO_BIN_EXE_mdbook"));
cmd.current_dir(&self.dir) cmd.current_dir(&self.dir)
.args(&self.args) .args(&self.args)
.env_remove("RUST_LOG") .env_remove("MDBOOK_LOG")
// Don't read the system git config which is out of our control. // Don't read the system git config which is out of our control.
.env("GIT_CONFIG_NOSYSTEM", "1") .env("GIT_CONFIG_NOSYSTEM", "1")
.env("GIT_CONFIG_GLOBAL", &self.dir) .env("GIT_CONFIG_GLOBAL", &self.dir)
@ -389,7 +389,7 @@ impl BookCommand {
.env_remove("GIT_COMMITTER_NAME"); .env_remove("GIT_COMMITTER_NAME");
if let Some(debug) = &self.debug { if let Some(debug) = &self.debug {
cmd.env("RUST_LOG", debug); cmd.env("MDBOOK_LOG", debug);
} }
for (k, v) in &self.env { for (k, v) in &self.env {
@ -479,23 +479,9 @@ static LITERAL_REDACTIONS: &[(&str, &str)] = &[
("[EXE]", std::env::consts::EXE_SUFFIX), ("[EXE]", std::env::consts::EXE_SUFFIX),
]; ];
/// This makes it easier to write regex replacements that are guaranteed to only
/// get compiled once
macro_rules! regex {
($re:literal $(,)?) => {{
static RE: std::sync::OnceLock<regex::Regex> = std::sync::OnceLock::new();
RE.get_or_init(|| regex::Regex::new($re).unwrap())
}};
}
fn assert(root: &Path) -> snapbox::Assert { fn assert(root: &Path) -> snapbox::Assert {
let mut subs = snapbox::Redactions::new(); let mut subs = snapbox::Redactions::new();
subs.insert("[ROOT]", root.to_path_buf()).unwrap(); subs.insert("[ROOT]", root.to_path_buf()).unwrap();
subs.insert(
"[TIMESTAMP]",
regex!(r"(?m)(?<redacted>20\d\d-\d{2}-\d{2} \d{2}:\d{2}:\d{2})"),
)
.unwrap();
subs.insert("[VERSION]", mdbook_core::MDBOOK_VERSION) subs.insert("[VERSION]", mdbook_core::MDBOOK_VERSION)
.unwrap(); .unwrap();

View file

@ -10,9 +10,9 @@ use crate::prelude::*;
fn basic_build() { fn basic_build() {
BookTest::from_dir("build/basic_build").run("build", |cmd| { BookTest::from_dir("build/basic_build").run("build", |cmd| {
cmd.expect_stderr(str![[r#" cmd.expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}); });
@ -24,8 +24,8 @@ fn basic_build() {
fn failure_on_missing_file() { fn failure_on_missing_file() {
BookTest::from_dir("build/missing_file").run("build", |cmd| { BookTest::from_dir("build/missing_file").run("build", |cmd| {
cmd.expect_failure().expect_stderr(str![[r#" cmd.expect_failure().expect_stderr(str![[r#"
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Chapter file not found, ./chapter_1.md ERROR Chapter file not found, ./chapter_1.md
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: [NOT_FOUND] [TAB]Caused by: [NOT_FOUND]
"#]]); "#]]);
}); });
@ -46,10 +46,10 @@ fn create_missing() {
fn no_reserved_filename() { fn no_reserved_filename() {
BookTest::from_dir("build/no_reserved_filename").run("build", |cmd| { BookTest::from_dir("build/no_reserved_filename").run("build", |cmd| {
cmd.expect_failure().expect_stderr(str![[r#" cmd.expect_failure().expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Rendering failed ERROR Rendering failed
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: print.md is reserved for internal use [TAB]Caused by: print.md is reserved for internal use
"#]]); "#]]);
}); });
@ -77,9 +77,9 @@ fn dest_dir_relative_path() {
cmd.args(&["--dest-dir", "foo", ".."]) cmd.args(&["--dest-dir", "foo", ".."])
.current_dir(&current_dir) .current_dir(&current_dir)
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/work/foo` INFO HTML book written to `[ROOT]/work/foo`
"#]]); "#]]);
}); });

View file

@ -120,8 +120,8 @@ fn bad_config_top_level() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Invalid configuration file ERROR Invalid configuration file
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: TOML parse error at line 1, column 1 [TAB]Caused by: TOML parse error at line 1, column 1
| |
1 | foo = 123 1 | foo = 123
| ^^^ | ^^^
@ -145,8 +145,8 @@ fn bad_config_top_level_table() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Invalid configuration file ERROR Invalid configuration file
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: TOML parse error at line 1, column 2 [TAB]Caused by: TOML parse error at line 1, column 2
| |
1 | [other] 1 | [other]
| ^^^^^ | ^^^^^
@ -171,8 +171,8 @@ fn bad_config_in_book_table() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Invalid configuration file ERROR Invalid configuration file
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: TOML parse error at line 3, column 1 [TAB]Caused by: TOML parse error at line 3, column 1
| |
3 | foo = 123 3 | foo = 123
| ^^^ | ^^^
@ -196,8 +196,8 @@ fn bad_config_in_rust_table() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Invalid configuration file ERROR Invalid configuration file
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: TOML parse error at line 2, column 1 [TAB]Caused by: TOML parse error at line 2, column 1
| |
2 | title = "bad-config" 2 | title = "bad-config"
| ^^^^^ | ^^^^^

View file

@ -45,10 +45,10 @@ fn recursive_include() {
BookTest::from_dir("includes/all_includes") BookTest::from_dir("includes/all_includes")
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stderr(str![[r#" cmd.expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [ERROR] (mdbook_driver::builtin_preprocessors::links): Stack depth exceeded in recursive.md. Check for cyclic includes ERROR Stack depth exceeded in recursive.md. Check for cyclic includes
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}) })

View file

@ -19,7 +19,7 @@ All done, no errors...
"#]]) "#]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::init): Creating a new book with stub content INFO Creating a new book with stub content
"#]]); "#]]);
}) })
@ -84,7 +84,7 @@ All done, no errors...
"#]]) "#]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::init): Creating a new book with stub content INFO Creating a new book with stub content
"#]]); "#]]);
}) })
@ -115,7 +115,7 @@ All done, no errors...
"#]]) "#]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::init): Creating a new book with stub content INFO Creating a new book with stub content
"#]]) "#]])
.args(&["--title", "Example title"]); .args(&["--title", "Example title"]);

View file

@ -20,13 +20,13 @@ fn footnotes() {
BookTest::from_dir("markdown/footnotes") BookTest::from_dir("markdown/footnotes")
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stderr(str![[r#" cmd.expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [WARN] (mdbook_markdown): footnote `multiple-definitions` in footnotes.md defined multiple times - not updating to new definition WARN footnote `multiple-definitions` in footnotes.md defined multiple times - not updating to new definition
[TIMESTAMP] [WARN] (mdbook_markdown): footnote `unused` in `footnotes.md` is defined but not referenced WARN footnote `unused` in `footnotes.md` is defined but not referenced
[TIMESTAMP] [WARN] (mdbook_markdown): footnote `multiple-definitions` in footnotes.md defined multiple times - not updating to new definition WARN footnote `multiple-definitions` in footnotes.md defined multiple times - not updating to new definition
[TIMESTAMP] [WARN] (mdbook_markdown): footnote `unused` in `footnotes.md` is defined but not referenced WARN footnote `unused` in `footnotes.md` is defined but not referenced
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}) })

View file

@ -49,9 +49,9 @@ fn runs_preprocessors() {
fn nop_preprocessor() { fn nop_preprocessor() {
BookTest::from_dir("preprocessor/nop_preprocessor").run("build", |cmd| { BookTest::from_dir("preprocessor/nop_preprocessor").run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}); });
@ -60,17 +60,16 @@ fn nop_preprocessor() {
// Failing preprocessor generates an error. // Failing preprocessor generates an error.
#[test] #[test]
fn failing_preprocessor() { fn failing_preprocessor() {
BookTest::from_dir("preprocessor/failing_preprocessor") BookTest::from_dir("preprocessor/failing_preprocessor").run("build", |cmd| {
.run("build", |cmd| { cmd.expect_failure()
cmd.expect_failure() .expect_stdout(str![[""]])
.expect_stdout(str![[""]]) .expect_stderr(str![[r#"
.expect_stderr(str![[r#" INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started
Boom!!1! Boom!!1!
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: The "nop-preprocessor" preprocessor exited unsuccessfully with [EXIT_STATUS]: 1 status ERROR The "nop-preprocessor" preprocessor exited unsuccessfully with [EXIT_STATUS]: 1 status
"#]]); "#]]);
}); });
} }
fn example() -> CmdPreprocessor { fn example() -> CmdPreprocessor {
@ -128,9 +127,9 @@ fn relative_command_path() {
) )
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stdout(str![""]).expect_stderr(str![[r#" cmd.expect_stdout(str![""]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}) })
@ -143,9 +142,9 @@ fn relative_command_path() {
cmd.current_dir(cmd.dir.join("src")) cmd.current_dir(cmd.dir.join("src"))
.expect_stdout(str![""]) .expect_stdout(str![""])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/src/../book` INFO HTML book written to `[ROOT]/src/../book`
"#]]); "#]]);
}) })
@ -160,10 +159,10 @@ fn missing_preprocessor() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [ERROR] (mdbook_driver): The command `trduyvbhijnorgevfuhn` wasn't found, is the `missing` preprocessor installed? If you want to ignore this error when the `missing` preprocessor is not installed, set `optional = true` in the `[preprocessor.missing]` section of the book.toml configuration file. ERROR The command `trduyvbhijnorgevfuhn` wasn't found, is the `missing` preprocessor installed? If you want to ignore this error when the `missing` preprocessor is not installed, set `optional = true` in the `[preprocessor.missing]` section of the book.toml configuration file.
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Unable to run the preprocessor `missing` ERROR Unable to run the preprocessor `missing`
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: [NOT_FOUND] [TAB]Caused by: [NOT_FOUND]
"#]]); "#]]);
}); });
@ -174,10 +173,10 @@ fn missing_preprocessor() {
fn missing_optional_not_fatal() { fn missing_optional_not_fatal() {
BookTest::from_dir("preprocessor/missing_optional_not_fatal").run("build", |cmd| { BookTest::from_dir("preprocessor/missing_optional_not_fatal").run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [WARN] (mdbook_driver): The command `trduyvbhijnorgevfuhn` for preprocessor `missing` was not found, but is marked as optional. WARN The command `trduyvbhijnorgevfuhn` for preprocessor `missing` was not found, but is marked as optional.
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}); });
@ -239,14 +238,14 @@ fn extension_compatibility() {
// that the built book is identical with the preprocessor enabled. // that the built book is identical with the preprocessor enabled.
test.run("build", |cmd| { test.run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [WARN] (mdbook_driver): The command `./my-preprocessor` for preprocessor `my-preprocessor` was not found, but is marked as optional. WARN The command `./my-preprocessor` for preprocessor `my-preprocessor` was not found, but is marked as optional.
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book/html` INFO HTML book written to `[ROOT]/book/html`
[TIMESTAMP] [WARN] (mdbook_driver): The command `./my-preprocessor` for preprocessor `my-preprocessor` was not found, but is marked as optional. WARN The command `./my-preprocessor` for preprocessor `my-preprocessor` was not found, but is marked as optional.
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the my-renderer backend INFO Running the my-renderer backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "my-renderer" renderer INFO Invoking the "my-renderer" renderer
[TIMESTAMP] [WARN] (mdbook_driver): The command `./my-renderer` for backend `my-renderer` was not found, but is marked as optional. WARN The command `./my-renderer` for backend `my-renderer` was not found, but is marked as optional.
"#]]); "#]]);
}); });
@ -441,11 +440,11 @@ fn extension_compatibility() {
) )
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book/html` INFO HTML book written to `[ROOT]/book/html`
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the my-renderer backend INFO Running the my-renderer backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "my-renderer" renderer INFO Invoking the "my-renderer" renderer
"#]]); "#]]);
}) })

View file

@ -22,11 +22,11 @@ fn redirects_are_emitted_correctly() {
fn redirect_removed_with_fragments_only() { fn redirect_removed_with_fragments_only() {
BookTest::from_dir("redirects/redirect_removed_with_fragments_only").run("build", |cmd| { BookTest::from_dir("redirects/redirect_removed_with_fragments_only").run("build", |cmd| {
cmd.expect_failure().expect_stderr(str![[r#" cmd.expect_failure().expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Rendering failed ERROR Rendering failed
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: Unable to emit redirects [TAB]Caused by: Unable to emit redirects
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: redirect entry for `old-file.html` only has source paths with `#` fragments [TAB]Caused by: redirect entry for `old-file.html` only has source paths with `#` fragments
There must be an entry without the `#` fragment to determine the default destination. There must be an entry without the `#` fragment to determine the default destination.
"#]]); "#]]);
@ -38,10 +38,10 @@ There must be an entry without the `#` fragment to determine the default destina
fn redirect_existing_page() { fn redirect_existing_page() {
BookTest::from_dir("redirects/redirect_existing_page").run("build", |cmd| { BookTest::from_dir("redirects/redirect_existing_page").run("build", |cmd| {
cmd.expect_failure().expect_stderr(str![[r#" cmd.expect_failure().expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Rendering failed ERROR Rendering failed
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: redirect found for existing chapter at `/chapter_1.html` [TAB]Caused by: redirect found for existing chapter at `/chapter_1.html`
Either delete the redirect or remove the chapter. Either delete the redirect or remove the chapter.
"#]]); "#]]);

View file

@ -64,12 +64,12 @@ fn failing_command() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the failing backend INFO Running the failing backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "failing" renderer INFO Invoking the "failing" renderer
[TIMESTAMP] [ERROR] (mdbook_driver::builtin_renderers): Renderer exited with non-zero return code. ERROR Renderer exited with non-zero return code.
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Rendering failed ERROR Rendering failed
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: The "failing" renderer failed [TAB]Caused by: The "failing" renderer failed
"#]]); "#]]);
}); });
@ -82,13 +82,13 @@ fn missing_renderer() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the missing backend INFO Running the missing backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "missing" renderer INFO Invoking the "missing" renderer
[TIMESTAMP] [ERROR] (mdbook_driver): The command `trduyvbhijnorgevfuhn` wasn't found, is the `missing` backend installed? If you want to ignore this error when the `missing` backend is not installed, set `optional = true` in the `[output.missing]` section of the book.toml configuration file. ERROR The command `trduyvbhijnorgevfuhn` wasn't found, is the `missing` backend installed? If you want to ignore this error when the `missing` backend is not installed, set `optional = true` in the `[output.missing]` section of the book.toml configuration file.
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Rendering failed ERROR Rendering failed
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: Unable to run the backend `missing` [TAB]Caused by: Unable to run the backend `missing`
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: [NOT_FOUND] [TAB]Caused by: [NOT_FOUND]
"#]]); "#]]);
}); });
@ -99,10 +99,10 @@ fn missing_renderer() {
fn missing_optional_not_fatal() { fn missing_optional_not_fatal() {
BookTest::from_dir("renderer/missing_optional_not_fatal").run("build", |cmd| { BookTest::from_dir("renderer/missing_optional_not_fatal").run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the missing backend INFO Running the missing backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "missing" renderer INFO Invoking the "missing" renderer
[TIMESTAMP] [WARN] (mdbook_driver): The command `trduyvbhijnorgevfuhn` for backend `missing` was not found, but is marked as optional. WARN The command `trduyvbhijnorgevfuhn` for backend `missing` was not found, but is marked as optional.
"#]]); "#]]);
}); });
@ -131,9 +131,9 @@ Hello World!
"#]]) "#]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the arguments backend INFO Running the arguments backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "arguments" renderer INFO Invoking the "arguments" renderer
"#]]); "#]]);
}); });
@ -156,9 +156,9 @@ fn backends_receive_render_context_via_stdin() {
) )
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the cat-to-file backend INFO Running the cat-to-file backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "cat-to-file" renderer INFO Invoking the "cat-to-file" renderer
"#]]); "#]]);
}) })
@ -233,9 +233,9 @@ fn relative_command_path() {
) )
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the myrenderer backend INFO Running the myrenderer backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "myrenderer" renderer INFO Invoking the "myrenderer" renderer
"#]]); "#]]);
}) })

View file

@ -126,10 +126,10 @@ fn with_no_source_path() {
fn chapter_settings_validation_error() { fn chapter_settings_validation_error() {
BookTest::from_dir("search/chapter_settings_validation_error").run("build", |cmd| { BookTest::from_dir("search/chapter_settings_validation_error").run("build", |cmd| {
cmd.expect_failure().expect_stderr(str![[r#" cmd.expect_failure().expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Rendering failed ERROR Rendering failed
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: [output.html.search.chapter] key `does-not-exist` does not match any chapter paths [TAB]Caused by: [output.html.search.chapter] key `does-not-exist` does not match any chapter paths
"#]]); "#]]);
}); });

View file

@ -7,9 +7,9 @@ use crate::prelude::*;
fn passing_tests() { fn passing_tests() {
BookTest::from_dir("test/passing_tests").run("test", |cmd| { BookTest::from_dir("test/passing_tests").run("test", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Testing chapter 'Intro': "intro.md" INFO Testing chapter 'Intro': "intro.md"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Testing chapter 'Passing 1': "passing1.md" INFO Testing chapter 'Passing 1': "passing1.md"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Testing chapter 'Passing 2': "passing2.md" INFO Testing chapter 'Passing 2': "passing2.md"
"#]]); "#]]);
}); });
@ -27,8 +27,8 @@ fn failing_tests() {
// still includes a little bit of output, so if that is a problem, // still includes a little bit of output, so if that is a problem,
// add more redactions. // add more redactions.
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Testing chapter 'Failing Tests': "failing.md" INFO Testing chapter 'Failing Tests': "failing.md"
[TIMESTAMP] [ERROR] (mdbook_driver::mdbook): rustdoc returned an error: ERROR rustdoc returned an error:
--- stdout --- stdout
@ -38,8 +38,8 @@ test failing.md - Failing_Tests (line 3) ... FAILED
thread [..] panicked at failing.md:3:1: thread [..] panicked at failing.md:3:1:
fail fail
... ...
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Testing chapter 'Failing Include': "failing_include.md" INFO Testing chapter 'Failing Include': "failing_include.md"
[TIMESTAMP] [ERROR] (mdbook_driver::mdbook): rustdoc returned an error: ERROR rustdoc returned an error:
--- stdout --- stdout
... ...
@ -48,7 +48,7 @@ test failing_include.md - Failing_Include (line 3) ... FAILED
thread [..] panicked at failing_include.md:3:1: thread [..] panicked at failing_include.md:3:1:
failing! failing!
... ...
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: One or more tests failed ERROR One or more tests failed
"#]]); "#]]);
}); });
@ -62,14 +62,14 @@ fn test_individual_chapter() {
cmd.args(&["Passing 1"]) cmd.args(&["Passing 1"])
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Testing chapter 'Passing 1': "passing1.md" INFO Testing chapter 'Passing 1': "passing1.md"
"#]]); "#]]);
}) })
// Can also be a source path. // Can also be a source path.
.run("test -c passing2.md", |cmd| { .run("test -c passing2.md", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#" cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Testing chapter 'Passing 2': "passing2.md" INFO Testing chapter 'Passing 2': "passing2.md"
"#]]); "#]]);
}); });
@ -82,7 +82,7 @@ fn chapter_not_found() {
cmd.expect_failure() cmd.expect_failure()
.expect_stdout(str![[""]]) .expect_stdout(str![[""]])
.expect_stderr(str![[r#" .expect_stderr(str![[r#"
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Chapter not found: bogus ERROR Chapter not found: bogus
"#]]); "#]]);
}); });

View file

@ -5,14 +5,12 @@ use crate::prelude::*;
// Checks what happens if the theme directory is missing. // Checks what happens if the theme directory is missing.
#[test] #[test]
fn missing_theme() { fn missing_theme() {
BookTest::from_dir("theme/missing_theme") BookTest::from_dir("theme/missing_theme").run("build", |cmd| {
.run("build", |cmd| { cmd.expect_failure().expect_stderr(str![[r#"
cmd.expect_failure() INFO Book building has started
.expect_stderr(str![[r#" INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started ERROR Rendering failed
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend [TAB]Caused by: theme dir [ROOT]/./non-existent-directory does not exist
[TIMESTAMP] [ERROR] (mdbook_core::utils): Error: Rendering failed
[TIMESTAMP] [ERROR] (mdbook_core::utils): [TAB]Caused By: theme dir [ROOT]/./non-existent-directory does not exist
"#]]); "#]]);
}); });
@ -24,9 +22,9 @@ fn empty_theme() {
BookTest::from_dir("theme/empty_theme").run("build", |cmd| { BookTest::from_dir("theme/empty_theme").run("build", |cmd| {
std::fs::create_dir(cmd.dir.join("theme")).unwrap(); std::fs::create_dir(cmd.dir.join("theme")).unwrap();
cmd.expect_stderr(str![[r#" cmd.expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}); });
@ -147,9 +145,9 @@ fn empty_fonts_css() {
BookTest::from_dir("theme/empty_fonts_css") BookTest::from_dir("theme/empty_fonts_css")
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stderr(str![[r#" cmd.expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}) })
@ -163,9 +161,9 @@ fn custom_fonts_css() {
BookTest::from_dir("theme/custom_fonts_css") BookTest::from_dir("theme/custom_fonts_css")
.run("build", |cmd| { .run("build", |cmd| {
cmd.expect_stderr(str![[r#" cmd.expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started INFO Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the html backend INFO Running the html backend
[TIMESTAMP] [INFO] (mdbook_html::html_handlebars::hbs_renderer): HTML book written to `[ROOT]/book` INFO HTML book written to `[ROOT]/book`
"#]]); "#]]);
}) })