Skip to content

Commit

Permalink
refactor: add a global DIRS variable
Browse files Browse the repository at this point in the history
To avoid passing dirs to every function, we add a global DIRS variable
to store the dirs.
  • Loading branch information
wangl-cc committed Nov 25, 2023
1 parent b054974 commit 628f5c0
Show file tree
Hide file tree
Showing 10 changed files with 296 additions and 267 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions maa-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ paste = "1"
anyhow = "1"
signal-hook = "0.3.17"
dunce = "1.0.4"
lazy_static = "1.4.0"

clap = { version = "4.4", features = ["derive"] }
clap_complete = { version = "4.4" }
Expand Down
126 changes: 126 additions & 0 deletions maa-cli/src/config/cli/maa_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{normalize_url, return_true, Channel};

use std::env::var_os;

use clap::Parser;
use serde::Deserialize;

#[cfg_attr(test, derive(Debug, PartialEq))]
Expand Down Expand Up @@ -64,6 +65,22 @@ impl Config {
f(&mut self.components);
self
}

pub fn apply_args(&mut self, args: &CommonArgs) -> &Self {
if let Some(channel) = args.channel {
self.set_channel(channel);
}
if let Some(test_time) = args.test_time {
self.set_test_time(test_time);
}
if let Some(api_url) = &args.api_url {
self.set_api_url(api_url);
}
if args.no_resource {
self.set_components(|components| components.resource = false);
}
self
}
}

fn default_test_time() -> u64 {
Expand Down Expand Up @@ -96,6 +113,54 @@ impl Default for Components {
}
}

#[derive(Parser, Default)]
pub struct CommonArgs {
/// Channel to download prebuilt package
///
/// There are three channels of maa-core prebuilt packages,
/// stable, beta and alpha.
/// The default channel is stable, you can use this flag to change the channel.
/// If you want to use the latest features of maa-core,
/// you can use beta or alpha channel.
/// You can also configure the default channel
/// in the cli configure file `$MAA_CONFIG_DIR/cli.toml` with the key `maa_core.channel`.
/// Note: the alpha channel is only available for windows.
pub channel: Option<Channel>,
/// Do not install resource
///
/// By default, resources are shipped with maa-core,
/// and we will install them when installing maa-core.
/// If you do not want to install resource,
/// you can use this flag to disable it.
/// You can also configure the default value in the cli configure file
/// `$MAA_CONFIG_DIR/cli.toml` with the key `maa_core.component.resource`;
/// set it to false to disable installing resource by default.
/// This is useful when you want to install maa-core only.
/// For my own, I will use this flag to install maa-core,
/// because I use the latest resource from github,
/// and this flag can avoid the resource being overwritten.
/// Note: if you use resources that too new or too old,
/// you may encounter some problems.
/// Use at your own risk.
#[arg(long)]
pub no_resource: bool,
/// Time to test download speed
///
/// There are several mirrors of maa-core prebuilt packages.
/// This command will test the download speed of these mirrors,
/// and choose the fastest one to download.
/// This flag is used to set the time in seconds to test download speed.
/// If test time is 0, speed test will be skipped.
#[arg(short, long)]
pub test_time: Option<u64>,
/// URL of api to get version information
///
/// This flag is used to set the URL of api to get version information.
/// It can also be changed by environment variable `MAA_API_URL`.
#[arg(long)]
pub api_url: Option<String>,
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -267,5 +332,66 @@ mod tests {
}
));
}

#[test]
fn apply_args() {
fn apply_to_default(args: &CommonArgs) -> Config {
let mut config = Config::default();
config.apply_args(args);
config
}

assert_eq!(apply_to_default(&CommonArgs::default()), Config::default());

assert_eq!(
&apply_to_default(&CommonArgs {
channel: Some(Channel::Beta),
..Default::default()
}),
Config::default().set_channel(Channel::Beta)
);

assert_eq!(
&apply_to_default(&CommonArgs {
test_time: Some(5),
..Default::default()
}),
Config::default().set_test_time(5)
);

assert_eq!(
&apply_to_default(&CommonArgs {
api_url: Some("https://foo.bar/core/".to_string()),
..Default::default()
}),
Config::default().set_api_url("https://foo.bar/core/")
);

assert_eq!(
&apply_to_default(&CommonArgs {
no_resource: true,
..Default::default()
}),
Config::default().set_components(|components| {
components.resource = false;
})
);

assert_eq!(
&apply_to_default(&CommonArgs {
channel: Some(Channel::Beta),
test_time: Some(5),
api_url: Some("https://foo.bar/maa_core/".to_string()),
no_resource: true,
}),
Config::default()
.with_channel(Channel::Beta)
.with_test_time(5)
.with_api_url("https://foo.bar/maa_core/")
.set_components(|components| {
components.resource = false;
})
);
}
}
}
12 changes: 5 additions & 7 deletions maa-cli/src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
pub const MAA_CLI_EXE: &str = if cfg!(windows) { "maa.exe" } else { "maa" };

pub const MAA_CORE_LIB: &str = if cfg!(unix) {
if cfg!(target_os = "macos") {
"libMaaCore.dylib"
} else {
"libMaaCore.so"
}
} else {
pub const MAA_CORE_LIB: &str = if cfg!(windows) {
"MaaCore.dll"
} else if cfg!(target_os = "macos") {
"libMaaCore.dylib"
} else {
"libMaaCore.so"
};

pub const MAA_CLI_VERSION: &str = env!("CARGO_PKG_VERSION");
114 changes: 76 additions & 38 deletions maa-cli/src/dirs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::{

use directories::ProjectDirs;
use dunce::canonicalize;
use lazy_static::lazy_static;
use paste::paste;

macro_rules! matct_loc {
Expand Down Expand Up @@ -107,56 +108,88 @@ impl Dirs {
pub fn log(&self) -> &Path {
&self.log
}
}

pub fn find_library(&self) -> Option<PathBuf> {
let lib_dir = self.library();
if lib_dir.join(MAA_CORE_LIB).exists() {
return Some(lib_dir.to_path_buf());
}
lazy_static! {
pub static ref DIRS: Dirs = Dirs::new(ProjectDirs::from("com", "loong", "maa"));
}

current_exe_dir_find(|exe_dir| {
if exe_dir.join(MAA_CORE_LIB).exists() {
return Some(exe_dir.to_path_buf());
}
if let Some(dir) = exe_dir.parent() {
let lib_dir = dir.join("lib");
let lib_path = lib_dir.join(MAA_CORE_LIB);
if lib_path.exists() {
return Some(lib_dir);
}
pub fn data() -> &'static Path {
DIRS.data()
}

pub fn library() -> &'static Path {
DIRS.library()
}

pub fn config() -> &'static Path {
DIRS.config()
}

pub fn cache() -> &'static Path {
DIRS.cache()
}

pub fn resource() -> &'static Path {
DIRS.resource()
}

pub fn state() -> &'static Path {
DIRS.state()
}

pub fn log() -> &'static Path {
DIRS.log()
}

pub fn find_library() -> Option<PathBuf> {
let lib_dir = library();
if lib_dir.join(MAA_CORE_LIB).exists() {
return Some(lib_dir.to_path_buf());
}

current_exe_dir_find(|exe_dir| {
if exe_dir.join(MAA_CORE_LIB).exists() {
return Some(exe_dir.to_path_buf());
}
if let Some(dir) = exe_dir.parent() {
let lib_dir = dir.join("lib");
let lib_path = lib_dir.join(MAA_CORE_LIB);
if lib_path.exists() {
return Some(lib_dir);
}
}

None
})
None
})
}

pub fn find_resource() -> Option<PathBuf> {
let resource_dir = resource();
if resource_dir.exists() {
return Some(resource_dir.to_path_buf());
}

pub fn find_resource(&self) -> Option<PathBuf> {
let resource_dir = self.resource();
current_exe_dir_find(|exe_dir| {
let resource_dir = exe_dir.join("resource");
if resource_dir.exists() {
return Some(resource_dir.to_path_buf());
return Some(resource_dir);
}

current_exe_dir_find(|exe_dir| {
let resource_dir = exe_dir.join("resource");
if resource_dir.exists() {
return Some(resource_dir);
}
if let Some(dir) = exe_dir.parent() {
let share_dir = dir.join("share");
if let Some(extra_share) = option_env!("MAA_EXTRA_SHARE_NAME") {
let resource_dir = share_dir.join(extra_share).join("resource");
if resource_dir.exists() {
return Some(resource_dir);
}
}
let resource_dir = share_dir.join("maa").join("resource");
if let Some(dir) = exe_dir.parent() {
let share_dir = dir.join("share");
if let Some(extra_share) = option_env!("MAA_EXTRA_SHARE_NAME") {
let resource_dir = share_dir.join(extra_share).join("resource");
if resource_dir.exists() {
return Some(resource_dir);
}
}
None
})
}
let resource_dir = share_dir.join("maa").join("resource");
if resource_dir.exists() {
return Some(resource_dir);
}
}
None
})
}

/// Find path starting from current executable directory
Expand Down Expand Up @@ -244,6 +277,8 @@ mod tests {
assert_eq!(dirs.state(), home_dir.join(".local/state/maa"));
assert_eq!(dirs.log(), home_dir.join(".local/state/maa/debug"));
}
assert_eq!(state(), dirs.state());
assert_eq!(log(), dirs.log());

env::set_var("XDG_STATE_HOME", "/xdg");
let dirs = Dirs::new(project.clone());
Expand Down Expand Up @@ -280,6 +315,8 @@ mod tests {
assert_eq!(dirs.library(), home_dir.join(".local/share/maa/lib"));
assert_eq!(dirs.resource(), home_dir.join(".local/share/maa/resource"));
}
assert_eq!(data(), dirs.data());
assert_eq!(library(), dirs.library());

env::set_var("XDG_DATA_HOME", "/xdg");
let dirs = Dirs::new(project.clone());
Expand Down Expand Up @@ -329,6 +366,7 @@ mod tests {
} else if cfg!(target_os = "linux") {
assert_eq!(dirs.cache(), home_dir.join(".cache/maa"));
}
assert_eq!(cache(), dirs.cache());

env::set_var("XDG_CACHE_HOME", "/xdg");
let dirs = Dirs::new(project.clone());
Expand Down
6 changes: 3 additions & 3 deletions maa-cli/src/installer/maa_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{
use crate::{
config::cli::maa_cli::Config,
consts::{MAA_CLI_EXE, MAA_CLI_VERSION},
dirs::{Dirs, Ensure},
dirs::{self, Ensure},
normal,
};

Expand All @@ -26,7 +26,7 @@ pub fn version() -> Result<Version> {
Version::parse(MAA_CLI_VERSION).context("Failed to parse maa-cli version")
}

pub fn update(dirs: &Dirs, config: &Config) -> Result<()> {
pub fn update(config: &Config) -> Result<()> {
normal!("Fetching maa-cli version info...");
let version_json: VersionJSON<Details> = reqwest::blocking::get(config.api_url())
.context("Failed to fetch version info")?
Expand All @@ -43,7 +43,7 @@ pub fn update(dirs: &Dirs, config: &Config) -> Result<()> {
let asset_name = asset.name();
let asset_size = asset.size();
let asset_checksum = asset.checksum();
let cache_path = dirs.cache().ensure()?.join(asset_name);
let cache_path = dirs::cache().ensure()?.join(asset_name);

if cache_path.exists() && cache_path.metadata()?.len() == asset_size {
normal!(format!("Found existing file: {}", cache_path.display()));
Expand Down
Loading

0 comments on commit 628f5c0

Please sign in to comment.