Remove legacy relative renderer command paths

This removes the deprecated support for renderer paths that are relative
to the destination. Relative renderer command paths now must always be
relative to the book root.
This commit is contained in:
Eric Huss 2025-08-12 18:08:29 -07:00
parent 7e0949175a
commit df037d132d
2 changed files with 7 additions and 51 deletions

View file

@ -50,7 +50,7 @@ impl CmdRenderer {
CmdRenderer { name, cmd }
}
fn compose_command(&self, root: &Path, destination: &Path) -> Result<Command> {
fn compose_command(&self, root: &Path) -> Result<Command> {
let mut words = Shlex::new(&self.cmd);
let exe = match words.next() {
Some(e) => PathBuf::from(e),
@ -61,30 +61,8 @@ impl CmdRenderer {
// Search PATH for the executable.
exe
} else {
// Relative paths are preferred to be relative to the book root.
let abs_exe = root.join(&exe);
if abs_exe.exists() {
abs_exe
} else {
// Historically paths were relative to the destination, but
// this is not the preferred way.
let legacy_path = destination.join(&exe);
if legacy_path.exists() {
warn!(
"Renderer command `{}` uses a path relative to the \
renderer output directory `{}`. This was previously \
accepted, but has been deprecated. Relative executable \
paths should be relative to the book root.",
exe.display(),
destination.display()
);
legacy_path
} else {
// Let this bubble through to later be handled by
// handle_render_command_error.
abs_exe
}
}
// Relative path is relative to book root.
root.join(&exe)
};
let mut cmd = Command::new(exe);
@ -143,7 +121,7 @@ impl Renderer for CmdRenderer {
let _ = fs::create_dir_all(&ctx.destination);
let mut child = match self
.compose_command(&ctx.root, &ctx.destination)?
.compose_command(&ctx.root)?
.stdin(Stdio::piped())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())

View file

@ -211,11 +211,10 @@ fn backends_receive_render_context_via_stdin() {
RenderContext::from_json(f).unwrap();
}
// Legacy relative renderer paths.
//
// https://github.com/rust-lang/mdBook/pull/1418
// Verifies that a relative path for the renderer command is relative to the
// book root.
#[test]
fn legacy_relative_command_path() {
fn relative_command_path() {
let mut test = BookTest::init(|_| {});
test.rust_program(
"renderers/myrenderer",
@ -228,7 +227,6 @@ fn legacy_relative_command_path() {
}
"#,
)
// Test with a modern path, relative to the book directory.
.change_file(
"book.toml",
"[output.myrenderer]\n\
@ -240,26 +238,6 @@ fn legacy_relative_command_path() {
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the myrenderer backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "myrenderer" renderer
"#]]);
})
.check_file("book/output", "test");
std::fs::remove_file(test.dir.join("book/output")).unwrap();
// Test with legacy path, relative to the output directory.
test.change_file(
"book.toml",
&format!(
"[output.myrenderer]\n\
command = '../renderers/myrenderer{exe}'\n",
exe = std::env::consts::EXE_SUFFIX
),
)
.run("build", |cmd| {
cmd.expect_stdout(str![[""]]).expect_stderr(str![[r#"
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Book building has started
[TIMESTAMP] [INFO] (mdbook_driver::mdbook): Running the myrenderer backend
[TIMESTAMP] [INFO] (mdbook_driver::builtin_renderers): Invoking the "myrenderer" renderer
[TIMESTAMP] [WARN] (mdbook_driver::builtin_renderers): Renderer command `../renderers/myrenderer[EXE]` uses a path relative to the renderer output directory `[ROOT]/book`. This was previously accepted, but has been deprecated. Relative executable paths should be relative to the book root.
"#]]);
})
.check_file("book/output", "test");