mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-24 22:30:03 +00:00
cleaning up binary logic, using standard [[bin]] definitions now
This commit is contained in:
parent
d7aae3275d
commit
5fd78341c8
5 changed files with 228 additions and 114 deletions
87
Cargo.lock
generated
87
Cargo.lock
generated
|
@ -6,6 +6,15 @@ version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
@ -127,6 +136,7 @@ dependencies = [
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
"crates_io_api",
|
"crates_io_api",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"env_logger",
|
||||||
"flate2",
|
"flate2",
|
||||||
"log",
|
"log",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
@ -139,7 +149,7 @@ dependencies = [
|
||||||
"tar",
|
"tar",
|
||||||
"tempdir",
|
"tempdir",
|
||||||
"tinytemplate",
|
"tinytemplate",
|
||||||
"tokio 1.0.1",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -247,7 +257,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio 0.2.24",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -309,6 +319,19 @@ dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fake-simd"
|
name = "fake-simd"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -521,7 +544,7 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio 0.2.24",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-futures",
|
"tracing-futures",
|
||||||
|
@ -584,6 +607,12 @@ version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
|
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.13.9"
|
version = "0.13.9"
|
||||||
|
@ -602,7 +631,7 @@ dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project 1.0.2",
|
"pin-project 1.0.2",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio 0.2.24",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
"want",
|
"want",
|
||||||
|
@ -617,7 +646,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"hyper",
|
"hyper",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"tokio 0.2.24",
|
"tokio",
|
||||||
"tokio-tls",
|
"tokio-tls",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1149,6 +1178,24 @@ dependencies = [
|
||||||
"rust-argon2",
|
"rust-argon2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
"thread_local",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remove_dir_all"
|
name = "remove_dir_all"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -1185,7 +1232,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"tokio 0.2.24",
|
"tokio",
|
||||||
"tokio-tls",
|
"tokio-tls",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
@ -1461,6 +1508,15 @@ dependencies = [
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
|
@ -1513,25 +1569,14 @@ dependencies = [
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"pin-project-lite 0.1.11",
|
"pin-project-lite 0.1.11",
|
||||||
"slab",
|
"slab",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d258221f566b6c803c7b4714abadc080172b272090cdc5e244a6d4dd13c3a6bd"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"num_cpus",
|
|
||||||
"pin-project-lite 0.2.0",
|
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "1.0.0"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42517d2975ca3114b22a16192634e8241dc5cc1f130be194645970cc1c371494"
|
checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1545,7 +1590,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
|
checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"tokio 0.2.24",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1559,7 +1604,7 @@ dependencies = [
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"log",
|
"log",
|
||||||
"pin-project-lite 0.1.11",
|
"pin-project-lite 0.1.11",
|
||||||
"tokio 0.2.24",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -7,12 +7,19 @@ authors = ["ryan <ryan@kurte.nz>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
|
|
||||||
|
[package.metadata.binstall]
|
||||||
|
pkg-url = "https://github.com/ryankurte/cargo-binstall/releases/download/v{ version }/cargo-binstall-{ target }.tgz"
|
||||||
|
pkg-fmt = "tgz"
|
||||||
|
|
||||||
|
[[pkg_bin]]
|
||||||
|
name = "cargo-binstall"
|
||||||
|
path = "cargo-binstall-{ target }"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
crates_io_api = "0.6.1"
|
crates_io_api = "0.6.1"
|
||||||
cargo_metadata = "0.12.1"
|
cargo_metadata = "0.12.1"
|
||||||
tinytemplate = "1.1.0"
|
tinytemplate = "1.1.0"
|
||||||
tokio = { version = "1.0.1", features = [ "macros", "rt-multi-thread" ] }
|
tokio = { version = "0.2.24", features = [ "macros" ] }
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
structopt = "0.3.21"
|
structopt = "0.3.21"
|
||||||
simplelog = "0.8.0"
|
simplelog = "0.8.0"
|
||||||
|
@ -27,5 +34,10 @@ strum_macros = "0.20.1"
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
dirs = "3.0.1"
|
dirs = "3.0.1"
|
||||||
serde_derive = "1.0.118"
|
serde_derive = "1.0.118"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
env_logger = "0.8.2"
|
||||||
#github = "0.1.2"
|
#github = "0.1.2"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
#reqwest = { git = "https://github.com/seanmonstar/reqwest.git" }
|
||||||
|
|
|
@ -3,12 +3,25 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use log::{debug, info, error};
|
use log::{debug, info, error};
|
||||||
|
|
||||||
|
use cargo_toml::{Manifest};
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
use tar::Archive;
|
use tar::Archive;
|
||||||
|
|
||||||
|
|
||||||
|
use crate::{Meta};
|
||||||
|
|
||||||
use super::PkgFmt;
|
use super::PkgFmt;
|
||||||
|
|
||||||
|
/// Load binstall metadata from the crate `Cargo.toml` at the provided path
|
||||||
|
pub fn load_manifest_path<P: AsRef<Path>>(manifest_path: P) -> Result<Manifest<Meta>, anyhow::Error> {
|
||||||
|
debug!("Reading manifest: {}", manifest_path.as_ref().display());
|
||||||
|
|
||||||
|
// Load and parse manifest (this checks file system for binary output names)
|
||||||
|
let manifest = Manifest::<Meta>::from_path_with_metadata(manifest_path)?;
|
||||||
|
|
||||||
|
// Return metadata
|
||||||
|
Ok(manifest)
|
||||||
|
}
|
||||||
|
|
||||||
/// Download a file from the provided URL to the provided path
|
/// Download a file from the provided URL to the provided path
|
||||||
pub async fn download<P: AsRef<Path>>(url: &str, path: P) -> Result<(), anyhow::Error> {
|
pub async fn download<P: AsRef<Path>>(url: &str, path: P) -> Result<(), anyhow::Error> {
|
||||||
|
@ -63,8 +76,6 @@ pub fn extract<S: AsRef<Path>, P: AsRef<Path>>(source: S, fmt: PkgFmt, path: P)
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Fetch install path from environment
|
/// Fetch install path from environment
|
||||||
/// roughly follows https://doc.rust-lang.org/cargo/commands/cargo-install.html#description
|
/// roughly follows https://doc.rust-lang.org/cargo/commands/cargo-install.html#description
|
||||||
pub fn get_install_path<P: AsRef<Path>>(install_path: Option<P>) -> Option<PathBuf> {
|
pub fn get_install_path<P: AsRef<Path>>(install_path: Option<P>) -> Option<PathBuf> {
|
||||||
|
|
98
src/lib.rs
98
src/lib.rs
|
@ -1,4 +1,3 @@
|
||||||
use structopt::StructOpt;
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use strum_macros::{Display, EnumString, EnumVariantNames};
|
use strum_macros::{Display, EnumString, EnumVariantNames};
|
||||||
use tinytemplate::TinyTemplate;
|
use tinytemplate::TinyTemplate;
|
||||||
|
@ -15,10 +14,10 @@ pub use drivers::*;
|
||||||
pub const TARGET: &'static str = env!("TARGET");
|
pub const TARGET: &'static str = env!("TARGET");
|
||||||
|
|
||||||
/// Default package path template (may be overridden in package Cargo.toml)
|
/// Default package path template (may be overridden in package Cargo.toml)
|
||||||
pub const DEFAULT_PKG_PATH: &'static str = "{ repo }/releases/download/v{ version }/{ name }-{ target }-v{ version }.{ format }";
|
pub const DEFAULT_PKG_URL: &'static str = "{ repo }/releases/download/v{ version }/{ name }-{ target }-v{ version }.{ format }";
|
||||||
|
|
||||||
/// Default binary name template (may be overridden in package Cargo.toml)
|
/// Default binary name template (may be overridden in package Cargo.toml)
|
||||||
pub const DEFAULT_BIN_NAME: &'static str = "{ name }-{ target }-v{ version }";
|
pub const DEFAULT_BIN_PATH: &'static str = "{ name }-{ target }-v{ version }/{ name }{ format }";
|
||||||
|
|
||||||
|
|
||||||
/// Binary format enumeration
|
/// Binary format enumeration
|
||||||
|
@ -41,30 +40,54 @@ impl Default for PkgFmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `binstall` metadata container
|
||||||
|
///
|
||||||
|
/// Required to nest metadata under `package.metadata.binstall`
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub struct Meta {
|
||||||
|
pub binstall: Option<PkgMeta>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Metadata for binary installation use.
|
/// Metadata for binary installation use.
|
||||||
///
|
///
|
||||||
/// Exposed via `[package.metadata]` in `Cargo.toml`
|
/// Exposed via `[package.metadata]` in `Cargo.toml`
|
||||||
#[derive(Clone, Debug, StructOpt, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case", default)]
|
||||||
pub struct Meta {
|
pub struct PkgMeta {
|
||||||
/// Path template override for package downloads
|
/// URL template for package downloads
|
||||||
pub pkg_url: Option<String>,
|
pub pkg_url: String,
|
||||||
|
|
||||||
/// Package name override for package downloads
|
/// Format for package downloads
|
||||||
pub pkg_name: Option<String>,
|
pub pkg_fmt: PkgFmt,
|
||||||
|
|
||||||
/// Format override for package downloads
|
/// Path template for binary files in packages
|
||||||
#[serde(default)]
|
pub bin_dir: String,
|
||||||
pub pkg_fmt: Option<PkgFmt>,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
/// Filters for binary files allowed in the package
|
|
||||||
pub pkg_bins: Vec<String>,
|
|
||||||
|
|
||||||
/// Public key for package verification (base64 encoded)
|
/// Public key for package verification (base64 encoded)
|
||||||
pub pub_key: Option<String>,
|
pub pub_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for PkgMeta {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
pkg_url: DEFAULT_PKG_URL.to_string(),
|
||||||
|
pkg_fmt: PkgFmt::default(),
|
||||||
|
bin_dir: DEFAULT_BIN_PATH.to_string(),
|
||||||
|
pub_key: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub struct BinMeta {
|
||||||
|
/// Binary name
|
||||||
|
pub name: String,
|
||||||
|
/// Binary template path (within package)
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|
||||||
/// Template for constructing download paths
|
/// Template for constructing download paths
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
|
@ -91,3 +114,44 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::{load_manifest_path};
|
||||||
|
|
||||||
|
use cargo_toml::Product;
|
||||||
|
|
||||||
|
fn init() {
|
||||||
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_meta() {
|
||||||
|
init();
|
||||||
|
|
||||||
|
let mut manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||||
|
manifest_dir.push_str("/Cargo.toml");
|
||||||
|
|
||||||
|
let manifest = load_manifest_path(&manifest_dir).expect("Error parsing metadata");
|
||||||
|
let package = manifest.package.unwrap();
|
||||||
|
let meta = package.metadata.map(|m| m.binstall ).flatten().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(&package.name, "cargo-binstall");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
&meta.pkg_url,
|
||||||
|
"https://github.com/ryankurte/cargo-binstall/releases/download/v{ version }/cargo-binstall-{ target }.tgz"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
manifest.bin.as_slice(),
|
||||||
|
&[
|
||||||
|
Product{
|
||||||
|
name: Some("cargo-binstall".to_string()),
|
||||||
|
path: Some("src/main.rs".to_string()),
|
||||||
|
edition: Some(cargo_toml::Edition::E2018),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
126
src/main.rs
126
src/main.rs
|
@ -5,8 +5,6 @@ use simplelog::{TermLogger, ConfigBuilder, TerminalMode};
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use cargo_toml::Manifest;
|
|
||||||
|
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
|
|
||||||
use cargo_binstall::*;
|
use cargo_binstall::*;
|
||||||
|
@ -19,7 +17,7 @@ struct Options {
|
||||||
#[structopt()]
|
#[structopt()]
|
||||||
name: String,
|
name: String,
|
||||||
|
|
||||||
/// Package version to install
|
/// Filter for package version to install
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
version: Option<String>,
|
version: Option<String>,
|
||||||
|
|
||||||
|
@ -44,6 +42,10 @@ struct Options {
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
no_symlinks: bool,
|
no_symlinks: bool,
|
||||||
|
|
||||||
|
/// Dry run, fetch and show changes without installing binaries
|
||||||
|
#[structopt(long)]
|
||||||
|
dry_run: bool,
|
||||||
|
|
||||||
/// Override manifest source.
|
/// Override manifest source.
|
||||||
/// This skips searching crates.io for a manifest and uses
|
/// This skips searching crates.io for a manifest and uses
|
||||||
/// the specified path directly, useful for debugging and
|
/// the specified path directly, useful for debugging and
|
||||||
|
@ -56,6 +58,8 @@ struct Options {
|
||||||
log_level: LevelFilter,
|
log_level: LevelFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), anyhow::Error> {
|
async fn main() -> Result<(), anyhow::Error> {
|
||||||
|
|
||||||
|
@ -85,71 +89,36 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
// Fetch crate via crates.io, git, or use a local manifest path
|
// Fetch crate via crates.io, git, or use a local manifest path
|
||||||
// TODO: work out which of these to do based on `opts.name`
|
// TODO: work out which of these to do based on `opts.name`
|
||||||
// TODO: support git-based fetches (whole repo name rather than just crate name)
|
// TODO: support git-based fetches (whole repo name rather than just crate name)
|
||||||
let crate_path = match opts.manifest_path {
|
let manifest_path = match opts.manifest_path.clone() {
|
||||||
Some(p) => {
|
Some(p) => p,
|
||||||
p
|
None => fetch_crate_cratesio(&opts.name, opts.version.as_deref(), temp_dir.path()).await?,
|
||||||
},
|
|
||||||
None => {
|
|
||||||
fetch_crate_cratesio(&opts.name, opts.version.as_deref(), temp_dir.path()).await?
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Read cargo manifest
|
debug!("Reading manifest: {}", manifest_path.display());
|
||||||
let manifest_path = crate_path.join("Cargo.toml");
|
let manifest = load_manifest_path(manifest_path.join("Cargo.toml"))?;
|
||||||
|
let package = manifest.package.unwrap();
|
||||||
|
|
||||||
debug!("Reading manifest: {}", manifest_path.to_str().unwrap());
|
let (meta, binaries) = (
|
||||||
let package = match Manifest::<Meta>::from_path_with_metadata(&manifest_path) {
|
package.metadata.map(|m| m.binstall ).flatten().unwrap_or(PkgMeta::default()),
|
||||||
Ok(m) => m.package.unwrap(),
|
manifest.bin,
|
||||||
Err(e) => {
|
);
|
||||||
error!("Error reading manifest '{}': {:?}", manifest_path.to_str().unwrap(), e);
|
|
||||||
return Err(e.into());
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let meta = package.metadata;
|
|
||||||
debug!("Retrieved metadata: {:?}", meta);
|
|
||||||
|
|
||||||
// Select which package path to use
|
|
||||||
let pkg_url = match meta.as_ref().map(|m| m.pkg_url.clone() ).flatten() {
|
|
||||||
Some(m) => {
|
|
||||||
debug!("Using package url: '{}'", &m);
|
|
||||||
m
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
debug!("No `pkg-url` key found in Cargo.toml or `--pkg-url` argument provided");
|
|
||||||
debug!("Using default url: {}", DEFAULT_PKG_PATH);
|
|
||||||
DEFAULT_PKG_PATH.to_string()
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Select bin format to use
|
|
||||||
let pkg_fmt = match meta.as_ref().map(|m| m.pkg_fmt.clone() ).flatten() {
|
|
||||||
Some(m) => m.clone(),
|
|
||||||
_ => PkgFmt::Tgz,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Override package name if required
|
|
||||||
let pkg_name = match meta.as_ref().map(|m| m.pkg_name.clone() ).flatten() {
|
|
||||||
Some(m) => m,
|
|
||||||
_ => opts.name.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generate context for URL interpolation
|
// Generate context for URL interpolation
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
name: pkg_name.to_string(),
|
name: opts.name.clone(),
|
||||||
repo: package.repository,
|
repo: package.repository,
|
||||||
target: opts.target.clone(),
|
target: opts.target.clone(),
|
||||||
version: package.version.clone(),
|
version: package.version.clone(),
|
||||||
format: pkg_fmt.to_string(),
|
format: meta.pkg_fmt.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Using context: {:?}", ctx);
|
debug!("Using context: {:?}", ctx);
|
||||||
|
|
||||||
// Interpolate version / target / etc.
|
// Interpolate version / target / etc.
|
||||||
let rendered = ctx.render(&pkg_url)?;
|
let rendered = ctx.render(&meta.pkg_url)?;
|
||||||
|
|
||||||
// Compute install directory
|
// Compute install directory
|
||||||
let install_path = match get_install_path(opts.install_path) {
|
let install_path = match get_install_path(opts.install_path.as_deref()) {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => {
|
||||||
error!("No viable install path found of specified, try `--install-path`");
|
error!("No viable install path found of specified, try `--install-path`");
|
||||||
|
@ -162,7 +131,7 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
info!("Downloading package from: '{}'", rendered);
|
info!("Downloading package from: '{}'", rendered);
|
||||||
|
|
||||||
// Download package
|
// Download package
|
||||||
let pkg_path = temp_dir.path().join(format!("pkg-{}.{}", pkg_name, pkg_fmt));
|
let pkg_path = temp_dir.path().join(format!("pkg-{}.{}", opts.name, meta.pkg_fmt));
|
||||||
download(&rendered, pkg_path.to_str().unwrap()).await?;
|
download(&rendered, pkg_path.to_str().unwrap()).await?;
|
||||||
|
|
||||||
#[cfg(incomplete)]
|
#[cfg(incomplete)]
|
||||||
|
@ -191,39 +160,52 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract files
|
// Extract files
|
||||||
let bin_path = temp_dir.path().join(format!("bin-{}", pkg_name));
|
let bin_path = temp_dir.path().join(format!("bin-{}", opts.name));
|
||||||
extract(&pkg_path, pkg_fmt, &bin_path)?;
|
extract(&pkg_path, meta.pkg_fmt, &bin_path)?;
|
||||||
|
|
||||||
// Bypass cleanup if disabled
|
// Bypass cleanup if disabled
|
||||||
if opts.no_cleanup {
|
if opts.no_cleanup {
|
||||||
let _ = temp_dir.into_path();
|
let _ = temp_dir.into_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if binaries.len() == 0 {
|
||||||
|
error!("No binaries specified (or inferred from file system)");
|
||||||
|
return Err(anyhow::anyhow!("No binaries specified (or inferred from file system)"));
|
||||||
|
}
|
||||||
|
|
||||||
// List files to be installed
|
// List files to be installed
|
||||||
// TODO: check extracted files are sensible / filter by allowed files
|
// based on those found via Cargo.toml
|
||||||
// TODO: this seems overcomplicated / should be able to be simplified?
|
let bin_files = binaries.iter().map(|p| {
|
||||||
let bin_files = std::fs::read_dir(&bin_path)?;
|
// Fetch binary base name
|
||||||
let bin_files: Vec<_> = bin_files.filter_map(|f| f.ok() ).map(|f| {
|
let base_name = p.name.clone().unwrap();
|
||||||
let source = f.path().to_owned();
|
|
||||||
let name = source.file_name().map(|v| v.to_str()).flatten().unwrap().to_string();
|
|
||||||
|
|
||||||
// Trim target and version from name if included in binary file name
|
// Generate binary path via interpolation
|
||||||
let base_name = name.replace(&format!("-{}", TARGET), "")
|
let mut bin_ctx = ctx.clone();
|
||||||
.replace(&format!("-v{}", ctx.version), "")
|
bin_ctx.name = base_name.clone();
|
||||||
.replace(&format!("-{}", ctx.version), "");
|
|
||||||
|
|
||||||
// Generate install destination with version suffix
|
// Append .exe to windows binaries
|
||||||
let dest = install_path.join(format!("{}-v{}", base_name, ctx.version));
|
bin_ctx.format = match &opts.target.clone().contains("windows") {
|
||||||
|
true => ".exe".to_string(),
|
||||||
|
false => "".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
// Generate symlink path from base name
|
// Generate install paths
|
||||||
|
// Source path is the download dir + the generated binary path
|
||||||
|
let source_file_path = bin_ctx.render(&meta.bin_dir)?;
|
||||||
|
let source = bin_path.join(&source_file_path);
|
||||||
|
|
||||||
|
// Destination path is the install dir + base-name-version{.format}
|
||||||
|
let dest_file_path = bin_ctx.render("{ name }-v{ version }{ format }")?;
|
||||||
|
let dest = install_path.join(dest_file_path);
|
||||||
|
|
||||||
|
// Link at install dir + base name
|
||||||
let link = install_path.join(&base_name);
|
let link = install_path.join(&base_name);
|
||||||
|
|
||||||
(base_name, source, dest, link)
|
Ok((base_name, source, dest, link))
|
||||||
}).collect();
|
}).collect::<Result<Vec<_>, anyhow::Error>>()?;
|
||||||
|
|
||||||
|
|
||||||
// Prompt user for confirmation
|
// Prompt user for confirmation
|
||||||
info!("This will install the following files:");
|
info!("This will install the following binaries:");
|
||||||
for (name, source, dest, _link) in &bin_files {
|
for (name, source, dest, _link) in &bin_files {
|
||||||
info!(" - {} ({} -> {})", name, source.file_name().unwrap().to_string_lossy(), dest.display());
|
info!(" - {} ({} -> {})", name, source.file_name().unwrap().to_string_lossy(), dest.display());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue