Skip to content

Commit f3a3740

Browse files
authored
Merge pull request #1340 from jyn514/shared-files
Upload exactly the shared files needed and give precedence to global files over local ones
2 parents 9708001 + d9a14bc commit f3a3740

File tree

4 files changed

+36
-107
lines changed

4 files changed

+36
-107
lines changed

src/docbuilder/rustwide_builder.rs

+16-56
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ use crate::docbuilder::{crates::crates_from_path, Limits};
77
use crate::error::Result;
88
use crate::index::api::ReleaseData;
99
use crate::storage::CompressionAlgorithms;
10-
use crate::utils::{copy_doc_dir, parse_rustc_version, CargoMetadata, GithubUpdater};
10+
use crate::utils::{copy_dir_all, parse_rustc_version, CargoMetadata, GithubUpdater};
1111
use crate::{db::blacklist::is_blacklisted, utils::MetadataPackage};
1212
use crate::{Config, Context, Index, Metrics, Storage};
1313
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::{Binary, Command, SandboxBuilder, SandboxImage};
17+
use rustwide::cmd::{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, PathBuf};
23+
use std::path::Path;
2424
use std::sync::Arc;
2525

2626
const USER_AGENT: &str = "docs.rs builder (https://github.com/rust-lang/docs.rs)";
@@ -182,26 +182,12 @@ impl RustwideBuilder {
182182
let krate = Crate::crates_io(DUMMY_CRATE_NAME, DUMMY_CRATE_VERSION);
183183
krate.fetch(&self.workspace)?;
184184

185-
// TODO: remove this when https://github.com/rust-lang/rustwide/pull/53 lands.
186-
struct Rustdoc<'a> {
187-
toolchain_version: &'a str,
188-
}
189-
impl rustwide::cmd::Runnable for Rustdoc<'_> {
190-
fn name(&self) -> Binary {
191-
Binary::ManagedByRustwide(PathBuf::from("rustdoc"))
192-
}
193-
194-
fn prepare_command<'w, 'pl>(&self, cmd: Command<'w, 'pl>) -> Command<'w, 'pl> {
195-
cmd.args(&[format!("+{}", self.toolchain_version)])
196-
}
197-
}
198-
199185
build_dir
200186
.build(&self.toolchain, &krate, self.prepare_sandbox(&limits))
201187
.run(|build| {
202188
let metadata = Metadata::from_crate_root(&build.host_source_dir())?;
203189

204-
let res = self.execute_build(HOST_TARGET, true, build, &limits, &metadata)?;
190+
let res = self.execute_build(HOST_TARGET, true, build, &limits, &metadata, true)?;
205191
if !res.result.successful {
206192
failure::bail!("failed to build dummy crate for {}", self.rustc_version);
207193
}
@@ -211,39 +197,7 @@ impl RustwideBuilder {
211197
let dest = tempfile::Builder::new()
212198
.prefix("essential-files")
213199
.tempdir()?;
214-
215-
let toolchain_version = self.toolchain.as_dist().unwrap().name();
216-
let output = build.cmd(Rustdoc { toolchain_version })
217-
.args(&["-Zunstable-options", "--print=unversioned-files"])
218-
.run_capture()
219-
.context("failed to learn about unversioned files - make sure you have nightly-2021-03-07 or later")?;
220-
let essential_files_unversioned = output
221-
.stdout_lines()
222-
.iter()
223-
.map(PathBuf::from);
224-
let resource_suffix = format!("-{}", parse_rustc_version(&self.rustc_version)?);
225-
let essential_files_versioned: Vec<_> = source.read_dir()?
226-
.collect::<std::result::Result<Vec<_>, _>>()?
227-
.into_iter()
228-
.filter_map(|entry| {
229-
entry.file_name().to_str().and_then(|name| if name.contains(&resource_suffix) {
230-
Some(entry.file_name().into())
231-
} else { None })
232-
})
233-
.collect();
234-
for file_name in essential_files_unversioned.chain(essential_files_versioned) {
235-
let source_path = source.join(&file_name);
236-
let dest_path = dest.path().join(&file_name);
237-
debug!("copying {} to {}", source_path.display(), dest_path.display());
238-
::std::fs::copy(&source_path, &dest_path).with_context(|_| {
239-
format!(
240-
"couldn't copy '{}' to '{}'",
241-
source_path.display(),
242-
dest_path.display()
243-
)
244-
})?;
245-
}
246-
200+
copy_dir_all(source, &dest)?;
247201
add_path_into_database(&self.storage, "", &dest)?;
248202
conn.query(
249203
"INSERT INTO config (name, value) VALUES ('rustc_version', $1) \
@@ -352,7 +306,8 @@ impl RustwideBuilder {
352306
} = metadata.targets(self.config.include_default_targets);
353307

354308
// Perform an initial build
355-
let res = self.execute_build(default_target, true, &build, &limits, &metadata)?;
309+
let res =
310+
self.execute_build(default_target, true, &build, &limits, &metadata, false)?;
356311
if res.result.successful {
357312
if let Some(name) = res.cargo_metadata.root().library_name() {
358313
let host_target = build.host_target_dir();
@@ -458,7 +413,7 @@ impl RustwideBuilder {
458413
successful_targets: &mut Vec<String>,
459414
metadata: &Metadata,
460415
) -> Result<()> {
461-
let target_res = self.execute_build(target, false, build, limits, metadata)?;
416+
let target_res = self.execute_build(target, false, build, limits, metadata, false)?;
462417
if target_res.result.successful {
463418
// Cargo is not giving any error and not generating documentation of some crates
464419
// when we use a target compile options. Check documentation exists before
@@ -534,12 +489,17 @@ impl RustwideBuilder {
534489
build: &Build,
535490
limits: &Limits,
536491
metadata: &Metadata,
492+
create_essential_files: bool,
537493
) -> Result<FullBuildResult> {
538494
let cargo_metadata =
539495
CargoMetadata::load(&self.workspace, &self.toolchain, &build.host_source_dir())?;
540496

541-
let mut rustdoc_flags = Vec::new();
542-
497+
let mut rustdoc_flags = vec![if create_essential_files {
498+
"--emit=unversioned-shared-resources,toolchain-shared-resources"
499+
} else {
500+
"--emit=invocation-specific"
501+
}
502+
.to_string()];
543503
rustdoc_flags.extend(vec![
544504
"--resource-suffix".to_string(),
545505
format!("-{}", parse_rustc_version(&self.rustc_version)?),
@@ -656,7 +616,7 @@ impl RustwideBuilder {
656616
}
657617

658618
info!("{} {}", source.display(), dest.display());
659-
copy_doc_dir(source, dest)
619+
copy_dir_all(source, dest).map_err(Into::into)
660620
}
661621

662622
fn upload_docs(

src/utils/copy.rs

+12-43
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,18 @@
1-
use crate::error::Result;
21
use std::fs;
2+
use std::io;
33
use std::path::Path;
44

5-
use regex::Regex;
6-
7-
/// Copies documentation from a crate's target directory to destination.
8-
///
9-
/// Target directory must have doc directory.
10-
///
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<()> {
13-
let destination = destination.as_ref();
14-
15-
// Make sure destination directory exists
16-
if !destination.exists() {
17-
fs::create_dir_all(destination)?;
18-
}
19-
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-
25-
for file in source.as_ref().read_dir()? {
26-
let file = file?;
27-
let destination_full_path = destination.join(file.file_name());
28-
29-
let metadata = file.metadata()?;
30-
31-
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()[..]) {
34-
continue;
5+
/// cp -r src dst
6+
pub(crate) fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
7+
let dst = dst.as_ref();
8+
fs::create_dir_all(dst)?;
9+
for entry in fs::read_dir(src)? {
10+
let entry = entry?;
11+
let filename = entry.file_name();
12+
if entry.file_type()?.is_dir() {
13+
copy_dir_all(entry.path(), dst.join(filename))?;
3514
} else {
36-
fs::copy(&file.path(), &destination_full_path)?;
15+
fs::copy(entry.path(), dst.join(filename))?;
3716
}
3817
}
3918
Ok(())
@@ -59,21 +38,11 @@ mod test {
5938
fs::create_dir(doc.join("inner")).unwrap();
6039

6140
fs::write(doc.join("index.html"), "<html>spooky</html>").unwrap();
62-
fs::write(doc.join("index.txt"), "spooky").unwrap();
6341
fs::write(doc.join("inner").join("index.html"), "<html>spooky</html>").unwrap();
64-
fs::write(doc.join("inner").join("index.txt"), "spooky").unwrap();
65-
fs::write(doc.join("inner").join("important.svg"), "<svg></svg>").unwrap();
6642

6743
// lets try to copy a src directory to tempdir
68-
copy_doc_dir(source.path().join("doc"), destination.path()).unwrap();
44+
copy_dir_all(source.path().join("doc"), destination.path()).unwrap();
6945
assert!(destination.path().join("index.html").exists());
70-
assert!(!destination.path().join("index.txt").exists());
7146
assert!(destination.path().join("inner").join("index.html").exists());
72-
assert!(!destination.path().join("inner").join("index.txt").exists());
73-
assert!(!destination
74-
.path()
75-
.join("inner")
76-
.join("important.svg")
77-
.exists());
7847
}
7948
}

src/utils/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Various utilities for docs.rs
22
33
pub(crate) use self::cargo_metadata::{CargoMetadata, Package as MetadataPackage};
4-
pub(crate) use self::copy::copy_doc_dir;
4+
pub(crate) use self::copy::copy_dir_all;
55
pub use self::daemon::start_daemon;
66
pub use self::github_updater::GithubUpdater;
77
pub(crate) use self::html::rewrite_lol;

src/web/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ impl Handler for CratesfyiHandler {
162162
handle: impl FnOnce() -> IronResult<Response>,
163163
) -> IronResult<Response> {
164164
if e.response.status == Some(status::NotFound) {
165-
// the routes are ordered from most specific to least; give precedence to the
166-
// original error message.
167-
handle().or(Err(e))
165+
// the routes are ordered from least specific to most; give precedence to the
166+
// new error message.
167+
handle()
168168
} else {
169169
Err(e)
170170
}
@@ -181,11 +181,11 @@ impl Handler for CratesfyiHandler {
181181
// specific path means that buggy docs from 2018 will have missing CSS (#1181) so until
182182
// that's fixed, we need to keep the current (buggy) behavior.
183183
//
184-
// It's important that `router_handler` comes first so that local rustdoc files take
185-
// precedence over global ones (see #1324).
186-
self.router_handler
184+
// It's important that `shared_resource_handler` comes first so that global rustdoc files take
185+
// precedence over local ones (see #1327).
186+
self.shared_resource_handler
187187
.handle(req)
188-
.or_else(|e| if_404(e, || self.shared_resource_handler.handle(req)))
188+
.or_else(|e| if_404(e, || self.router_handler.handle(req)))
189189
.or_else(|e| {
190190
let err = if let Some(err) = e.error.downcast_ref::<error::Nope>() {
191191
*err

0 commit comments

Comments
 (0)