xref: /aosp_15_r20/tools/asuite/adevice/src/cli.rs (revision c2e18aaa1096c836b086f94603d04f4eb9cf37f5)
1*c2e18aaaSAndroid Build Coastguard Worker use clap::{Args, Parser, Subcommand};
2*c2e18aaaSAndroid Build Coastguard Worker 
3*c2e18aaaSAndroid Build Coastguard Worker #[derive(Parser)]
4*c2e18aaaSAndroid Build Coastguard Worker #[command(
5*c2e18aaaSAndroid Build Coastguard Worker     about = "Tool to push your rebuilt modules to your device.\nSet ANDROID_SERIAL to choose your device if there is more than one."
6*c2e18aaaSAndroid Build Coastguard Worker )]
7*c2e18aaaSAndroid Build Coastguard Worker #[command(version = "0.4")]
8*c2e18aaaSAndroid Build Coastguard Worker pub struct Cli {
9*c2e18aaaSAndroid Build Coastguard Worker     #[command(subcommand)]
10*c2e18aaaSAndroid Build Coastguard Worker     pub command: Commands,
11*c2e18aaaSAndroid Build Coastguard Worker     #[clap(flatten)]
12*c2e18aaaSAndroid Build Coastguard Worker     pub global_options: GlobalOptions,
13*c2e18aaaSAndroid Build Coastguard Worker }
14*c2e18aaaSAndroid Build Coastguard Worker 
15*c2e18aaaSAndroid Build Coastguard Worker #[derive(Subcommand)]
16*c2e18aaaSAndroid Build Coastguard Worker pub enum Commands {
17*c2e18aaaSAndroid Build Coastguard Worker     /// Shows the file differences between build tree and host.
18*c2e18aaaSAndroid Build Coastguard Worker     /// Show the actions that would be run.
19*c2e18aaaSAndroid Build Coastguard Worker     Status,
20*c2e18aaaSAndroid Build Coastguard Worker     /// Updates the device (via adb push) with files from $ANDROID_PRODUCT_OUT.
21*c2e18aaaSAndroid Build Coastguard Worker     /// Only pushes files listed on --partitions.
22*c2e18aaaSAndroid Build Coastguard Worker     /// This does not work well when $ANDROID_PRODUCT_OUT and the device image
23*c2e18aaaSAndroid Build Coastguard Worker     /// are vastly different.  You should reimage the device in that case.
24*c2e18aaaSAndroid Build Coastguard Worker     Update,
25*c2e18aaaSAndroid Build Coastguard Worker     /// Adds module name to the list of tracked modules.
26*c2e18aaaSAndroid Build Coastguard Worker     /// If an installed file under $ANDROID_PRODUCT_OUT is not
27*c2e18aaaSAndroid Build Coastguard Worker     /// part of a tracked module or the base image, then it will
28*c2e18aaaSAndroid Build Coastguard Worker     /// not be pushed to the device.
29*c2e18aaaSAndroid Build Coastguard Worker     Track(ModuleNames),
30*c2e18aaaSAndroid Build Coastguard Worker     /// Change the base module we are tracking from `droid` to something else.
31*c2e18aaaSAndroid Build Coastguard Worker     TrackBase(BaseModule),
32*c2e18aaaSAndroid Build Coastguard Worker     /// Removes module name from list of tracked modules.
33*c2e18aaaSAndroid Build Coastguard Worker     /// See `track` for more details.
34*c2e18aaaSAndroid Build Coastguard Worker     Untrack(ModuleNames),
35*c2e18aaaSAndroid Build Coastguard Worker     /// Removes untracked files from the device.
36*c2e18aaaSAndroid Build Coastguard Worker     Clean {
37*c2e18aaaSAndroid Build Coastguard Worker         #[clap(long, short)]
38*c2e18aaaSAndroid Build Coastguard Worker         force: bool,
39*c2e18aaaSAndroid Build Coastguard Worker     },
40*c2e18aaaSAndroid Build Coastguard Worker }
41*c2e18aaaSAndroid Build Coastguard Worker 
42*c2e18aaaSAndroid Build Coastguard Worker #[derive(Debug, Args)]
43*c2e18aaaSAndroid Build Coastguard Worker pub struct ModuleNames {
44*c2e18aaaSAndroid Build Coastguard Worker     /// List one or modules, space separated.
45*c2e18aaaSAndroid Build Coastguard Worker     /// Use the module name in Android.bp
46*c2e18aaaSAndroid Build Coastguard Worker     pub modules: Vec<String>,
47*c2e18aaaSAndroid Build Coastguard Worker }
48*c2e18aaaSAndroid Build Coastguard Worker 
49*c2e18aaaSAndroid Build Coastguard Worker #[derive(Debug, Args)]
50*c2e18aaaSAndroid Build Coastguard Worker pub struct BaseModule {
51*c2e18aaaSAndroid Build Coastguard Worker     /// The module name the system image is built from like 'droid' or 'sync'.
52*c2e18aaaSAndroid Build Coastguard Worker     /// It can also be an unbundled mainline module name.
53*c2e18aaaSAndroid Build Coastguard Worker     pub base: String,
54*c2e18aaaSAndroid Build Coastguard Worker }
55*c2e18aaaSAndroid Build Coastguard Worker 
56*c2e18aaaSAndroid Build Coastguard Worker #[derive(Args, Debug)]
57*c2e18aaaSAndroid Build Coastguard Worker pub struct GlobalOptions {
58*c2e18aaaSAndroid Build Coastguard Worker     // TODO(rbraunstein): Revisit all the command name descriptions.
59*c2e18aaaSAndroid Build Coastguard Worker     // TODO(rbraunstein): Add system_other to the default list, but deal gracefully
60*c2e18aaaSAndroid Build Coastguard Worker     // with it not being on the device.
61*c2e18aaaSAndroid Build Coastguard Worker     /// Partitions in the product tree to sync. Repeat arg or comma-separate.
62*c2e18aaaSAndroid Build Coastguard Worker     ///
63*c2e18aaaSAndroid Build Coastguard Worker     /// By default this includes: "system", "system_ext", "odm", "product"
64*c2e18aaaSAndroid Build Coastguard Worker     ///
65*c2e18aaaSAndroid Build Coastguard Worker     /// If a partition is explicitly passed in but that does not exist in the
66*c2e18aaaSAndroid Build Coastguard Worker     /// tracked files then adevice will error.
67*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long, short, global = true, value_delimiter = ',')]
68*c2e18aaaSAndroid Build Coastguard Worker     pub partitions: Option<Vec<String>>,
69*c2e18aaaSAndroid Build Coastguard Worker     // TODO(rbraunstein): Validate relative, not absolute paths.
70*c2e18aaaSAndroid Build Coastguard Worker     /// If unset defaults to ANDROID_PRODUCT_OUT env variable.
71*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long = "product_out", global = true)]
72*c2e18aaaSAndroid Build Coastguard Worker     pub product_out: Option<String>,
73*c2e18aaaSAndroid Build Coastguard Worker     /// Do not make any modification if more than this many are needed
74*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long, short, default_value_t = 400, global = true)]
75*c2e18aaaSAndroid Build Coastguard Worker     pub max_allowed_changes: usize,
76*c2e18aaaSAndroid Build Coastguard Worker     /// If passed, use the device, otherwise use the only connected device or ANDROID_SERIAL env value.
77*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long, short, global = true)]
78*c2e18aaaSAndroid Build Coastguard Worker     pub serial: Option<String>,
79*c2e18aaaSAndroid Build Coastguard Worker     /// Override the type of restart that happens after an update.
80*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long = "restart", short, global = true, value_enum, default_value_t=RestartChoice::Auto)]
81*c2e18aaaSAndroid Build Coastguard Worker     pub restart_choice: RestartChoice,
82*c2e18aaaSAndroid Build Coastguard Worker     /// Path to config file.  Uses $HOME/.config/asuite/adevice-tracking.json if unset.
83*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long = "config", global = true)]
84*c2e18aaaSAndroid Build Coastguard Worker     pub config_path: Option<String>,
85*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long = "force", global = true, alias = "force", alias = "force")]
86*c2e18aaaSAndroid Build Coastguard Worker     // Force device update even if unbuilt modules are detected.
87*c2e18aaaSAndroid Build Coastguard Worker     pub force: bool,
88*c2e18aaaSAndroid Build Coastguard Worker     // Don't wait for device to become available after restarting it.
89*c2e18aaaSAndroid Build Coastguard Worker     #[clap(long = "nowait", global = true, alias = "no_wait", alias = "no-wait")]
90*c2e18aaaSAndroid Build Coastguard Worker     pub nowait: bool,
91*c2e18aaaSAndroid Build Coastguard Worker }
92*c2e18aaaSAndroid Build Coastguard Worker 
93*c2e18aaaSAndroid Build Coastguard Worker #[derive(clap::ValueEnum, Clone, Debug)]
94*c2e18aaaSAndroid Build Coastguard Worker pub enum Verbosity {
95*c2e18aaaSAndroid Build Coastguard Worker     /// Only show minimal information.
96*c2e18aaaSAndroid Build Coastguard Worker     None,
97*c2e18aaaSAndroid Build Coastguard Worker     /// Show all adb operations.
98*c2e18aaaSAndroid Build Coastguard Worker     Details,
99*c2e18aaaSAndroid Build Coastguard Worker     /// For debugging internals of tool and timings.
100*c2e18aaaSAndroid Build Coastguard Worker     Debug,
101*c2e18aaaSAndroid Build Coastguard Worker }
102*c2e18aaaSAndroid Build Coastguard Worker 
103*c2e18aaaSAndroid Build Coastguard Worker /// Allows you to choose how to reboot or to not reboot.
104*c2e18aaaSAndroid Build Coastguard Worker #[derive(clap::ValueEnum, Clone, Debug)]
105*c2e18aaaSAndroid Build Coastguard Worker pub enum RestartChoice {
106*c2e18aaaSAndroid Build Coastguard Worker     /// Let the system choose the restart based on the files changed.
107*c2e18aaaSAndroid Build Coastguard Worker     Auto,
108*c2e18aaaSAndroid Build Coastguard Worker     /// Don't restart.
109*c2e18aaaSAndroid Build Coastguard Worker     None,
110*c2e18aaaSAndroid Build Coastguard Worker     /// Always do a full system reboot after updates.
111*c2e18aaaSAndroid Build Coastguard Worker     Reboot,
112*c2e18aaaSAndroid Build Coastguard Worker     /// Always do a framework restart restart after updates.
113*c2e18aaaSAndroid Build Coastguard Worker     Restart,
114*c2e18aaaSAndroid Build Coastguard Worker }
115*c2e18aaaSAndroid Build Coastguard Worker 
116*c2e18aaaSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq)]
117*c2e18aaaSAndroid Build Coastguard Worker pub enum Wait {
118*c2e18aaaSAndroid Build Coastguard Worker     Yes,
119*c2e18aaaSAndroid Build Coastguard Worker     No,
120*c2e18aaaSAndroid Build Coastguard Worker }
121*c2e18aaaSAndroid Build Coastguard Worker 
122*c2e18aaaSAndroid Build Coastguard Worker impl From<Wait> for bool {
from(w: Wait) -> bool123*c2e18aaaSAndroid Build Coastguard Worker     fn from(w: Wait) -> bool {
124*c2e18aaaSAndroid Build Coastguard Worker         match w {
125*c2e18aaaSAndroid Build Coastguard Worker             Wait::Yes => true,
126*c2e18aaaSAndroid Build Coastguard Worker             Wait::No => false,
127*c2e18aaaSAndroid Build Coastguard Worker         }
128*c2e18aaaSAndroid Build Coastguard Worker     }
129*c2e18aaaSAndroid Build Coastguard Worker }
130*c2e18aaaSAndroid Build Coastguard Worker 
131*c2e18aaaSAndroid Build Coastguard Worker impl Cli {
132*c2e18aaaSAndroid Build Coastguard Worker     /// Decide if the options indicate that we should wait for the device.
133*c2e18aaaSAndroid Build Coastguard Worker     /// Exists in case the cli options get more complicated like --wait=false
should_wait(&self) -> Wait134*c2e18aaaSAndroid Build Coastguard Worker     pub fn should_wait(&self) -> Wait {
135*c2e18aaaSAndroid Build Coastguard Worker         match self.global_options.nowait {
136*c2e18aaaSAndroid Build Coastguard Worker             true => Wait::No,
137*c2e18aaaSAndroid Build Coastguard Worker             false => Wait::Yes,
138*c2e18aaaSAndroid Build Coastguard Worker         }
139*c2e18aaaSAndroid Build Coastguard Worker     }
140*c2e18aaaSAndroid Build Coastguard Worker }
141*c2e18aaaSAndroid Build Coastguard Worker 
142*c2e18aaaSAndroid Build Coastguard Worker #[cfg(test)]
143*c2e18aaaSAndroid Build Coastguard Worker mod tests {
144*c2e18aaaSAndroid Build Coastguard Worker     use crate::cli::Wait;
145*c2e18aaaSAndroid Build Coastguard Worker 
146*c2e18aaaSAndroid Build Coastguard Worker     use super::Cli;
147*c2e18aaaSAndroid Build Coastguard Worker     use clap::Parser;
148*c2e18aaaSAndroid Build Coastguard Worker 
149*c2e18aaaSAndroid Build Coastguard Worker     #[test]
force_default_false()150*c2e18aaaSAndroid Build Coastguard Worker     fn force_default_false() {
151*c2e18aaaSAndroid Build Coastguard Worker         let cli = Cli::parse_from(["fake_prog", "update"]);
152*c2e18aaaSAndroid Build Coastguard Worker         assert!(!cli.global_options.force);
153*c2e18aaaSAndroid Build Coastguard Worker     }
154*c2e18aaaSAndroid Build Coastguard Worker 
155*c2e18aaaSAndroid Build Coastguard Worker     #[test]
force_works()156*c2e18aaaSAndroid Build Coastguard Worker     fn force_works() {
157*c2e18aaaSAndroid Build Coastguard Worker         let cli = Cli::parse_from(["fake_prog", "update", "--force"]);
158*c2e18aaaSAndroid Build Coastguard Worker         assert!(cli.global_options.force);
159*c2e18aaaSAndroid Build Coastguard Worker     }
160*c2e18aaaSAndroid Build Coastguard Worker 
161*c2e18aaaSAndroid Build Coastguard Worker     #[test]
nowait_works()162*c2e18aaaSAndroid Build Coastguard Worker     fn nowait_works() {
163*c2e18aaaSAndroid Build Coastguard Worker         let cli = Cli::parse_from(["fake_prog", "update", "--nowait"]);
164*c2e18aaaSAndroid Build Coastguard Worker         assert!(cli.global_options.nowait);
165*c2e18aaaSAndroid Build Coastguard Worker     }
166*c2e18aaaSAndroid Build Coastguard Worker 
167*c2e18aaaSAndroid Build Coastguard Worker     #[test]
no_wait_alias_works()168*c2e18aaaSAndroid Build Coastguard Worker     fn no_wait_alias_works() {
169*c2e18aaaSAndroid Build Coastguard Worker         let cli = Cli::parse_from(["fake_prog", "update", "--no_wait"]);
170*c2e18aaaSAndroid Build Coastguard Worker         assert!(cli.global_options.nowait);
171*c2e18aaaSAndroid Build Coastguard Worker     }
172*c2e18aaaSAndroid Build Coastguard Worker 
173*c2e18aaaSAndroid Build Coastguard Worker     #[test]
unset_nowait_is_none()174*c2e18aaaSAndroid Build Coastguard Worker     fn unset_nowait_is_none() {
175*c2e18aaaSAndroid Build Coastguard Worker         let cli = Cli::parse_from(["fake_prog", "update"]);
176*c2e18aaaSAndroid Build Coastguard Worker         assert!(!cli.global_options.nowait);
177*c2e18aaaSAndroid Build Coastguard Worker     }
178*c2e18aaaSAndroid Build Coastguard Worker 
179*c2e18aaaSAndroid Build Coastguard Worker     #[test]
it_should_wait()180*c2e18aaaSAndroid Build Coastguard Worker     fn it_should_wait() {
181*c2e18aaaSAndroid Build Coastguard Worker         let cli = Cli::parse_from(["fake_prog", "update"]);
182*c2e18aaaSAndroid Build Coastguard Worker         assert_eq!(Wait::Yes, cli.should_wait());
183*c2e18aaaSAndroid Build Coastguard Worker         let should_wait: bool = cli.should_wait().into();
184*c2e18aaaSAndroid Build Coastguard Worker         assert!(should_wait);
185*c2e18aaaSAndroid Build Coastguard Worker     }
186*c2e18aaaSAndroid Build Coastguard Worker 
187*c2e18aaaSAndroid Build Coastguard Worker     #[test]
it_should_not_wait()188*c2e18aaaSAndroid Build Coastguard Worker     fn it_should_not_wait() {
189*c2e18aaaSAndroid Build Coastguard Worker         let cli = Cli::parse_from(["fake_prog", "update", "--nowait"]);
190*c2e18aaaSAndroid Build Coastguard Worker         assert_eq!(Wait::No, cli.should_wait());
191*c2e18aaaSAndroid Build Coastguard Worker         let should_wait: bool = cli.should_wait().into();
192*c2e18aaaSAndroid Build Coastguard Worker         assert!(!should_wait);
193*c2e18aaaSAndroid Build Coastguard Worker     }
194*c2e18aaaSAndroid Build Coastguard Worker }
195