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}