1use crate::core::compiler::BuildConfig;
2use crate::core::compiler::RustcTargetData;
3use crate::core::compiler::UserIntent;
4use crate::core::compiler::standard_lib;
5use crate::core::{PackageSet, Resolve, Workspace};
6use crate::ops;
7use crate::util::CargoResult;
8use crate::util::GlobalContext;
9use crate::util::context::JobsConfig;
10use crate::util::context::WarningHandling;
11use crate::util::data_structures::HashSet;
12
13pub struct FetchOptions<'a> {
14 pub gctx: &'a GlobalContext,
15 pub targets: Vec<String>,
17}
18
19pub fn fetch<'a>(
21 ws: &Workspace<'a>,
22 options: &FetchOptions<'a>,
23) -> CargoResult<(Resolve, PackageSet<'a>)> {
24 let parse_pass_output = crate::diagnostics::passes::emit_parse_diagnostics(
25 ws,
26 crate::diagnostics::rules::PARSE_PASS_RULES,
27 )?;
28 let dry_run = false;
29 let (mut packages, resolve) = ops::resolve_ws(ws, dry_run)?;
30
31 let jobs = Some(JobsConfig::Integer(1));
32 let keep_going = false;
33 let gctx = ws.gctx();
34 let build_config =
35 BuildConfig::new(gctx, jobs, keep_going, &options.targets, UserIntent::Build)?;
36 let mut data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
37 let mut fetched_packages = HashSet::default();
38 let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
39 let mut to_download = Vec::new();
40
41 while let Some(id) = deps_to_fetch.pop() {
42 if !fetched_packages.insert(id) {
43 continue;
44 }
45
46 to_download.push(id);
47 let deps = resolve
48 .deps(id)
49 .filter(|&(_id, deps)| {
50 deps.iter().any(|d| {
51 if options.targets.is_empty() {
54 return true;
55 }
56
57 build_config
63 .requested_kinds
64 .iter()
65 .any(|kind| data.dep_platform_activated(d, *kind))
66 })
67 })
68 .map(|(id, _deps)| id);
69 deps_to_fetch.extend(deps);
70 }
71
72 if let Some(crates) = &gctx.cli_unstable().build_std {
74 let (std_package_set, _, _) = standard_lib::resolve_std(
75 ws,
76 &mut data,
77 &build_config,
78 crates,
79 &build_config.requested_kinds,
80 )?;
81 packages.add_set(std_package_set);
82 }
83
84 packages.get_many(to_download)?;
85 crate::core::gc::auto_gc(gctx);
86
87 if ws.gctx().warning_handling()? == WarningHandling::Deny
88 && parse_pass_output.lint_warning_count > 0
89 {
90 anyhow::bail!("warnings are denied by `build.warnings` configuration")
91 }
92
93 Ok((resolve, packages))
94}