Skip to content

Commit f552d45

Browse files
authored
Merge pull request #1312 from jyn514/rustdoc-files
Don't hard-code essential rustdoc files
2 parents 2e87f0f + 6f4477b commit f552d45

File tree

2 files changed

+76
-63
lines changed

2 files changed

+76
-63
lines changed

src/docbuilder/rustwide_builder.rs

+55-49
Original file line numberDiff line numberDiff line change
@@ -14,47 +14,16 @@ use docsrs_metadata::{Metadata, DEFAULT_TARGETS, HOST_TARGET};
1414
use failure::ResultExt;
1515
use log::{debug, info, warn, LevelFilter};
1616
use postgres::Client;
17-
use rustwide::cmd::{Command, SandboxBuilder, SandboxImage};
17+
use rustwide::cmd::{Binary, Command, SandboxBuilder, SandboxImage};
1818
use rustwide::logging::{self, LogStorage};
1919
use rustwide::toolchain::ToolchainError;
2020
use rustwide::{Build, Crate, Toolchain, Workspace, WorkspaceBuilder};
2121
use serde_json::Value;
2222
use std::collections::{HashMap, HashSet};
23-
use std::path::Path;
23+
use std::path::{Path, PathBuf};
2424
use std::sync::Arc;
2525

2626
const USER_AGENT: &str = "docs.rs builder (https://github.com/rust-lang/docs.rs)";
27-
const ESSENTIAL_FILES_VERSIONED: &[&str] = &[
28-
"brush.svg",
29-
"favicon.svg",
30-
"wheel.svg",
31-
"down-arrow.svg",
32-
"dark.css",
33-
"light.css",
34-
"ayu.css",
35-
"main.js",
36-
"normalize.css",
37-
"rustdoc.css",
38-
"settings.css",
39-
"settings.js",
40-
"storage.js",
41-
"theme.js",
42-
"source-script.js",
43-
"noscript.css",
44-
"rust-logo.png",
45-
];
46-
const ESSENTIAL_FILES_UNVERSIONED: &[&str] = &[
47-
"FiraSans-Medium.woff",
48-
"FiraSans-Medium.woff2",
49-
"FiraSans-Regular.woff",
50-
"FiraSans-Regular.woff2",
51-
"SourceCodePro-Regular.woff",
52-
"SourceCodePro-Semibold.woff",
53-
"SourceSerifPro-Bold.ttf.woff",
54-
"SourceSerifPro-Regular.ttf.woff",
55-
"SourceSerifPro-It.ttf.woff",
56-
];
57-
5827
const DUMMY_CRATE_NAME: &str = "empty-library";
5928
const DUMMY_CRATE_VERSION: &str = "1.0.0";
6029

@@ -229,19 +198,14 @@ impl RustwideBuilder {
229198
.prefix("essential-files")
230199
.tempdir()?;
231200

232-
let files = ESSENTIAL_FILES_VERSIONED
233-
.iter()
234-
.map(|f| (f, true))
235-
.chain(ESSENTIAL_FILES_UNVERSIONED.iter().map(|f| (f, false)));
236-
for (&file, versioned) in files {
237-
let segments = file.rsplitn(2, '.').collect::<Vec<_>>();
238-
let file_name = if versioned {
239-
format!("{}-{}.{}", segments[1], rustc_version, segments[0])
240-
} else {
241-
file.to_string()
242-
};
201+
for file_name in self.essential_files(build, &source)? {
243202
let source_path = source.join(&file_name);
244203
let dest_path = dest.path().join(&file_name);
204+
debug!(
205+
"copying {} to {}",
206+
source_path.display(),
207+
dest_path.display()
208+
);
245209
::std::fs::copy(&source_path, &dest_path).with_context(|_| {
246210
format!(
247211
"couldn't copy '{}' to '{}'",
@@ -370,7 +334,7 @@ impl RustwideBuilder {
370334
let mut algs = HashSet::new();
371335
if has_docs {
372336
debug!("adding documentation for the default target to the database");
373-
self.copy_docs(&build.host_target_dir(), local_storage.path(), "", true)?;
337+
self.copy_docs(build, local_storage.path(), "", true)?;
374338

375339
successful_targets.push(res.target.clone());
376340

@@ -472,7 +436,7 @@ impl RustwideBuilder {
472436
// adding target to successfully_targets.
473437
if build.host_target_dir().join(target).join("doc").is_dir() {
474438
debug!("adding documentation for target {} to the database", target,);
475-
self.copy_docs(&build.host_target_dir(), local_storage, target, false)?;
439+
self.copy_docs(build, local_storage, target, false)?;
476440
successful_targets.push(target.to_string());
477441
}
478442
}
@@ -645,12 +609,12 @@ impl RustwideBuilder {
645609

646610
fn copy_docs(
647611
&self,
648-
target_dir: &Path,
612+
build: &Build,
649613
local_storage: &Path,
650614
target: &str,
651615
is_default_target: bool,
652616
) -> Result<()> {
653-
let source = target_dir.join(target).join("doc");
617+
let source = build.host_target_dir().join(target).join("doc");
654618

655619
let mut dest = local_storage.to_path_buf();
656620
// only add target name to destination directory when we are copying a non-default target.
@@ -663,7 +627,49 @@ impl RustwideBuilder {
663627
}
664628

665629
info!("{} {}", source.display(), dest.display());
666-
copy_doc_dir(source, dest)
630+
let essential_files = self.essential_files(build, &source)?;
631+
copy_doc_dir(source, dest, &essential_files)
632+
}
633+
634+
fn essential_files(&self, build: &Build, doc_dir: &Path) -> Result<Vec<PathBuf>> {
635+
// TODO: remove this when https://github.com/rust-lang/rustwide/pull/53 lands.
636+
struct Rustdoc<'a> {
637+
toolchain_version: &'a str,
638+
}
639+
impl rustwide::cmd::Runnable for Rustdoc<'_> {
640+
fn name(&self) -> Binary {
641+
Binary::ManagedByRustwide(PathBuf::from("rustdoc"))
642+
}
643+
644+
fn prepare_command<'w, 'pl>(&self, cmd: Command<'w, 'pl>) -> Command<'w, 'pl> {
645+
cmd.args(&[format!("+{}", self.toolchain_version)])
646+
}
647+
}
648+
649+
let toolchain_version = self.toolchain.as_dist().unwrap().name();
650+
let output = build.cmd(Rustdoc { toolchain_version })
651+
.args(&["-Zunstable-options", "--print=unversioned-files"])
652+
.run_capture()
653+
.context("failed to learn about unversioned files - make sure you have nightly-2021-03-07 or later")?;
654+
let mut essential_files: Vec<_> = output.stdout_lines().iter().map(PathBuf::from).collect();
655+
let resource_suffix = format!("-{}", parse_rustc_version(&self.rustc_version)?);
656+
657+
let essential_files_versioned = doc_dir
658+
.read_dir()?
659+
.collect::<std::result::Result<Vec<_>, _>>()?
660+
.into_iter()
661+
.filter_map(|entry| {
662+
entry.file_name().to_str().and_then(|name| {
663+
if name.contains(&resource_suffix) {
664+
Some(entry.file_name().into())
665+
} else {
666+
None
667+
}
668+
})
669+
});
670+
671+
essential_files.extend(essential_files_versioned);
672+
Ok(essential_files)
667673
}
668674

669675
fn upload_docs(

src/utils/copy.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
11
use crate::error::Result;
22
use std::fs;
3-
use std::path::Path;
4-
5-
use regex::Regex;
3+
use std::path::{Path, PathBuf};
64

75
/// Copies documentation from a crate's target directory to destination.
86
///
97
/// Target directory must have doc directory.
108
///
11-
/// This function is designed to avoid file duplications.
12-
pub fn copy_doc_dir<P: AsRef<Path>, Q: AsRef<Path>>(source: P, destination: Q) -> Result<()> {
9+
/// This does not copy any files with the same name as `shared_files`.
10+
pub fn copy_doc_dir<P: AsRef<Path>, Q: AsRef<Path>>(
11+
source: P,
12+
destination: Q,
13+
shared_files: &[PathBuf],
14+
) -> Result<()> {
1315
let destination = destination.as_ref();
1416

1517
// Make sure destination directory exists
1618
if !destination.exists() {
1719
fs::create_dir_all(destination)?;
1820
}
1921

20-
// Avoid copying common files
21-
let dup_regex = Regex::new(
22-
r"(\.lock|\.txt|\.woff|\.svg|\.css|main-.*\.css|main-.*\.js|normalize-.*\.js|rustdoc-.*\.css|storage-.*\.js|theme-.*\.js)$")
23-
.unwrap();
24-
2522
for file in source.as_ref().read_dir()? {
2623
let file = file?;
27-
let destination_full_path = destination.join(file.file_name());
24+
let filename = file.file_name();
25+
let destination_full_path = destination.join(&filename);
2826

2927
let metadata = file.metadata()?;
3028

3129
if metadata.is_dir() {
32-
copy_doc_dir(file.path(), destination_full_path)?
33-
} else if dup_regex.is_match(&file.file_name().into_string().unwrap()[..]) {
30+
copy_doc_dir(file.path(), destination_full_path, shared_files)?;
31+
continue;
32+
}
33+
34+
if shared_files.contains(&PathBuf::from(filename)) {
3435
continue;
3536
} else {
3637
fs::copy(&file.path(), &destination_full_path)?;
@@ -65,7 +66,13 @@ mod test {
6566
fs::write(doc.join("inner").join("important.svg"), "<svg></svg>").unwrap();
6667

6768
// lets try to copy a src directory to tempdir
68-
copy_doc_dir(source.path().join("doc"), destination.path()).unwrap();
69+
let ignored_files = ["index.txt".into(), "important.svg".into()];
70+
copy_doc_dir(
71+
source.path().join("doc"),
72+
destination.path(),
73+
&ignored_files,
74+
)
75+
.unwrap();
6976
assert!(destination.path().join("index.html").exists());
7077
assert!(!destination.path().join("index.txt").exists());
7178
assert!(destination.path().join("inner").join("index.html").exists());

0 commit comments

Comments
 (0)