Skip to main content

cargo/ops/
cargo_fetch.rs

1use crate::core::compiler::{BuildConfig, CompileMode, TargetInfo};
2use crate::core::{PackageSet, Resolve, Workspace};
3use crate::ops;
4use crate::util::CargoResult;
5use crate::util::Config;
6use std::collections::HashSet;
7
8pub struct FetchOptions<'a> {
9    pub config: &'a Config,
10    /// The target arch triple to fetch dependencies for
11    pub target: Option<String>,
12}
13
14/// Executes `cargo fetch`.
15pub fn fetch<'a>(
16    ws: &Workspace<'a>,
17    options: &FetchOptions<'a>,
18) -> CargoResult<(Resolve, PackageSet<'a>)> {
19    ws.emit_warnings()?;
20    let (packages, resolve) = ops::resolve_ws(ws)?;
21
22    let jobs = Some(1);
23    let config = ws.config();
24    let build_config = BuildConfig::new(config, jobs, &options.target, CompileMode::Build)?;
25    let rustc = config.load_global_rustc(Some(ws))?;
26    let target_info = TargetInfo::new(
27        config,
28        build_config.requested_kind,
29        &rustc,
30        build_config.requested_kind,
31    )?;
32    let mut fetched_packages = HashSet::new();
33    let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
34    let mut to_download = Vec::new();
35
36    while let Some(id) = deps_to_fetch.pop() {
37        if !fetched_packages.insert(id) {
38            continue;
39        }
40
41        to_download.push(id);
42        let deps = resolve
43            .deps(id)
44            .filter(|&(_id, deps)| {
45                deps.iter().any(|d| {
46                    // If no target was specified then all dependencies can
47                    // be fetched.
48                    let target = match options.target {
49                        Some(ref t) => t,
50                        None => return true,
51                    };
52                    // If this dependency is only available for certain
53                    // platforms, make sure we're only fetching it for that
54                    // platform.
55                    let platform = match d.platform() {
56                        Some(p) => p,
57                        None => return true,
58                    };
59                    platform.matches(target, target_info.cfg())
60                })
61            })
62            .map(|(id, _deps)| id);
63        deps_to_fetch.extend(deps);
64    }
65    packages.get_many(to_download)?;
66
67    Ok((resolve, packages))
68}