Skip to content

Commit ba5ea9b

Browse files
jyn514Joshua Nelson
authored and
Joshua Nelson
committed
Use BuildTargets and simplify implementation
1 parent aecd970 commit ba5ea9b

File tree

2 files changed

+36
-41
lines changed

2 files changed

+36
-41
lines changed

src/docbuilder/metadata.rs

+33-40
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashSet;
12
use std::path::Path;
23
use toml::Value;
34
use error::Result;
@@ -63,7 +64,16 @@ pub struct Metadata {
6364
pub rustdoc_args: Option<Vec<String>>,
6465
}
6566

66-
67+
/// The targets that should be built for a crate.
68+
///
69+
/// The `default_target` is the target to be used as the home page for that crate.
70+
///
71+
/// # See also
72+
/// - [`Metadata::targets`](struct.Metadata.html#method.targets)
73+
pub(super) struct BuildTargets<'a> {
74+
pub(super) default_target: &'a str,
75+
pub(super) other_targets: HashSet<&'a str>,
76+
}
6777

6878
impl Metadata {
6979
pub(crate) fn from_source_dir(source_dir: &Path) -> Result<Metadata> {
@@ -136,39 +146,21 @@ impl Metadata {
136146
metadata
137147
}
138148
// Return (default_target, all other targets that should be built with duplicates removed)
139-
pub(super) fn targets(&self) -> (&str, Vec<&str>) {
149+
pub(super) fn targets(&self) -> BuildTargets<'_> {
140150
use super::rustwide_builder::{HOST_TARGET, TARGETS};
151+
152+
let default_target = self.default_target.as_deref()
153+
// Use the first element of `targets` if `default_target` is unset and `targets` is non-empty
154+
.or_else(|| self.targets.as_ref().and_then(|targets| targets.iter().next().map(String::as_str)))
155+
.unwrap_or(HOST_TARGET);
156+
141157
// Let people opt-in to only having specific targets
142-
// Ideally this would use Iterator instead of Vec so I could collect to a `HashSet`,
143-
// but I had trouble with `chain()` ¯\_(ツ)_/¯
144-
let mut all_targets: Vec<_> = self.default_target.as_deref().into_iter().collect();
145-
match &self.targets {
146-
Some(targets) => all_targets.extend(targets.iter().map(|s| s.as_str())),
147-
None if all_targets.is_empty() => {
148-
// Make sure HOST_TARGET is first
149-
all_targets.push(HOST_TARGET);
150-
all_targets.extend(TARGETS.iter().copied().filter(|&t| t != HOST_TARGET));
151-
}
152-
None => all_targets.extend(TARGETS.iter().copied()),
153-
};
158+
let mut targets: HashSet<_> = self.targets.as_ref()
159+
.map(|targets| targets.iter().map(String::as_str).collect())
160+
.unwrap_or_else(|| TARGETS.iter().copied().collect());
154161

155-
// default_target unset and targets set to `[]`
156-
let landing_page = if all_targets.is_empty() {
157-
HOST_TARGET
158-
} else {
159-
// This `swap_remove` has to come before the `sort()` to keep the ordering
160-
// `swap_remove` is ok because ordering doesn't matter except for first element
161-
all_targets.swap_remove(0)
162-
};
163-
// Remove duplicates
164-
all_targets.sort();
165-
all_targets.dedup();
166-
// Remove landing_page so we don't build it twice.
167-
// It wasn't removed during dedup because we called `swap_remove()` first.
168-
if let Ok(index) = all_targets.binary_search(&landing_page) {
169-
all_targets.swap_remove(index);
170-
}
171-
(landing_page, all_targets)
162+
targets.remove(&default_target);
163+
BuildTargets { default_target, other_targets: targets }
172164
}
173165
}
174166

@@ -255,10 +247,11 @@ mod test {
255247
#[test]
256248
fn test_select_targets() {
257249
use crate::docbuilder::rustwide_builder::{HOST_TARGET, TARGETS};
250+
use super::BuildTargets;
258251

259252
let mut metadata = Metadata::default();
260253
// unchanged default_target, targets not specified
261-
let (default, tier_one) = metadata.targets();
254+
let BuildTargets { default_target: default, other_targets: tier_one } = metadata.targets();
262255
assert_eq!(default, HOST_TARGET);
263256
// should be equal to TARGETS \ {HOST_TARGET}
264257
for actual in &tier_one {
@@ -274,47 +267,47 @@ mod test {
274267

275268
// unchanged default_target, targets specified to be empty
276269
metadata.targets = Some(Vec::new());
277-
let (default, others) = metadata.targets();
270+
let BuildTargets { default_target: default, other_targets: others } = metadata.targets();
278271
assert_eq!(default, HOST_TARGET);
279272
assert!(others.is_empty());
280273

281274
// unchanged default_target, targets non-empty
282275
metadata.targets = Some(vec!["i686-pc-windows-msvc".into(), "i686-apple-darwin".into()]);
283-
let (default, others) = metadata.targets();
276+
let BuildTargets { default_target: default, other_targets: others } = metadata.targets();
284277
assert_eq!(default, "i686-pc-windows-msvc");
285278
assert_eq!(others.len(), 1);
286279
assert!(others.contains(&"i686-apple-darwin"));
287280

288281
// make sure that default_target is not built twice
289282
metadata.targets = Some(vec![HOST_TARGET.into()]);
290-
let (default, others) = metadata.targets();
283+
let BuildTargets { default_target: default, other_targets: others } = metadata.targets();
291284
assert_eq!(default, HOST_TARGET);
292285
assert!(others.is_empty());
293286

294287
// make sure that duplicates are removed
295288
metadata.targets = Some(vec!["i686-pc-windows-msvc".into(), "i686-pc-windows-msvc".into()]);
296-
let (default, others) = metadata.targets();
289+
let BuildTargets { default_target: default, other_targets: others } = metadata.targets();
297290
assert_eq!(default, "i686-pc-windows-msvc");
298291
assert!(others.is_empty());
299292

300293
// make sure that `default_target` always takes priority over `targets`
301294
metadata.default_target = Some("i686-apple-darwin".into());
302-
let (default, others) = metadata.targets();
295+
let BuildTargets { default_target: default, other_targets: others } = metadata.targets();
303296
assert_eq!(default, "i686-apple-darwin");
304297
assert_eq!(others.len(), 1);
305298
assert!(others.contains(&"i686-pc-windows-msvc"));
306299

307300
// make sure that `default_target` takes priority over `HOST_TARGET`
308301
metadata.targets = Some(vec![]);
309-
let (default, others) = metadata.targets();
302+
let BuildTargets { default_target: default, other_targets: others } = metadata.targets();
310303
assert_eq!(default, "i686-apple-darwin");
311304
assert!(others.is_empty());
312305

313306
// and if `targets` is unset, it should still be set to `TARGETS`
314307
metadata.targets = None;
315-
let (default, others) = metadata.targets();
308+
let BuildTargets { default_target: default, other_targets: others } = metadata.targets();
316309
assert_eq!(default, "i686-apple-darwin");
317-
let tier_one_targets_no_default: Vec<_> = TARGETS.iter().filter(|&&t| t != "i686-apple-darwin").copied().collect();
310+
let tier_one_targets_no_default = TARGETS.iter().filter(|&&t| t != "i686-apple-darwin").copied().collect();
318311
assert_eq!(others, tier_one_targets_no_default);
319312
}
320313
}

src/docbuilder/rustwide_builder.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,13 @@ impl RustwideBuilder {
314314
let res = build_dir
315315
.build(&self.toolchain, &krate, sandbox)
316316
.run(|build| {
317+
use docbuilder::metadata::BuildTargets;
318+
317319
let mut files_list = None;
318320
let mut has_docs = false;
319321
let mut successful_targets = Vec::new();
320322
let metadata = Metadata::from_source_dir(&build.host_source_dir())?;
321-
let (default_target, other_targets) = metadata.targets();
323+
let BuildTargets { default_target, other_targets } = metadata.targets();
322324

323325
// Do an initial build and then copy the sources in the database
324326
let res = self.execute_build(default_target, true, &build, &limits, &metadata)?;

0 commit comments

Comments
 (0)