Fallback to installing from source (#114)

Closes #108
This commit is contained in:
Félix Saparelli 2022-04-29 10:15:43 +12:00 committed by GitHub
parent d68b0a209a
commit eeaba76b5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 535 additions and 192 deletions

607
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -19,29 +19,29 @@ pkg-fmt = "zip"
pkg-fmt = "zip" pkg-fmt = "zip"
[dependencies] [dependencies]
crates_io_api = "0.8.0" anyhow = "1.0.57"
cargo_metadata = "0.14.1"
tinytemplate = "1.2.1"
tokio = { version = "1.16.1", features = [ "full" ] }
log = "0.4.14"
structopt = "0.3.26"
simplelog = "0.11.2"
anyhow = "1.0.53"
reqwest = { version = "0.11.9", features = [ "rustls-tls" ], default-features = false }
tempdir = "0.3.7"
flate2 = "1.0.22"
tar = "0.4.38"
cargo_toml = "0.11.4"
serde = { version = "1.0.136", features = [ "derive" ] }
strum_macros = "0.23.1"
strum = "0.23.0"
dirs = "4.0.0"
crates-index = "0.18.5"
semver = "1.0.7"
xz2 = "0.1.6"
zip = "0.5.13"
async-trait = "0.1.52" async-trait = "0.1.52"
cargo_metadata = "0.14.2"
cargo_toml = "0.11.4"
crates-index = "0.18.7"
crates_io_api = "0.8.0"
dirs = "4.0.0"
flate2 = "1.0.22"
log = "0.4.14"
reqwest = { version = "0.11.10", features = [ "rustls-tls" ], default-features = false }
semver = "1.0.7"
serde = { version = "1.0.136", features = [ "derive" ] }
simplelog = "0.12.0"
structopt = "0.3.26"
strum = "0.24.0"
strum_macros = "0.24.0"
tar = "0.4.38"
tempdir = "0.3.7"
tinytemplate = "1.2.1"
tokio = { version = "1.18.0", features = [ "full" ] }
url = "2.2.2" url = "2.2.2"
xz2 = "0.1.6"
zip = "0.6.2"
[dev-dependencies] [dev-dependencies]
env_logger = "0.9.0" env_logger = "0.9.0"

View file

@ -1,11 +1,11 @@
use std::{path::PathBuf, str::FromStr}; use std::{path::PathBuf, str::FromStr};
use cargo_toml::{Package, Product};
use log::{debug, error, info, warn, LevelFilter}; use log::{debug, error, info, warn, LevelFilter};
use simplelog::{ColorChoice, ConfigBuilder, TermLogger, TerminalMode}; use simplelog::{ColorChoice, ConfigBuilder, TermLogger, TerminalMode};
use structopt::StructOpt; use structopt::StructOpt;
use tempdir::TempDir; use tempdir::TempDir;
use tokio::process::Command;
use cargo_binstall::{ use cargo_binstall::{
bins, bins,
@ -121,7 +121,8 @@ async fn main() -> Result<(), anyhow::Error> {
let (mut meta, binaries) = ( let (mut meta, binaries) = (
package package
.metadata .metadata
.map(|m| m.binstall) .as_ref()
.map(|m| m.binstall.clone())
.flatten() .flatten()
.unwrap_or(PkgMeta::default()), .unwrap_or(PkgMeta::default()),
manifest.bin, manifest.bin,
@ -160,11 +161,34 @@ async fn main() -> Result<(), anyhow::Error> {
fetchers.add(GhCrateMeta::new(&fetcher_data).await); fetchers.add(GhCrateMeta::new(&fetcher_data).await);
fetchers.add(QuickInstall::new(&fetcher_data).await); fetchers.add(QuickInstall::new(&fetcher_data).await);
let fetcher = fetchers.first_available().await.ok_or_else(|| { match fetchers.first_available().await {
error!("File does not exist remotely, cannot proceed"); Some(fetcher) => {
anyhow::anyhow!("No viable remote package found") install_from_package(
})?; binaries,
fetcher,
install_path,
meta,
opts,
package,
pkg_path,
temp_dir,
)
.await
}
None => install_from_source(opts, package).await,
}
}
async fn install_from_package(
binaries: Vec<Product>,
fetcher: &dyn Fetcher,
install_path: PathBuf,
mut meta: PkgMeta,
opts: Options,
package: Package<Meta>,
pkg_path: PathBuf,
temp_dir: TempDir,
) -> Result<(), anyhow::Error> {
// Prompt user for third-party source // Prompt user for third-party source
if fetcher.is_third_party() { if fetcher.is_third_party() {
warn!( warn!(
@ -293,3 +317,43 @@ async fn main() -> Result<(), anyhow::Error> {
info!("Installation complete!"); info!("Installation complete!");
Ok(()) Ok(())
} }
async fn install_from_source(opts: Options, package: Package<Meta>) -> Result<(), anyhow::Error> {
// Prompt user for source install
warn!("The package will be installed from source (with cargo)",);
if !opts.no_confirm && !opts.dry_run && !confirm()? {
warn!("Installation cancelled");
return Ok(());
}
if opts.dry_run {
info!(
"Dry-run: running `cargo install {} --version {} --target {}`",
package.name, package.version, opts.target
);
Ok(())
} else {
debug!(
"Running `cargo install {} --version {} --target {}`",
package.name, package.version, opts.target
);
let mut child = Command::new("cargo")
.arg("install")
.arg(package.name)
.arg("--version")
.arg(package.version)
.arg("--target")
.arg(opts.target)
.spawn()?;
debug!("Spawned command pid={:?}", child.id());
let status = child.wait().await?;
if status.success() {
info!("Cargo finished successfully");
Ok(())
} else {
error!("Cargo errored! {:?}", status);
Err(anyhow::anyhow!("Cargo install error"))
}
}
}