mirror of
https://github.com/pesde-pkg/pesde.git
synced 2025-03-04 11:11:42 +00:00
refactor(cli): 🎨 use static variables
This commit is contained in:
parent
9e1ffc41b6
commit
5c77d8db76
12 changed files with 520 additions and 387 deletions
57
Cargo.lock
generated
57
Cargo.lock
generated
|
@ -92,7 +92,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
|
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -130,7 +130,7 @@ dependencies = [
|
||||||
"parse-size",
|
"parse-size",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -243,7 +243,7 @@ dependencies = [
|
||||||
"actix-router",
|
"actix-router",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -571,7 +571,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -600,13 +600,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.77"
|
version = "0.1.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
|
checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -925,7 +925,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1146,7 +1146,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim 0.10.0",
|
"strsim 0.10.0",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1157,7 +1157,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1363,7 +1363,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1711,7 +1711,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2604,9 +2604,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "luau0-src"
|
name = "luau0-src"
|
||||||
version = "0.8.4+luau616"
|
version = "0.8.5+luau617"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74f34c6c8e52606273c5d689b722e03383e58fed85840868885301fe9038fbd9"
|
checksum = "652e36b8c35d807ec76a4931fe7c62883c62cc93311fb49bf5b76084647078ea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
@ -3103,7 +3103,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3263,6 +3263,7 @@ dependencies = [
|
||||||
"keyring",
|
"keyring",
|
||||||
"log",
|
"log",
|
||||||
"lune",
|
"lune",
|
||||||
|
"once_cell",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
"relative-path",
|
"relative-path",
|
||||||
|
@ -3280,7 +3281,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pesde-registry"
|
name = "pesde-registry"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-cors",
|
"actix-cors",
|
||||||
"actix-governor",
|
"actix-governor",
|
||||||
|
@ -3325,7 +3326,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3470,7 +3471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4320,7 +4321,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4352,7 +4353,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4653,9 +4654,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.52"
|
version = "2.0.53"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -4888,7 +4889,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5022,7 +5023,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5180,7 +5181,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5474,7 +5475,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5508,7 +5509,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
@ -5872,7 +5873,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -9,7 +9,7 @@ homepage = "https://pesde.daimond113.com"
|
||||||
include = ["src/**/*", "Cargo.toml", "Cargo.lock", "README.md", "LICENSE", "CHANGELOG.md"]
|
include = ["src/**/*", "Cargo.toml", "Cargo.lock", "README.md", "LICENSE", "CHANGELOG.md"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
bin = ["clap", "directories", "keyring", "anyhow", "ignore", "pretty_env_logger", "serde_json", "reqwest/json", "reqwest/multipart", "lune", "futures-executor", "indicatif", "auth-git2", "indicatif-log-bridge", "inquire"]
|
bin = ["clap", "directories", "keyring", "anyhow", "ignore", "pretty_env_logger", "serde_json", "reqwest/json", "reqwest/multipart", "lune", "futures-executor", "indicatif", "auth-git2", "indicatif-log-bridge", "inquire", "once_cell"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "pesde"
|
name = "pesde"
|
||||||
|
@ -48,6 +48,7 @@ indicatif = { version = "0.17.8", optional = true }
|
||||||
auth-git2 = { version = "0.5.4", optional = true }
|
auth-git2 = { version = "0.5.4", optional = true }
|
||||||
indicatif-log-bridge = { version = "0.2.2", optional = true }
|
indicatif-log-bridge = { version = "0.2.2", optional = true }
|
||||||
inquire = { version = "0.7.1", optional = true }
|
inquire = { version = "0.7.1", optional = true }
|
||||||
|
once_cell = { version = "1.19.0", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.10.1"
|
tempfile = "3.10.1"
|
||||||
|
|
|
@ -174,10 +174,7 @@ pub async fn get_package_version(
|
||||||
match index.package(&package_name)? {
|
match index.package(&package_name)? {
|
||||||
Some(package) => {
|
Some(package) => {
|
||||||
if version == "latest" {
|
if version == "latest" {
|
||||||
version = package
|
version = package.last().map(|v| v.version.to_string()).unwrap();
|
||||||
.last()
|
|
||||||
.map(|v| v.version.to_string())
|
|
||||||
.unwrap();
|
|
||||||
} else if !package.iter().any(|v| v.version.to_string() == version) {
|
} else if !package.iter().any(|v| v.version.to_string() == version) {
|
||||||
return Ok(HttpResponse::NotFound().finish());
|
return Ok(HttpResponse::NotFound().finish());
|
||||||
}
|
}
|
||||||
|
|
147
src/cli/api_token.rs
Normal file
147
src/cli/api_token.rs
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use keyring::Entry;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::cli::INDEX_DIR;
|
||||||
|
|
||||||
|
pub trait ApiTokenSource: Send + Sync {
|
||||||
|
fn get_api_token(&self) -> anyhow::Result<Option<String>>;
|
||||||
|
fn set_api_token(&self, api_token: &str) -> anyhow::Result<()>;
|
||||||
|
fn delete_api_token(&self) -> anyhow::Result<()>;
|
||||||
|
fn persists(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EnvVarApiTokenSource;
|
||||||
|
|
||||||
|
const API_TOKEN_ENV_VAR: &str = "PESDE_API_TOKEN";
|
||||||
|
|
||||||
|
impl ApiTokenSource for EnvVarApiTokenSource {
|
||||||
|
fn get_api_token(&self) -> anyhow::Result<Option<String>> {
|
||||||
|
match std::env::var(API_TOKEN_ENV_VAR) {
|
||||||
|
Ok(token) => Ok(Some(token)),
|
||||||
|
Err(std::env::VarError::NotPresent) => Ok(None),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't need to implement set_api_token or delete_api_token
|
||||||
|
fn set_api_token(&self, _api_token: &str) -> anyhow::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_api_token(&self) -> anyhow::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn persists(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static KEYRING_ENTRY: Lazy<Entry> =
|
||||||
|
Lazy::new(|| Entry::new(env!("CARGO_BIN_NAME"), "api_token").unwrap());
|
||||||
|
|
||||||
|
pub struct KeyringApiTokenSource;
|
||||||
|
|
||||||
|
impl ApiTokenSource for KeyringApiTokenSource {
|
||||||
|
fn get_api_token(&self) -> anyhow::Result<Option<String>> {
|
||||||
|
match KEYRING_ENTRY.get_password() {
|
||||||
|
Ok(api_token) => Ok(Some(api_token)),
|
||||||
|
Err(err) => match err {
|
||||||
|
keyring::Error::NoEntry | keyring::Error::PlatformFailure(_) => Ok(None),
|
||||||
|
_ => Err(err.into()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_api_token(&self, api_token: &str) -> anyhow::Result<()> {
|
||||||
|
KEYRING_ENTRY.set_password(api_token)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_api_token(&self) -> anyhow::Result<()> {
|
||||||
|
KEYRING_ENTRY.delete_password()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AUTH_FILE_PATH: Lazy<PathBuf> = Lazy::new(|| INDEX_DIR.join("auth.yaml"));
|
||||||
|
static AUTH_FILE: Lazy<AuthFile> =
|
||||||
|
Lazy::new(
|
||||||
|
|| match std::fs::read_to_string(AUTH_FILE_PATH.to_path_buf()) {
|
||||||
|
Ok(config) => serde_yaml::from_str(&config).unwrap(),
|
||||||
|
Err(e) if e.kind() == std::io::ErrorKind::NotFound => AuthFile::default(),
|
||||||
|
Err(e) => panic!("{:?}", e),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Clone)]
|
||||||
|
struct AuthFile {
|
||||||
|
#[serde(default)]
|
||||||
|
api_token: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ConfigFileApiTokenSource;
|
||||||
|
|
||||||
|
impl ApiTokenSource for ConfigFileApiTokenSource {
|
||||||
|
fn get_api_token(&self) -> anyhow::Result<Option<String>> {
|
||||||
|
Ok(AUTH_FILE.api_token.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_api_token(&self, api_token: &str) -> anyhow::Result<()> {
|
||||||
|
let mut config = AUTH_FILE.clone();
|
||||||
|
config.api_token = Some(api_token.to_string());
|
||||||
|
|
||||||
|
serde_yaml::to_writer(
|
||||||
|
&mut std::fs::File::create(AUTH_FILE_PATH.to_path_buf())?,
|
||||||
|
&config,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_api_token(&self) -> anyhow::Result<()> {
|
||||||
|
let mut config = AUTH_FILE.clone();
|
||||||
|
|
||||||
|
config.api_token = None;
|
||||||
|
|
||||||
|
serde_yaml::to_writer(
|
||||||
|
&mut std::fs::File::create(AUTH_FILE_PATH.to_path_buf())?,
|
||||||
|
&config,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static API_TOKEN_SOURCE: Lazy<Box<dyn ApiTokenSource>> = Lazy::new(|| {
|
||||||
|
let sources: Vec<Box<dyn ApiTokenSource>> = vec![
|
||||||
|
Box::new(EnvVarApiTokenSource),
|
||||||
|
Box::new(KeyringApiTokenSource),
|
||||||
|
Box::new(ConfigFileApiTokenSource),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut valid_sources = vec![];
|
||||||
|
|
||||||
|
for source in sources {
|
||||||
|
match source.get_api_token() {
|
||||||
|
Ok(Some(_)) => return source,
|
||||||
|
Ok(None) => {
|
||||||
|
if source.persists() {
|
||||||
|
valid_sources.push(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("error getting api token: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_sources.pop().unwrap()
|
||||||
|
});
|
|
@ -2,9 +2,9 @@ use clap::Subcommand;
|
||||||
use pesde::index::Index;
|
use pesde::index::Index;
|
||||||
use reqwest::{header::AUTHORIZATION, Url};
|
use reqwest::{header::AUTHORIZATION, Url};
|
||||||
|
|
||||||
use crate::{send_request, CliParams};
|
use crate::cli::{api_token::API_TOKEN_SOURCE, send_request, INDEX, REQWEST_CLIENT};
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand, Clone)]
|
||||||
pub enum AuthCommand {
|
pub enum AuthCommand {
|
||||||
/// Logs in to the registry
|
/// Logs in to the registry
|
||||||
Login,
|
Login,
|
||||||
|
@ -12,14 +12,14 @@ pub enum AuthCommand {
|
||||||
Logout,
|
Logout,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn auth_command(cmd: AuthCommand, params: CliParams) -> anyhow::Result<()> {
|
pub fn auth_command(cmd: AuthCommand) -> anyhow::Result<()> {
|
||||||
let index_config = params.index.config()?;
|
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
AuthCommand::Login => {
|
AuthCommand::Login => {
|
||||||
let response = send_request(params.reqwest_client.post(Url::parse_with_params(
|
let github_oauth_client_id = INDEX.config()?.github_oauth_client_id;
|
||||||
|
|
||||||
|
let response = send_request(REQWEST_CLIENT.post(Url::parse_with_params(
|
||||||
"https://github.com/login/device/code",
|
"https://github.com/login/device/code",
|
||||||
&[("client_id", index_config.github_oauth_client_id.as_str())],
|
&[("client_id", &github_oauth_client_id)],
|
||||||
)?))?
|
)?))?
|
||||||
.json::<serde_json::Value>()?;
|
.json::<serde_json::Value>()?;
|
||||||
|
|
||||||
|
@ -43,10 +43,10 @@ pub fn auth_command(cmd: AuthCommand, params: CliParams) -> anyhow::Result<()> {
|
||||||
while time_left > 0 {
|
while time_left > 0 {
|
||||||
std::thread::sleep(interval);
|
std::thread::sleep(interval);
|
||||||
time_left -= interval.as_secs() as i64;
|
time_left -= interval.as_secs() as i64;
|
||||||
let response = send_request(params.reqwest_client.post(Url::parse_with_params(
|
let response = send_request(REQWEST_CLIENT.post(Url::parse_with_params(
|
||||||
"https://github.com/login/oauth/access_token",
|
"https://github.com/login/oauth/access_token",
|
||||||
&[
|
&[
|
||||||
("client_id", index_config.github_oauth_client_id.as_str()),
|
("client_id", github_oauth_client_id.as_str()),
|
||||||
("device_code", device_code),
|
("device_code", device_code),
|
||||||
("grant_type", "urn:ietf:params:oauth:grant-type:device_code"),
|
("grant_type", "urn:ietf:params:oauth:grant-type:device_code"),
|
||||||
],
|
],
|
||||||
|
@ -80,11 +80,10 @@ pub fn auth_command(cmd: AuthCommand, params: CliParams) -> anyhow::Result<()> {
|
||||||
.as_str()
|
.as_str()
|
||||||
.ok_or(anyhow::anyhow!("couldn't get access_token"))?;
|
.ok_or(anyhow::anyhow!("couldn't get access_token"))?;
|
||||||
|
|
||||||
params.api_token_entry.set_password(access_token)?;
|
API_TOKEN_SOURCE.set_api_token(access_token)?;
|
||||||
|
|
||||||
let response = send_request(
|
let response = send_request(
|
||||||
params
|
REQWEST_CLIENT
|
||||||
.reqwest_client
|
|
||||||
.get("https://api.github.com/user")
|
.get("https://api.github.com/user")
|
||||||
.header(AUTHORIZATION, format!("Bearer {access_token}")),
|
.header(AUTHORIZATION, format!("Bearer {access_token}")),
|
||||||
)?
|
)?
|
||||||
|
@ -102,7 +101,7 @@ pub fn auth_command(cmd: AuthCommand, params: CliParams) -> anyhow::Result<()> {
|
||||||
anyhow::bail!("code expired, please re-run the login command");
|
anyhow::bail!("code expired, please re-run the login command");
|
||||||
}
|
}
|
||||||
AuthCommand::Logout => {
|
AuthCommand::Logout => {
|
||||||
params.api_token_entry.delete_password()?;
|
API_TOKEN_SOURCE.delete_api_token()?;
|
||||||
|
|
||||||
println!("you're now logged out");
|
println!("you're now logged out");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
|
|
||||||
use crate::{CliConfig, CliParams};
|
use crate::{cli::CLI_CONFIG, CliConfig};
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand, Clone)]
|
||||||
pub enum ConfigCommand {
|
pub enum ConfigCommand {
|
||||||
/// Sets the index repository URL
|
/// Sets the index repository URL
|
||||||
SetIndexRepo {
|
SetIndexRepo {
|
||||||
|
@ -25,41 +25,41 @@ pub enum ConfigCommand {
|
||||||
GetCacheDir,
|
GetCacheDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config_command(cmd: ConfigCommand, params: CliParams) -> anyhow::Result<()> {
|
pub fn config_command(cmd: ConfigCommand) -> anyhow::Result<()> {
|
||||||
match cmd {
|
match cmd {
|
||||||
ConfigCommand::SetIndexRepo { url } => {
|
ConfigCommand::SetIndexRepo { url } => {
|
||||||
let cli_config = CliConfig {
|
let cli_config = CliConfig {
|
||||||
index_repo_url: url.clone(),
|
index_repo_url: url.clone(),
|
||||||
..params.cli_config
|
..CLI_CONFIG.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
cli_config.write(¶ms.directories)?;
|
cli_config.write()?;
|
||||||
|
|
||||||
println!("index repository url set to: `{url}`");
|
println!("index repository url set to: `{url}`");
|
||||||
}
|
}
|
||||||
ConfigCommand::GetIndexRepo => {
|
ConfigCommand::GetIndexRepo => {
|
||||||
println!(
|
println!(
|
||||||
"current index repository url: `{}`",
|
"current index repository url: `{}`",
|
||||||
params.cli_config.index_repo_url
|
CLI_CONFIG.index_repo_url
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ConfigCommand::SetCacheDir { directory } => {
|
ConfigCommand::SetCacheDir { directory } => {
|
||||||
let cli_config = CliConfig {
|
let cli_config = CliConfig {
|
||||||
cache_dir: directory,
|
cache_dir: directory,
|
||||||
..params.cli_config
|
..CLI_CONFIG.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
cli_config.write(¶ms.directories)?;
|
cli_config.write()?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"cache directory set to: `{}`",
|
"cache directory set to: `{}`",
|
||||||
cli_config.cache_dir(¶ms.directories).display()
|
cli_config.cache_dir().display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ConfigCommand::GetCacheDir => {
|
ConfigCommand::GetCacheDir => {
|
||||||
println!(
|
println!(
|
||||||
"current cache directory: `{}`",
|
"current cache directory: `{}`",
|
||||||
params.cli_config.cache_dir(¶ms.directories).display()
|
CLI_CONFIG.cache_dir().display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
274
src/cli/mod.rs
274
src/cli/mod.rs
|
@ -1,3 +1,277 @@
|
||||||
|
use crate::cli::{api_token::API_TOKEN_SOURCE, auth::AuthCommand, config::ConfigCommand};
|
||||||
|
use auth_git2::GitAuthenticator;
|
||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
use directories::ProjectDirs;
|
||||||
|
use indicatif::MultiProgress;
|
||||||
|
use indicatif_log_bridge::LogWrapper;
|
||||||
|
use log::error;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use pesde::{index::GitIndex, manifest::Realm, package_name::PackageName};
|
||||||
|
use pretty_env_logger::env_logger::Env;
|
||||||
|
use reqwest::{
|
||||||
|
blocking::{RequestBuilder, Response},
|
||||||
|
header::ACCEPT,
|
||||||
|
};
|
||||||
|
use semver::{Version, VersionReq};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{
|
||||||
|
hash::{DefaultHasher, Hash, Hasher},
|
||||||
|
path::PathBuf,
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub mod api_token;
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod root;
|
pub mod root;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct VersionedPackageName<V: FromStr<Err = semver::Error>>(PackageName, V);
|
||||||
|
|
||||||
|
impl<V: FromStr<Err = semver::Error>> FromStr for VersionedPackageName<V> {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let (name, version) = s.split_once('@').ok_or_else(|| {
|
||||||
|
anyhow::anyhow!("invalid package name: {s}; expected format: name@version")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(VersionedPackageName(
|
||||||
|
name.to_string().parse()?,
|
||||||
|
version.parse()?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand, Clone)]
|
||||||
|
pub enum Command {
|
||||||
|
/// Initializes a manifest file
|
||||||
|
Init,
|
||||||
|
|
||||||
|
/// Adds a package to the manifest
|
||||||
|
Add {
|
||||||
|
/// The package to add
|
||||||
|
#[clap(value_name = "PACKAGE")]
|
||||||
|
package: VersionedPackageName<VersionReq>,
|
||||||
|
|
||||||
|
/// Whether the package is a peer dependency
|
||||||
|
#[clap(long, short)]
|
||||||
|
peer: bool,
|
||||||
|
|
||||||
|
/// The realm of the package
|
||||||
|
#[clap(long, short)]
|
||||||
|
realm: Option<Realm>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Removes a package from the manifest
|
||||||
|
Remove {
|
||||||
|
/// The package to remove
|
||||||
|
#[clap(value_name = "PACKAGE")]
|
||||||
|
package: PackageName,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Lists outdated packages
|
||||||
|
Outdated,
|
||||||
|
|
||||||
|
/// Installs the dependencies of the project
|
||||||
|
Install {
|
||||||
|
/// Whether to use the lockfile for resolving dependencies
|
||||||
|
#[clap(long, short)]
|
||||||
|
locked: bool,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Runs the `bin` export of the specified package
|
||||||
|
Run {
|
||||||
|
/// The package to run
|
||||||
|
#[clap(value_name = "PACKAGE")]
|
||||||
|
package: PackageName,
|
||||||
|
|
||||||
|
/// The arguments to pass to the package
|
||||||
|
#[clap(last = true)]
|
||||||
|
args: Vec<String>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Searches for a package on the registry
|
||||||
|
Search {
|
||||||
|
/// The query to search for
|
||||||
|
#[clap(value_name = "QUERY")]
|
||||||
|
query: Option<String>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Publishes the project to the registry
|
||||||
|
Publish,
|
||||||
|
|
||||||
|
/// Converts a `wally.toml` file to a `pesde.yaml` file
|
||||||
|
Convert,
|
||||||
|
|
||||||
|
/// Begins a new patch
|
||||||
|
Patch {
|
||||||
|
/// The package to patch
|
||||||
|
#[clap(value_name = "PACKAGE")]
|
||||||
|
package: VersionedPackageName<Version>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Commits (finishes) the patch
|
||||||
|
PatchCommit {
|
||||||
|
/// The package's changed directory
|
||||||
|
#[clap(value_name = "DIRECTORY")]
|
||||||
|
dir: PathBuf,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Auth-related commands
|
||||||
|
Auth {
|
||||||
|
#[clap(subcommand)]
|
||||||
|
command: AuthCommand,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Config-related commands
|
||||||
|
Config {
|
||||||
|
#[clap(subcommand)]
|
||||||
|
command: ConfigCommand,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, Clone)]
|
||||||
|
pub struct Cli {
|
||||||
|
#[clap(subcommand)]
|
||||||
|
pub command: Command,
|
||||||
|
|
||||||
|
/// The directory to run the command in
|
||||||
|
#[arg(short, long, value_name = "DIRECTORY")]
|
||||||
|
pub directory: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
pub struct CliConfig {
|
||||||
|
pub index_repo_url: String,
|
||||||
|
pub cache_dir: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CliConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
index_repo_url: "https://github.com/daimond113/pesde-index".to_string(),
|
||||||
|
cache_dir: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CliConfig {
|
||||||
|
pub fn cache_dir(&self) -> PathBuf {
|
||||||
|
self.cache_dir
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| DIRS.cache_dir().to_path_buf())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open() -> anyhow::Result<Self> {
|
||||||
|
let cli_config_path = DIRS.config_dir().join("config.yaml");
|
||||||
|
|
||||||
|
if cli_config_path.exists() {
|
||||||
|
Ok(serde_yaml::from_slice(&std::fs::read(cli_config_path)?)?)
|
||||||
|
} else {
|
||||||
|
let config = CliConfig::default();
|
||||||
|
config.write()?;
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) -> anyhow::Result<()> {
|
||||||
|
let cli_config_path = DIRS.config_dir().join("config.yaml");
|
||||||
|
serde_yaml::to_writer(
|
||||||
|
&mut std::fs::File::create(cli_config_path.as_path())?,
|
||||||
|
&self,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_request(request_builder: RequestBuilder) -> anyhow::Result<Response> {
|
||||||
|
let res = request_builder.send()?;
|
||||||
|
|
||||||
|
match res.error_for_status_ref() {
|
||||||
|
Ok(_) => Ok(res),
|
||||||
|
Err(e) => {
|
||||||
|
error!("request failed: {e}\nbody: {}", res.text()?);
|
||||||
|
Err(e.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static CLI: Lazy<Cli> = Lazy::new(Cli::parse);
|
||||||
|
|
||||||
|
pub static DIRS: Lazy<ProjectDirs> = Lazy::new(|| {
|
||||||
|
ProjectDirs::from("com", env!("CARGO_BIN_NAME"), env!("CARGO_BIN_NAME"))
|
||||||
|
.expect("couldn't get home directory")
|
||||||
|
});
|
||||||
|
|
||||||
|
pub static CLI_CONFIG: Lazy<CliConfig> = Lazy::new(|| CliConfig::open().unwrap());
|
||||||
|
|
||||||
|
pub static INDEX_DIR: Lazy<PathBuf> = Lazy::new(|| {
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
CLI_CONFIG.index_repo_url.hash(&mut hasher);
|
||||||
|
let hash = hasher.finish().to_string();
|
||||||
|
|
||||||
|
CLI_CONFIG.cache_dir().join("indices").join(hash)
|
||||||
|
});
|
||||||
|
|
||||||
|
pub static INDEX: Lazy<GitIndex> = Lazy::new(|| {
|
||||||
|
let index = GitIndex::new(
|
||||||
|
INDEX_DIR.join("index"),
|
||||||
|
&CLI_CONFIG.index_repo_url,
|
||||||
|
Some(Box::new(|| {
|
||||||
|
Box::new(|a, b, c| {
|
||||||
|
let git_authenticator = GitAuthenticator::new();
|
||||||
|
let config = git2::Config::open_default().unwrap();
|
||||||
|
let mut cred = git_authenticator.credentials(&config);
|
||||||
|
|
||||||
|
cred(a, b, c)
|
||||||
|
})
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
index.refresh().unwrap();
|
||||||
|
|
||||||
|
index
|
||||||
|
});
|
||||||
|
|
||||||
|
pub static CWD: Lazy<PathBuf> = Lazy::new(|| {
|
||||||
|
CLI.directory
|
||||||
|
.clone()
|
||||||
|
.or(std::env::current_dir().ok())
|
||||||
|
.expect("couldn't get current directory")
|
||||||
|
});
|
||||||
|
|
||||||
|
pub static REQWEST_CLIENT: Lazy<reqwest::blocking::Client> = Lazy::new(|| {
|
||||||
|
let mut header_map = reqwest::header::HeaderMap::new();
|
||||||
|
header_map.insert(ACCEPT, "application/json".parse().unwrap());
|
||||||
|
header_map.insert("X-GitHub-Api-Version", "2022-11-28".parse().unwrap());
|
||||||
|
|
||||||
|
if let Ok(Some(token)) = API_TOKEN_SOURCE.get_api_token() {
|
||||||
|
header_map.insert(
|
||||||
|
reqwest::header::AUTHORIZATION,
|
||||||
|
format!("Bearer {token}").parse().unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
reqwest::blocking::Client::builder()
|
||||||
|
.user_agent(concat!(
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
"/",
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
))
|
||||||
|
.default_headers(header_map)
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
pub static MULTI: Lazy<MultiProgress> = Lazy::new(|| {
|
||||||
|
let logger = pretty_env_logger::formatted_builder()
|
||||||
|
.parse_env(Env::default().default_filter_or("info"))
|
||||||
|
.build();
|
||||||
|
let multi = MultiProgress::new();
|
||||||
|
|
||||||
|
LogWrapper::new(multi.clone(), logger).try_init().unwrap();
|
||||||
|
|
||||||
|
multi
|
||||||
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@ use ignore::{overrides::OverrideBuilder, WalkBuilder};
|
||||||
use inquire::{validator::Validation, Select, Text};
|
use inquire::{validator::Validation, Select, Text};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use lune::Runtime;
|
use lune::Runtime;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use reqwest::{header::AUTHORIZATION, Url};
|
use reqwest::{header::AUTHORIZATION, Url};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -27,27 +28,19 @@ use pesde::{
|
||||||
SERVER_PACKAGES_FOLDER,
|
SERVER_PACKAGES_FOLDER,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{send_request, CliParams, Command};
|
use crate::cli::{
|
||||||
|
api_token::API_TOKEN_SOURCE, send_request, Command, CLI_CONFIG, CWD, DIRS, INDEX, MULTI,
|
||||||
|
REQWEST_CLIENT,
|
||||||
|
};
|
||||||
|
|
||||||
pub const MAX_ARCHIVE_SIZE: usize = 4 * 1024 * 1024;
|
pub const MAX_ARCHIVE_SIZE: usize = 4 * 1024 * 1024;
|
||||||
|
|
||||||
fn get_project(params: &CliParams) -> anyhow::Result<Project<GitIndex>> {
|
|
||||||
Project::from_path(
|
|
||||||
¶ms.cwd,
|
|
||||||
params.cli_config.cache_dir(¶ms.directories),
|
|
||||||
params.index.clone(),
|
|
||||||
params.api_token_entry.get_password().ok(),
|
|
||||||
)
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn multithreaded_bar<E: Send + Sync + Into<anyhow::Error> + 'static>(
|
fn multithreaded_bar<E: Send + Sync + Into<anyhow::Error> + 'static>(
|
||||||
params: &CliParams,
|
|
||||||
job: MultithreadedJob<E>,
|
job: MultithreadedJob<E>,
|
||||||
len: u64,
|
len: u64,
|
||||||
message: String,
|
message: String,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<(), anyhow::Error> {
|
||||||
let bar = params.multi.add(
|
let bar = MULTI.add(
|
||||||
indicatif::ProgressBar::new(len)
|
indicatif::ProgressBar::new(len)
|
||||||
.with_style(
|
.with_style(
|
||||||
indicatif::ProgressStyle::default_bar()
|
indicatif::ProgressStyle::default_bar()
|
||||||
|
@ -77,13 +70,21 @@ macro_rules! none_if_empty {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
pub fn root_command(cmd: Command) -> anyhow::Result<()> {
|
||||||
|
let project: Lazy<Project<GitIndex>> = Lazy::new(|| {
|
||||||
|
Project::from_path(
|
||||||
|
CWD.to_path_buf(),
|
||||||
|
CLI_CONFIG.cache_dir(),
|
||||||
|
INDEX.clone(),
|
||||||
|
API_TOKEN_SOURCE.get_api_token().ok().flatten(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
Command::Install { locked } => {
|
Command::Install { locked } => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
for packages_folder in &[PACKAGES_FOLDER, DEV_PACKAGES_FOLDER, SERVER_PACKAGES_FOLDER] {
|
for packages_folder in &[PACKAGES_FOLDER, DEV_PACKAGES_FOLDER, SERVER_PACKAGES_FOLDER] {
|
||||||
if let Err(e) = remove_dir_all(¶ms.cwd.join(packages_folder)) {
|
if let Err(e) = remove_dir_all(CWD.join(packages_folder)) {
|
||||||
if e.kind() != std::io::ErrorKind::NotFound {
|
if e.kind() != std::io::ErrorKind::NotFound {
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,7 +98,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
let download_job = project.download(&resolved_versions_map)?;
|
let download_job = project.download(&resolved_versions_map)?;
|
||||||
|
|
||||||
multithreaded_bar(
|
multithreaded_bar(
|
||||||
¶ms,
|
|
||||||
download_job,
|
download_job,
|
||||||
resolved_versions_map.len() as u64,
|
resolved_versions_map.len() as u64,
|
||||||
"Downloading packages".to_string(),
|
"Downloading packages".to_string(),
|
||||||
|
@ -111,8 +111,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Command::Run { package, args } => {
|
Command::Run { package, args } => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
let lockfile = project
|
let lockfile = project
|
||||||
.lockfile()?
|
.lockfile()?
|
||||||
.ok_or(anyhow::anyhow!("lockfile not found"))?;
|
.ok_or(anyhow::anyhow!("lockfile not found"))?;
|
||||||
|
@ -145,10 +143,10 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
Command::Search { query } => {
|
Command::Search { query } => {
|
||||||
let config = params.index.config()?;
|
let config = INDEX.config()?;
|
||||||
let api_url = config.api();
|
let api_url = config.api();
|
||||||
|
|
||||||
let response = send_request(params.reqwest_client.get(Url::parse_with_params(
|
let response = send_request(REQWEST_CLIENT.get(Url::parse_with_params(
|
||||||
&format!("{}/v0/search", api_url),
|
&format!("{}/v0/search", api_url),
|
||||||
&query.map(|q| vec![("query", q)]).unwrap_or_default(),
|
&query.map(|q| vec![("query", q)]).unwrap_or_default(),
|
||||||
)?))?
|
)?))?
|
||||||
|
@ -171,8 +169,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Publish => {
|
Command::Publish => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
if project.manifest().private {
|
if project.manifest().private {
|
||||||
anyhow::bail!("package is private, cannot publish");
|
anyhow::bail!("package is private, cannot publish");
|
||||||
}
|
}
|
||||||
|
@ -180,9 +176,11 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
let encoder = GzEncoder::new(vec![], Compression::default());
|
let encoder = GzEncoder::new(vec![], Compression::default());
|
||||||
let mut archive = TarBuilder::new(encoder);
|
let mut archive = TarBuilder::new(encoder);
|
||||||
|
|
||||||
let mut walk_builder = WalkBuilder::new(¶ms.cwd);
|
let cwd = &CWD.to_path_buf();
|
||||||
|
|
||||||
|
let mut walk_builder = WalkBuilder::new(cwd);
|
||||||
walk_builder.add_custom_ignore_filename(".pesdeignore");
|
walk_builder.add_custom_ignore_filename(".pesdeignore");
|
||||||
let mut overrides = OverrideBuilder::new(¶ms.cwd);
|
let mut overrides = OverrideBuilder::new(cwd);
|
||||||
|
|
||||||
for packages_folder in IGNORED_FOLDERS {
|
for packages_folder in IGNORED_FOLDERS {
|
||||||
overrides.add(&format!("!{}", packages_folder))?;
|
overrides.add(&format!("!{}", packages_folder))?;
|
||||||
|
@ -193,7 +191,7 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
for entry in walk_builder.build() {
|
for entry in walk_builder.build() {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
let relative_path = path.strip_prefix(¶ms.cwd)?;
|
let relative_path = path.strip_prefix(cwd)?;
|
||||||
let entry_type = entry
|
let entry_type = entry
|
||||||
.file_type()
|
.file_type()
|
||||||
.ok_or(anyhow::anyhow!("failed to get file type"))?;
|
.ok_or(anyhow::anyhow!("failed to get file type"))?;
|
||||||
|
@ -222,8 +220,7 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
.file_name("tarball.tar.gz")
|
.file_name("tarball.tar.gz")
|
||||||
.mime_str("application/gzip")?;
|
.mime_str("application/gzip")?;
|
||||||
|
|
||||||
let mut request = params
|
let mut request = REQWEST_CLIENT
|
||||||
.reqwest_client
|
|
||||||
.post(format!("{}/v0/packages", project.index().config()?.api()))
|
.post(format!("{}/v0/packages", project.index().config()?.api()))
|
||||||
.multipart(reqwest::blocking::multipart::Form::new().part("tarball", part));
|
.multipart(reqwest::blocking::multipart::Form::new().part("tarball", part));
|
||||||
|
|
||||||
|
@ -236,8 +233,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
println!("{}", send_request(request)?.text()?);
|
println!("{}", send_request(request)?.text()?);
|
||||||
}
|
}
|
||||||
Command::Patch { package } => {
|
Command::Patch { package } => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
let lockfile = project
|
let lockfile = project
|
||||||
.lockfile()?
|
.lockfile()?
|
||||||
.ok_or(anyhow::anyhow!("lockfile not found"))?;
|
.ok_or(anyhow::anyhow!("lockfile not found"))?;
|
||||||
|
@ -247,7 +242,7 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
.and_then(|versions| versions.get(&package.1))
|
.and_then(|versions| versions.get(&package.1))
|
||||||
.ok_or(anyhow::anyhow!("package not found in lockfile"))?;
|
.ok_or(anyhow::anyhow!("package not found in lockfile"))?;
|
||||||
|
|
||||||
let dir = params.directories.data_dir().join("patches").join(format!(
|
let dir = DIRS.data_dir().join("patches").join(format!(
|
||||||
"{}_{}",
|
"{}_{}",
|
||||||
package.0.escaped(),
|
package.0.escaped(),
|
||||||
package.1
|
package.1
|
||||||
|
@ -273,8 +268,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
println!("done! modify the files in {} and run `{} patch-commit <DIRECTORY>` to commit the changes", dir.display(), env!("CARGO_BIN_NAME"));
|
println!("done! modify the files in {} and run `{} patch-commit <DIRECTORY>` to commit the changes", dir.display(), env!("CARGO_BIN_NAME"));
|
||||||
}
|
}
|
||||||
Command::PatchCommit { dir } => {
|
Command::PatchCommit { dir } => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
let manifest = Manifest::from_path(&dir)?;
|
let manifest = Manifest::from_path(&dir)?;
|
||||||
let patch_path = project.path().join(PATCHES_FOLDER).join(format!(
|
let patch_path = project.path().join(PATCHES_FOLDER).join(format!(
|
||||||
"{}@{}.patch",
|
"{}@{}.patch",
|
||||||
|
@ -301,13 +294,13 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Command::Init => {
|
Command::Init => {
|
||||||
let manifest_path = params.cwd.join(MANIFEST_FILE_NAME);
|
let manifest_path = CWD.join(MANIFEST_FILE_NAME);
|
||||||
|
|
||||||
if manifest_path.exists() {
|
if manifest_path.exists() {
|
||||||
anyhow::bail!("manifest already exists");
|
anyhow::bail!("manifest already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
let default_name = params.cwd.file_name().and_then(|s| s.to_str());
|
let default_name = CWD.file_name().and_then(|s| s.to_str());
|
||||||
|
|
||||||
let mut name =
|
let mut name =
|
||||||
Text::new("What is the name of the package?").with_validator(|name: &str| {
|
Text::new("What is the name of the package?").with_validator(|name: &str| {
|
||||||
|
@ -380,8 +373,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
realm,
|
realm,
|
||||||
peer,
|
peer,
|
||||||
} => {
|
} => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
let mut manifest = project.manifest().clone();
|
let mut manifest = project.manifest().clone();
|
||||||
|
|
||||||
let specifier = DependencySpecifier::Registry(RegistryDependencySpecifier {
|
let specifier = DependencySpecifier::Registry(RegistryDependencySpecifier {
|
||||||
|
@ -402,8 +393,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Command::Remove { package } => {
|
Command::Remove { package } => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
let mut manifest = project.manifest().clone();
|
let mut manifest = project.manifest().clone();
|
||||||
|
|
||||||
for dependencies in [&mut manifest.dependencies, &mut manifest.peer_dependencies] {
|
for dependencies in [&mut manifest.dependencies, &mut manifest.peer_dependencies] {
|
||||||
|
@ -422,8 +411,6 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Command::Outdated => {
|
Command::Outdated => {
|
||||||
let project = get_project(¶ms)?;
|
|
||||||
|
|
||||||
let manifest = project.manifest();
|
let manifest = project.manifest();
|
||||||
let dependency_tree = manifest.dependency_tree(&project, false)?;
|
let dependency_tree = manifest.dependency_tree(&project, false)?;
|
||||||
|
|
||||||
|
@ -434,7 +421,7 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let PackageRef::Registry(registry) = resolved_pkg.pkg_ref {
|
if let PackageRef::Registry(registry) = resolved_pkg.pkg_ref {
|
||||||
let latest_version = send_request(params.reqwest_client.get(format!(
|
let latest_version = send_request(REQWEST_CLIENT.get(format!(
|
||||||
"{}/v0/packages/{}/{}/versions",
|
"{}/v0/packages/{}/{}/versions",
|
||||||
project.index().config()?.api(),
|
project.index().config()?.api(),
|
||||||
registry.name.scope(),
|
registry.name.scope(),
|
||||||
|
@ -459,7 +446,7 @@ pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Convert => {
|
Command::Convert => {
|
||||||
Manifest::from_path_or_convert(¶ms.cwd)?;
|
Manifest::from_path_or_convert(CWD.to_path_buf())?;
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,9 @@ impl<I: Index> Project<I> {
|
||||||
|
|
||||||
let project = self.clone();
|
let project = self.clone();
|
||||||
|
|
||||||
job.execute(&tx, move || resolved_package.pkg_ref.download(&project, source));
|
job.execute(&tx, move || {
|
||||||
|
resolved_package.pkg_ref.download(&project, source)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
288
src/main.rs
288
src/main.rs
|
@ -1,289 +1,17 @@
|
||||||
use anyhow::bail;
|
use once_cell::sync::Lazy;
|
||||||
use std::{
|
|
||||||
fs::{create_dir_all, read},
|
|
||||||
hash::{DefaultHasher, Hash, Hasher},
|
|
||||||
path::PathBuf,
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use auth_git2::GitAuthenticator;
|
use cli::{auth::auth_command, config::config_command, root::root_command};
|
||||||
use clap::{Parser, Subcommand};
|
|
||||||
use directories::ProjectDirs;
|
|
||||||
use indicatif::MultiProgress;
|
|
||||||
use indicatif_log_bridge::LogWrapper;
|
|
||||||
use keyring::Entry;
|
|
||||||
use log::error;
|
|
||||||
use pretty_env_logger::env_logger::Env;
|
|
||||||
use reqwest::{
|
|
||||||
blocking::{RequestBuilder, Response},
|
|
||||||
header::{ACCEPT, AUTHORIZATION},
|
|
||||||
};
|
|
||||||
use semver::{Version, VersionReq};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use cli::{
|
use crate::cli::{CliConfig, Command, CLI, MULTI};
|
||||||
auth::{auth_command, AuthCommand},
|
|
||||||
config::{config_command, ConfigCommand},
|
|
||||||
root::root_command,
|
|
||||||
};
|
|
||||||
use pesde::{index::GitIndex, manifest::Realm, package_name::PackageName};
|
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct VersionedPackageName<V: FromStr<Err = semver::Error>>(PackageName, V);
|
|
||||||
|
|
||||||
impl<V: FromStr<Err = semver::Error>> FromStr for VersionedPackageName<V> {
|
|
||||||
type Err = anyhow::Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let (name, version) = s.split_once('@').ok_or_else(|| {
|
|
||||||
anyhow::anyhow!("invalid package name: {s}; expected format: name@version")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(VersionedPackageName(
|
|
||||||
name.to_string().parse()?,
|
|
||||||
version.parse()?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
|
||||||
pub enum Command {
|
|
||||||
/// Initializes a manifest file
|
|
||||||
Init,
|
|
||||||
|
|
||||||
/// Adds a package to the manifest
|
|
||||||
Add {
|
|
||||||
/// The package to add
|
|
||||||
#[clap(value_name = "PACKAGE")]
|
|
||||||
package: VersionedPackageName<VersionReq>,
|
|
||||||
|
|
||||||
/// Whether the package is a peer dependency
|
|
||||||
#[clap(long, short)]
|
|
||||||
peer: bool,
|
|
||||||
|
|
||||||
/// The realm of the package
|
|
||||||
#[clap(long, short)]
|
|
||||||
realm: Option<Realm>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Removes a package from the manifest
|
|
||||||
Remove {
|
|
||||||
/// The package to remove
|
|
||||||
#[clap(value_name = "PACKAGE")]
|
|
||||||
package: PackageName,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Lists outdated packages
|
|
||||||
Outdated,
|
|
||||||
|
|
||||||
/// Installs the dependencies of the project
|
|
||||||
Install {
|
|
||||||
/// Whether to use the lockfile for resolving dependencies
|
|
||||||
#[clap(long, short)]
|
|
||||||
locked: bool,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Runs the `bin` export of the specified package
|
|
||||||
Run {
|
|
||||||
/// The package to run
|
|
||||||
#[clap(value_name = "PACKAGE")]
|
|
||||||
package: PackageName,
|
|
||||||
|
|
||||||
/// The arguments to pass to the package
|
|
||||||
#[clap(last = true)]
|
|
||||||
args: Vec<String>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Searches for a package on the registry
|
|
||||||
Search {
|
|
||||||
/// The query to search for
|
|
||||||
#[clap(value_name = "QUERY")]
|
|
||||||
query: Option<String>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Publishes the project to the registry
|
|
||||||
Publish,
|
|
||||||
|
|
||||||
/// Converts a `wally.toml` file to a `pesde.yaml` file
|
|
||||||
Convert,
|
|
||||||
|
|
||||||
/// Begins a new patch
|
|
||||||
Patch {
|
|
||||||
/// The package to patch
|
|
||||||
#[clap(value_name = "PACKAGE")]
|
|
||||||
package: VersionedPackageName<Version>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Commits (finishes) the patch
|
|
||||||
PatchCommit {
|
|
||||||
/// The package's changed directory
|
|
||||||
#[clap(value_name = "DIRECTORY")]
|
|
||||||
dir: PathBuf,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Auth-related commands
|
|
||||||
Auth {
|
|
||||||
#[clap(subcommand)]
|
|
||||||
command: AuthCommand,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Config-related commands
|
|
||||||
Config {
|
|
||||||
#[clap(subcommand)]
|
|
||||||
command: ConfigCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
struct Cli {
|
|
||||||
#[clap(subcommand)]
|
|
||||||
command: Command,
|
|
||||||
|
|
||||||
/// The directory to run the command in
|
|
||||||
#[arg(short, long, value_name = "DIRECTORY")]
|
|
||||||
directory: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
|
||||||
struct CliConfig {
|
|
||||||
index_repo_url: String,
|
|
||||||
cache_dir: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CliConfig {
|
|
||||||
fn cache_dir(&self, directories: &ProjectDirs) -> PathBuf {
|
|
||||||
self.cache_dir
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| directories.cache_dir().to_path_buf())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CliParams {
|
|
||||||
index: GitIndex,
|
|
||||||
api_token_entry: Entry,
|
|
||||||
reqwest_client: reqwest::blocking::Client,
|
|
||||||
cli_config: CliConfig,
|
|
||||||
cwd: PathBuf,
|
|
||||||
multi: MultiProgress,
|
|
||||||
directories: ProjectDirs,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CliConfig {
|
|
||||||
fn write(&self, directories: &ProjectDirs) -> anyhow::Result<()> {
|
|
||||||
let cli_config_path = directories.config_dir().join("config.yaml");
|
|
||||||
serde_yaml::to_writer(
|
|
||||||
&mut std::fs::File::create(cli_config_path.as_path())?,
|
|
||||||
&self,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_request(request_builder: RequestBuilder) -> anyhow::Result<Response> {
|
|
||||||
let res = request_builder.send()?;
|
|
||||||
|
|
||||||
match res.error_for_status_ref() {
|
|
||||||
Ok(_) => Ok(res),
|
|
||||||
Err(e) => {
|
|
||||||
error!("request failed: {e}\nbody: {}", res.text()?);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let logger = pretty_env_logger::formatted_builder()
|
Lazy::force(&MULTI);
|
||||||
.parse_env(Env::default().default_filter_or("info"))
|
|
||||||
.build();
|
|
||||||
let multi = MultiProgress::new();
|
|
||||||
|
|
||||||
LogWrapper::new(multi.clone(), logger).try_init().unwrap();
|
match CLI.command.clone() {
|
||||||
|
Command::Auth { command } => auth_command(command),
|
||||||
let cli = Cli::parse();
|
Command::Config { command } => config_command(command),
|
||||||
|
cmd => root_command(cmd),
|
||||||
let directories = ProjectDirs::from("com", env!("CARGO_BIN_NAME"), env!("CARGO_BIN_NAME"))
|
|
||||||
.expect("couldn't get home directory");
|
|
||||||
|
|
||||||
let cli_config_path = directories.config_dir().join("config.yaml");
|
|
||||||
let cli_config = if cli_config_path.exists() {
|
|
||||||
serde_yaml::from_slice(&read(cli_config_path.as_path())?)?
|
|
||||||
} else {
|
|
||||||
let config = CliConfig {
|
|
||||||
index_repo_url: "https://github.com/daimond113/pesde-index".to_string(),
|
|
||||||
cache_dir: None,
|
|
||||||
};
|
|
||||||
create_dir_all(directories.config_dir())?;
|
|
||||||
config.write(&directories)?;
|
|
||||||
config
|
|
||||||
};
|
|
||||||
|
|
||||||
let cwd_buf = cli
|
|
||||||
.directory
|
|
||||||
.or(std::env::current_dir().ok())
|
|
||||||
.ok_or(anyhow::anyhow!("couldn't get current directory"))?;
|
|
||||||
|
|
||||||
let api_token_entry = Entry::new(env!("CARGO_BIN_NAME"), "api_token")?;
|
|
||||||
|
|
||||||
let mut hasher = DefaultHasher::new();
|
|
||||||
cli_config.index_repo_url.hash(&mut hasher);
|
|
||||||
let hash = hasher.finish().to_string();
|
|
||||||
|
|
||||||
let index = GitIndex::new(
|
|
||||||
cli_config.cache_dir(&directories).join("index").join(hash),
|
|
||||||
&cli_config.index_repo_url,
|
|
||||||
Some(Box::new(|| {
|
|
||||||
Box::new(|a, b, c| {
|
|
||||||
let git_authenticator = GitAuthenticator::new();
|
|
||||||
let config = git2::Config::open_default().unwrap();
|
|
||||||
let mut cred = git_authenticator.credentials(&config);
|
|
||||||
|
|
||||||
cred(a, b, c)
|
|
||||||
})
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
index.refresh()?;
|
|
||||||
|
|
||||||
let mut header_map = reqwest::header::HeaderMap::new();
|
|
||||||
header_map.insert(ACCEPT, "application/json".parse()?);
|
|
||||||
header_map.insert("X-GitHub-Api-Version", "2022-11-28".parse()?);
|
|
||||||
|
|
||||||
match api_token_entry.get_password() {
|
|
||||||
Ok(api_token) => {
|
|
||||||
header_map.insert(AUTHORIZATION, format!("Bearer {api_token}").parse()?);
|
|
||||||
}
|
|
||||||
Err(err) => match err {
|
|
||||||
keyring::Error::NoEntry => {}
|
|
||||||
_ => {
|
|
||||||
bail!("error getting api token from keyring: {err}")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let reqwest_client = reqwest::blocking::Client::builder()
|
|
||||||
.user_agent(concat!(
|
|
||||||
env!("CARGO_PKG_NAME"),
|
|
||||||
"/",
|
|
||||||
env!("CARGO_PKG_VERSION")
|
|
||||||
))
|
|
||||||
.default_headers(header_map)
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
let params = CliParams {
|
|
||||||
index,
|
|
||||||
api_token_entry,
|
|
||||||
reqwest_client,
|
|
||||||
cli_config,
|
|
||||||
cwd: cwd_buf,
|
|
||||||
multi,
|
|
||||||
directories,
|
|
||||||
};
|
|
||||||
|
|
||||||
match cli.command {
|
|
||||||
Command::Auth { command } => auth_command(command, params),
|
|
||||||
Command::Config { command } => config_command(command, params),
|
|
||||||
cmd => root_command(cmd, params),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,7 @@ impl<E: Send + Sync + 'static> MultithreadedJob<E> {
|
||||||
let (tx, rx) = std::sync::mpsc::channel();
|
let (tx, rx) = std::sync::mpsc::channel();
|
||||||
let pool = ThreadPool::new(6);
|
let pool = ThreadPool::new(6);
|
||||||
|
|
||||||
(Self {
|
(Self { progress: rx, pool }, tx)
|
||||||
progress: rx,
|
|
||||||
pool,
|
|
||||||
}, tx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the progress of the job
|
/// Returns the progress of the job
|
||||||
|
|
Loading…
Add table
Reference in a new issue