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