Improvement/Add logging (closes #2, #3, #25)

This commit is contained in:
w1nst0n 2021-09-16 14:43:15 +02:00
commit e095d48e71
No known key found for this signature in database
GPG key ID: 34D27465928A0A1D
9 changed files with 201 additions and 32 deletions

View file

@ -10,3 +10,13 @@ and `Removed`.
## [Unreleased]
### Added
- UAD now comes with a logger. Debug information will be written to a `uad.log` file (Warning level log in *stdout*) (#2)
### Changed
- UAD will no longer crash at start if it doesn't find ADB but display a useful message (#25)
- Better handling of ADB errors (#3)
### Fixed
- Spelling mistake
-

68
Cargo.lock generated
View file

@ -85,6 +85,17 @@ dependencies = [
"libloading 0.7.0",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
@ -196,6 +207,19 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
name = "clipboard-win"
version = "4.2.1"
@ -287,6 +311,17 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "colored"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
dependencies = [
"atty",
"lazy_static",
"winapi",
]
[[package]]
name = "copyless"
version = "0.1.5"
@ -654,6 +689,16 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "fern"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9a4820f0ccc8a7afd67c39a0f1a0f4b07ca1725164271a64939d7aeb9af065"
dependencies = [
"colored",
"log",
]
[[package]]
name = "fixedbitset"
version = "0.4.0"
@ -1526,6 +1571,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
@ -2301,6 +2356,16 @@ dependencies = [
"syn",
]
[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "tiny-skia"
version = "0.2.0"
@ -2371,7 +2436,10 @@ dependencies = [
name = "uad_gui"
version = "0.1.0"
dependencies = [
"chrono",
"fern",
"iced",
"log",
"serde",
"serde_json",
"static_init",

View file

@ -11,6 +11,9 @@ iced = { git = "https://github.com/hecrj/iced.git", features = ["svg"] }
serde = { version = "^1.0", features = ["derive"] }
serde_json = "^1.0"
static_init = "^1.0"
fern = { version = "^0.6", features = ["colored"] }
log = "^0.4"
chrono = "^0.4"
[profile.release]
opt-level = "s"

View file

@ -1,5 +1,6 @@
use std::process::Command;
use std::collections::HashSet;
use crate::core::uad_lists::Removal;
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;
@ -11,26 +12,34 @@ pub fn adb_shell_command(args: &str) -> Result<String,String> {
let output = Command::new("adb")
.args(&["shell", args])
.creation_flags(0x08000000) // do not open a cmd window
.output()
.expect("adb command failed to start. Do you have ADB installed?");
.output();
#[cfg(target_os = "macos")]
let output = Command::new("adb")
.args(&["shell", args])
.output()
.expect("adb command failed to start. Do you have ADB installed?");
.output();
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
let output = Command::new("adb")
.args(&["shell", args])
.output()
.expect("adb command failed to start. Do you have ADB installed?");
.output();
if !output.status.success() {
Err(String::from_utf8(output.stderr).unwrap())
} else {
Ok(String::from_utf8(output.stdout).unwrap())
}
match output {
Err(e) => {
error!("ADB: {}", e);
Err("ADB was not found".to_string())
},
Ok(o) => {
if !o.status.success() {
let stderr = String::from_utf8(o.stderr).unwrap().trim_end().to_string();
error!("ADB: {}", stderr);
Err(stderr)
} else {
Ok(String::from_utf8(o.stdout).unwrap().trim_end().to_string())
}
}
}
}
@ -42,33 +51,46 @@ pub fn list_all_system_packages() -> String {
}
pub fn hashset_installed_system_packages() -> HashSet<String> {
let hashet: HashSet<String> = adb_shell_command("pm list packages -s")
adb_shell_command("pm list packages -s")
.unwrap_or("".to_string())
.replace("package:", "")
.lines()
.map(String::from)
.collect();
hashet
.collect()
}
pub fn uninstall_package(package: String) -> String {
pub fn uninstall_package(package: String, removal: Removal) {
let arg = "pm uninstall --user 0 ".to_string() + &package;
let output = adb_shell_command(&arg).unwrap();
if output.contains("Success") {
info!("REMOVE [{}]: {}", removal, package);
} else {
error!("REMOVE [{}]: {}", removal, output);
}
adb_shell_command(&arg).unwrap()
}
pub fn restore_package(package: String) -> String {
pub fn restore_package(package: String, removal: Removal) {
let arg = "cmd package install-existing --user 0 ".to_string() + &package;
let output = adb_shell_command(&arg).unwrap();
if output.contains("installed for user") {
info!("RESTORE [{}]: {}", removal, package);
} else {
error!("RESTORE: {} -- ", output);
}
adb_shell_command(&arg).unwrap()
}
pub fn get_phone_model() -> String {
match adb_shell_command("getprop ro.product.model") {
Ok(model) => model,
Ok(model) => {
model
},
Err(err) => {
if err.contains("adb: no devices/emulators found") {
"adb: no devices/emulators found".to_string()

View file

@ -107,6 +107,8 @@ impl Application for UadGui {
UadGui::Loaded(state) => match message {
Message::CatalogRefreshPress => {
state.list_view = ListView::default();
state.device_name = get_phone_brand();
info!("PHONE_MODEL: {}", state.device_name);
state.list_view.update(ListMessage::LoadSettings(state.settings_view.clone()));
state.view = View::List;
Command::perform(Self::load_phone_packages(), Message::CatalogAction)
@ -121,7 +123,6 @@ impl Application for UadGui {
Command::none()
}
Message::CatalogAction(msg) => {
state.device_name = get_phone_brand();
state.list_view.update(msg).map(Message::CatalogAction)
}
Message::SettingsAction(msg) => {
@ -238,6 +239,7 @@ impl UadGui {
State::default()
}
pub async fn load_phone_packages() -> ListMessage {
info!("PHONE_MODEL: {}", get_phone_brand());
ListMessage::LoadPackages(&UAD_LISTS)
}
}

View file

@ -19,6 +19,7 @@ use crate::core::sync::{
pub struct SelectionPackage {
pub name: String,
pub state: PackageState,
pub removal: Removal,
}
#[derive(Default, Debug, Clone)]
@ -138,7 +139,8 @@ impl List {
self.selected_packages.push(
SelectionPackage {
name: self.filtered_packages[i].name.clone(),
state: self.filtered_packages[i].state
state: self.filtered_packages[i].state,
removal: self.filtered_packages[i].removal,
}
);
} else {
@ -170,17 +172,20 @@ impl List {
Message::ApplyActionOnSelection => {
for p in &self.selected_packages {
match p.state {
PackageState::Installed => uninstall_package(p.name.clone()),
PackageState::Uninstalled => restore_package(p.name.clone()),
PackageState::All => "[DEBUG] ApplySelectionAction: Unknown package state".to_string(), // This can't happen
PackageState::Installed => uninstall_package(p.name.clone(), p.removal),
PackageState::Uninstalled => restore_package(p.name.clone(), p.removal),
PackageState::All => error!("ApplySelectionAction: Unknown package state"), // This can't happen
};
for phone_p in &mut self.phone_packages {
if p.name == phone_p.name {
phone_p.state = match phone_p.state {
PackageState::Installed => PackageState::Uninstalled,
PackageState::Uninstalled => PackageState::Installed,
PackageState::All => PackageState::All, // This can't happen (Like... never)
PackageState::Uninstalled => PackageState::Installed,
PackageState::All => {
error!("ApplyActionOnSelection: Unknown package state");
PackageState::All // This can't happen (like... never)
}
};
break
}
@ -193,7 +198,7 @@ impl List {
let mut package;
for p in &mut self.filtered_packages {
p.selected = true;
package = SelectionPackage { name: p.name.clone(), state: p.state };
package = SelectionPackage { name: p.name.clone(), state: p.state, removal: p.removal };
if !self.selected_packages.contains(&package) {
self.selected_packages.push(package);
}
@ -408,13 +413,13 @@ impl PackageRow {
pub fn update(&mut self, message: RowMessage) -> Command<RowMessage> {
match message {
RowMessage::RemovePressed(package) => {
uninstall_package(package.name);
uninstall_package(package.name, self.removal);
self.state = PackageState::Uninstalled;
self.selected = false;
Command::none()
}
RowMessage::RestorePressed(package) => {
restore_package(package.name);
restore_package(package.name, self.removal);
self.state = PackageState::Installed;
self.selected = false;
Command::none()

View file

@ -1,4 +1,3 @@
pub mod list;
pub mod package;
pub mod settings;
pub mod about;

View file

@ -24,6 +24,7 @@ impl Settings {
pub fn update(&mut self, msg: Message) {
match msg {
Message::ExpertModeToogle(toggled) => {
info!("Expert mode {}", if toggled {"enabled"} else {"disabled"});
self.expert_mode = toggled;
}
}

View file

@ -1,9 +1,68 @@
#![windows_subsystem = "windows"]
#![feature(drain_filter)]
#[macro_use] extern crate log;
use chrono;
use std::{fs::OpenOptions, fmt::Arguments};
use fern::{FormatCallback, colors::{Color, ColoredLevelConfig}};
use log::Record;
mod core;
mod gui;
fn main() {
setup_logger().expect("setup logging");
gui::UadGui::start();
}
pub fn setup_logger() -> Result<(), fern::InitError> {
let colors = ColoredLevelConfig::new().info(Color::Green);
let make_formatter = |use_colors: bool| {
move |out: FormatCallback, message: &Arguments, record: &Record| {
out.finish(format_args!(
"{} {} [{}:{}] {}",
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
if use_colors {
format!("{:5}", colors.color(record.level()))
} else {
format!("{:5}", record.level().to_string())
},
record.file().unwrap_or("?".into()),
record
.line()
.map(|l| l.to_string())
.unwrap_or(String::new()),
message
))
}
};
let default_log_level = log::LevelFilter::Warn;
let log_file = OpenOptions::new()
.write(true)
.create(true)
.append(false)
.truncate(true)
.open("uad.log")?;
let file_dispatcher = fern::Dispatch::new()
.format(make_formatter(false))
.level(default_log_level)
.level_for("uad_gui", log::LevelFilter::Debug)
.chain(log_file);
let stdout_dispatcher = fern::Dispatch::new()
.format(make_formatter(true))
.level(default_log_level)
.level_for("uad_gui", log::LevelFilter::Warn)
.chain(std::io::stdout());
fern::Dispatch::new()
.chain(stdout_dispatcher)
.chain(file_dispatcher)
.apply()?;
Ok(())
}