Skip to content

Commit 9379b1a

Browse files
committed
adding recursive copy functionality
1 parent 40cac0d commit 9379b1a

File tree

5 files changed

+95
-1
lines changed

5 files changed

+95
-1
lines changed

src/librustdoc/config.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ pub(crate) struct RenderOptions {
296296
pub(crate) read_rendered_cci: bool,
297297
/// If `true` (default) write the shared cross-crate information to the doc root
298298
pub(crate) write_rendered_cci: bool,
299+
/// Copies these folders into our doc root.
300+
pub(crate) include_rendered_docs: Vec<PathToDocSubdirectory>,
299301
/// The location of the doc directory for externally located crates.
300302
/// Absolute path ending in doc/.
301303
pub(crate) parts_paths: Vec<PathToParts>,
@@ -505,7 +507,10 @@ impl Options {
505507
Err(err) => dcx.fatal(err),
506508
};
507509

508-
let parts_paths = matches.opt_strs("include-info-json").iter()
510+
let include_rendered_docs = matches.opt_strs("include-rendered-docs").into_iter()
511+
.map(|p| PathToDocSubdirectory(PathBuf::from(p)))
512+
.collect();
513+
let parts_paths = matches.opt_strs("include-info-json").into_iter()
509514
.map(|path| PathToParts(PathBuf::from(path)))
510515
.collect();
511516

@@ -842,6 +847,7 @@ impl Options {
842847
read_rendered_cci,
843848
write_rendered_cci,
844849
parts_paths,
850+
include_rendered_docs,
845851
parts_out_dir,
846852
};
847853
Some((options, render_options))
@@ -921,6 +927,10 @@ fn parse_extern_html_roots(
921927
Ok(externs)
922928
}
923929

930+
/// Path to the doc subdirectory for a specific crate, for example `target/doc/serde_json`.
931+
#[derive(Clone, Debug)]
932+
pub(crate) struct PathToDocSubdirectory(pub PathBuf);
933+
924934
/// Path to cci root, including doc.parts, but not the crate name
925935
///
926936
/// For example, `/home/user/project/target/doc.parts/<crate>/crate-info.json`.

src/librustdoc/html/render/context.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_span::{sym, FileName, Symbol};
1414

1515
use super::print_item::{full_path, item_path, print_item};
1616
use super::write_shared::{write_shared};
17+
use super::copy_dir::{copy_dir_all};
1718
use super::{
1819
collect_spans_and_sources, scrape_examples_help,
1920
sidebar::print_sidebar,
@@ -470,6 +471,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
470471
call_locations,
471472
no_emit_shared,
472473
html_no_source,
474+
include_rendered_docs,
473475
..
474476
} = options;
475477

@@ -573,6 +575,10 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
573575
is_inside_inlined_module: false,
574576
};
575577

578+
for extern_docs in include_rendered_docs.iter() {
579+
try_err!(copy_dir_all(&extern_docs.0, &cx.dst), &extern_docs.0);
580+
}
581+
576582
if emit_crate {
577583
sources::render(&mut cx, &krate)?;
578584
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use std::io::{Error, Result, ErrorKind};
2+
use std::path::{PathBuf};
3+
use std::fs;
4+
5+
/// Recursively copies the contents of the directory `src` to the directory `dst`.
6+
/// Analogous to `cp -rf src/* dst`.
7+
pub(crate) fn copy_dir_all<S: Into<PathBuf>, D: Into<PathBuf>>(src: S, dst: D) -> Result<()> {
8+
copy_dir_mono(src.into(), dst.into())
9+
}
10+
11+
/// Monomorphized version of `copy_dir`
12+
fn copy_dir_mono(src: PathBuf, dst: PathBuf) -> Result<()> {
13+
let mut dirs: Vec<(PathBuf, PathBuf)> = Vec::default();
14+
15+
if !src.is_dir() {
16+
return Err(Error::new(ErrorKind::Other, format!("src path `{src:?}` should be a directory")));
17+
}
18+
if !dst.is_dir() {
19+
return Err(Error::new(ErrorKind::Other, format!("dst path `{dst:?}` should be a directory")));
20+
}
21+
22+
dirs.push((src, dst));
23+
24+
while let Some((src, dst)) = dirs.pop() {
25+
match fs::create_dir(&dst) {
26+
Ok(()) => {},
27+
Err(e) if e.kind() == ErrorKind::AlreadyExists => {},
28+
Err(e) => return Err(e),
29+
}
30+
31+
for entry in src.read_dir()? {
32+
let entry = entry?;
33+
let file_type = entry.file_type()?;
34+
let src_filename = dbg!(entry.file_name());
35+
let src = src.join(&src_filename);
36+
let dst = dst.join(&src_filename);
37+
if file_type.is_dir() {
38+
dirs.push((src, dst));
39+
} else {
40+
fs::copy(&src, &dst)?;
41+
}
42+
}
43+
}
44+
45+
Ok(())
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
use super::copy_dir_all;
51+
use tempfile::TempDir;
52+
// use std::fs::{write, read_to_string};
53+
use std::io::{Result};
54+
55+
#[test]
56+
fn empty_dir() -> Result<()> {
57+
let src = TempDir::new()?;
58+
let dst = TempDir::new()?;
59+
let src = src.path();
60+
let dst = dst.path();
61+
copy_dir_all(src, dst)?;
62+
let mut dst = dst.read_dir()?;
63+
assert!(dst.next().is_none(), "we copied nothing into the destination");
64+
Ok(())
65+
}
66+
67+
68+
}

src/librustdoc/html/render/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub(crate) mod search_index;
2828
#[cfg(test)]
2929
mod tests;
3030

31+
mod copy_dir;
3132
mod context;
3233
mod print_item;
3334
mod sidebar;

src/librustdoc/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,15 @@ fn opts() -> Vec<RustcOptGroup> {
630630
"PATH",
631631
)
632632
}),
633+
unstable("include-rendered-docs", |o| {
634+
o.optopt(
635+
"",
636+
"include-rendered-docs",
637+
"Copies docs from an external crate to the --out-dir. Expects PATH to be a path directly
638+
to the external crate's subdirectory in its doc root.",
639+
"PATH",
640+
)
641+
}),
633642
// deprecated / removed options
634643
unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")),
635644
stable("plugin-path", |o| {

0 commit comments

Comments
 (0)