cargo_flutter/
cargo.rs

1use crate::error::Error;
2use cargo::core::{Package, Workspace};
3use cargo::util::important_paths::find_root_manifest_for_wd;
4use cargo::util::Config;
5use std::path::PathBuf;
6use std::process::Command;
7
8pub struct Cargo<'a> {
9    args: Vec<&'a str>,
10    workspace: Workspace<'a>,
11}
12
13impl<'a> Cargo<'a> {
14    pub fn new(config: &'a mut Config, args: Vec<&'a str>) -> Result<Self, Error> {
15        let root_manifest = find_root_manifest_for_wd(config.cwd())?;
16        let target_dir = root_manifest
17            .parent()
18            .unwrap()
19            .join("target")
20            .join("flutter");
21        config
22            .configure(0, None, &None, false, false, false, &Some(target_dir), &[])
23            .unwrap();
24
25        let workspace = Workspace::new(&root_manifest, config)?;
26        Ok(Self { args, workspace })
27    }
28
29    fn arg<F: Fn(&str) -> bool>(&self, matches: F) -> Option<&str> {
30        self.args
31            .iter()
32            .position(|f| matches(f))
33            .map(|pos| self.args.get(pos + 1))
34            .unwrap_or_default()
35            .cloned()
36    }
37
38    pub fn cmd(&self) -> &str {
39        self.args.iter().next().expect("Expected command")
40    }
41
42    pub fn target(&self) -> Option<&str> {
43        self.arg(|f| f == "--target")
44    }
45
46    pub fn package(&self) -> Result<&Package, Error> {
47        Ok(
48            if let Some(package) = self.arg(|f| f == "--package" || f == "-p") {
49                self.workspace()
50                    .members()
51                    .find(|pkg| pkg.name().as_str() == package)
52                    .ok_or(Error::PackageNotMember)?
53            } else {
54                self.workspace().current()?
55            },
56        )
57    }
58
59    pub fn release(&self) -> bool {
60        self.args.iter().any(|f| *f == "--release")
61    }
62
63    pub fn host_triple(&self) -> Result<String, Error> {
64        let rustc = self
65            .workspace
66            .config()
67            .load_global_rustc(Some(&self.workspace))?;
68        Ok(rustc.host.as_str().to_string())
69    }
70
71    pub fn target_triple(&self) -> Result<String, Error> {
72        if let Some(target) = self.target() {
73            Ok(target.to_string())
74        } else {
75            self.host_triple()
76        }
77    }
78
79    pub fn workspace(&self) -> &Workspace {
80        &self.workspace
81    }
82
83    pub fn target_dir(&self) -> PathBuf {
84        self.workspace().target_dir().into_path_unlocked()
85    }
86
87    pub fn build_dir(&self) -> PathBuf {
88        let flutter_dir = self.target_dir();
89        let triple_dir = if let Some(target) = self.target() {
90            flutter_dir.join(target)
91        } else {
92            flutter_dir
93        };
94        if self.release() {
95            triple_dir.join("release")
96        } else {
97            triple_dir.join("debug")
98        }
99    }
100
101    fn cargo_command(&self) -> Command {
102        let mut cmd = Command::new("cargo");
103        cmd.current_dir(self.workspace.config().cwd())
104            .args(&self.args)
105            .arg("--target-dir")
106            .arg(self.target_dir());
107        cmd
108    }
109
110    pub fn exec(&self) -> Result<(), Error> {
111        let status = self.cargo_command().status().expect("Success");
112        if status.code() != Some(0) {
113            return Err(Error::CargoError);
114        }
115        Ok(())
116    }
117
118    pub fn spawn(&self) -> Result<(), Error> {
119        self.cargo_command().spawn().expect("Success");
120        Ok(())
121    }
122}