Skip to main content

cargo/ops/
cargo_fetch.rs

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 std::collections::HashSet;
11
12pub struct FetchOptions<'a> {
13    pub gctx: &'a GlobalContext,
14    /// The target arch triple to fetch dependencies for
15    pub targets: Vec<String>,
16}
17
18/// Executes `cargo fetch`.
19pub fn fetch<'a>(
20    ws: &Workspace<'a>,
21    options: &FetchOptions<'a>,
22) -> CargoResult<(Resolve, PackageSet<'a>)> {
23    crate::diagnostics::passes::emit_parse_diagnostics(
24        ws,
25        crate::diagnostics::rules::PARSE_PASS_RULES,
26    )?;
27    let dry_run = false;
28    let (mut packages, resolve) = ops::resolve_ws(ws, dry_run)?;
29
30    let jobs = Some(JobsConfig::Integer(1));
31    let keep_going = false;
32    let gctx = ws.gctx();
33    let build_config =
34        BuildConfig::new(gctx, jobs, keep_going, &options.targets, UserIntent::Build)?;
35    let mut data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
36    let mut fetched_packages = HashSet::new();
37    let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
38    let mut to_download = Vec::new();
39
40    while let Some(id) = deps_to_fetch.pop() {
41        if !fetched_packages.insert(id) {
42            continue;
43        }
44
45        to_download.push(id);
46        let deps = resolve
47            .deps(id)
48            .filter(|&(_id, deps)| {
49                deps.iter().any(|d| {
50                    // If no target was specified then all dependencies are
51                    // fetched.
52                    if options.targets.is_empty() {
53                        return true;
54                    }
55
56                    // Otherwise we only download this dependency if any of the
57                    // requested platforms would match this dependency. Note
58                    // that this is a bit lossy because not all dependencies are
59                    // always compiled for all platforms, but it should be
60                    // "close enough" for now.
61                    build_config
62                        .requested_kinds
63                        .iter()
64                        .any(|kind| data.dep_platform_activated(d, *kind))
65                })
66            })
67            .map(|(id, _deps)| id);
68        deps_to_fetch.extend(deps);
69    }
70
71    // If -Zbuild-std was passed, download dependencies for the standard library.
72    if let Some(crates) = &gctx.cli_unstable().build_std {
73        let (std_package_set, _, _) = standard_lib::resolve_std(
74            ws,
75            &mut data,
76            &build_config,
77            crates,
78            &build_config.requested_kinds,
79        )?;
80        packages.add_set(std_package_set);
81    }
82
83    packages.get_many(to_download)?;
84    crate::core::gc::auto_gc(gctx);
85
86    Ok((resolve, packages))
87}