Skip to content

Commit f9f8212

Browse files
authored
Merge pull request #894 from Universal-Debloater-Alliance/feat/gui/adb-v__893
feat(GUI:view:about): show `adb version`
2 parents be39579 + adeed4c commit f9f8212

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

src/core/adb.rs

+60-1
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,15 @@ pub fn to_trimmed_utf8(v: Vec<u8>) -> String {
6363
pub struct ACommand(std::process::Command);
6464
impl ACommand {
6565
/// `adb` command builder
66+
#[must_use]
6667
pub fn new() -> Self {
6768
Self(std::process::Command::new("adb"))
6869
}
70+
6971
/// `shell` sub-command builder.
7072
///
7173
/// If `device_serial` is empty, it lets ADB choose the default device.
74+
#[must_use]
7275
pub fn shell<S: AsRef<str>>(mut self, device_serial: S) -> ShellCommand {
7376
let serial = device_serial.as_ref();
7477
if !serial.is_empty() {
@@ -77,6 +80,7 @@ impl ACommand {
7780
self.0.arg("shell");
7881
ShellCommand(self)
7982
}
83+
8084
/// Header-less list of attached devices (as serials) and their statuses:
8185
/// - USB
8286
/// - TCP/IP: WIFI, Ethernet, etc...
@@ -107,6 +111,61 @@ impl ACommand {
107111
})
108112
.collect())
109113
}
114+
115+
/// `version` sub-command, splitted by lines
116+
///
117+
/// ## Format
118+
/// This is just a sample,
119+
/// we don't know which guarantees are stable (yet):
120+
/// ```txt
121+
/// Android Debug Bridge version 1.0.41
122+
/// Version 34.0.5-debian
123+
/// Installed as /usr/lib/android-sdk/platform-tools/adb
124+
/// Running on Linux 6.12.12-amd64 (x86_64)
125+
/// ```
126+
///
127+
/// The expected format should be like:
128+
/// ```txt
129+
/// Android Debug Bridge version <num>.<num>.<num>
130+
/// Version <num>.<num>.<num>-<no spaces>
131+
/// Installed as <ANDROID_SDK_HOME>/platform-tools/adb[.exe]
132+
/// Running on <OS/kernel version> (<CPU arch>)
133+
/// ```
134+
pub fn version(mut self) -> Result<Vec<String>, String> {
135+
#[cfg(debug_assertions)]
136+
static TRIPLE: LazyLock<Regex> = LazyLock::new(|| {
137+
Regex::new(r"^Android Debug Bridge version \d+.\d+.\d+$")
138+
.unwrap_or_else(|_| unreachable!())
139+
});
140+
#[cfg(debug_assertions)]
141+
static DISTRO: LazyLock<Regex> = LazyLock::new(|| {
142+
Regex::new(r"^Version \d+.\d+.\d+-\S+$").unwrap_or_else(|_| unreachable!())
143+
});
144+
145+
self.0.arg("version");
146+
Ok(self
147+
.run()?
148+
.lines()
149+
.enumerate()
150+
// typically 5 allocs.
151+
// ideally 0, if we didn't use `lines`.
152+
.map(|(i, ln)| {
153+
debug_assert!(match i {
154+
0 => TRIPLE.is_match(ln),
155+
1 => DISTRO.is_match(ln),
156+
2 =>
157+
// missing test for valid path
158+
ln.starts_with("Installed as ")
159+
&& (ln.ends_with("adb") || ln.ends_with("adb.exe")),
160+
// missing test for x86/ARM (both 64b)
161+
3 => ln.starts_with("Running on "),
162+
_ => unreachable!("Expected < 5 lines"),
163+
});
164+
ln.to_string()
165+
})
166+
.collect())
167+
}
168+
110169
/// General executor
111170
fn run(self) -> Result<String, String> {
112171
let mut cmd = self.0;
@@ -118,7 +177,7 @@ impl ACommand {
118177
cmd.get_args()
119178
.map(|s| s.to_str().unwrap_or_else(|| unreachable!()))
120179
.collect::<Vec<_>>()
121-
.join("' '")
180+
.join(" ")
122181
);
123182
match cmd.output() {
124183
Err(e) => {

src/gui/views/about.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::CACHE_DIR;
2+
use crate::core::adb;
23
use crate::core::helpers::button_primary;
34
use crate::core::theme::Theme;
45
use crate::core::uad_lists::LIST_FNAME;
@@ -78,15 +79,39 @@ impl About {
7879
.spacing(10)
7980
.width(550);
8081

81-
#[cfg(feature = "self-update")]
82-
let update_column = column![uad_list_row, self_update_row]
82+
/*
83+
There's no need to fetch this info every time the view is updated,
84+
we could cache it in a `static` `LazyLock`.
85+
86+
But what if the system updates ADB while the app is running?
87+
the numbers will be out of sync!
88+
89+
However, the server will still be the "old" version
90+
until the next start
91+
*/
92+
let adb_version_text = text(
93+
adb::ACommand::new()
94+
.version()
95+
.map_err(|e| error!("{e}"))
96+
.ok()
97+
// 1st line is the relevant one.
98+
// 2nd could be useful, too
99+
.unwrap_or_default()[0]
100+
// there must be some way to avoid this...
101+
.clone(),
102+
)
103+
.width(250);
104+
let adb_version_row = row![adb_version_text]
83105
.align_items(Alignment::Center)
84-
.spacing(10);
106+
.width(550);
85107

86-
#[cfg(not(feature = "self-update"))]
87-
let update_column = column![uad_list_row]
88-
.align_items(Alignment::Center)
89-
.spacing(10);
108+
let update_column = if cfg!(feature = "self-update") {
109+
column![uad_list_row, self_update_row, adb_version_row]
110+
} else {
111+
column![uad_list_row, adb_version_row]
112+
}
113+
.align_items(Alignment::Center)
114+
.spacing(10);
90115

91116
let update_container = container(update_column)
92117
.width(Length::Fill)

0 commit comments

Comments
 (0)