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