From 934ccc257b200547e3766004f70b2b1b3a6da53e Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sat, 17 Sep 2022 18:34:36 +1000 Subject: [PATCH] Support new cmdline option `--roots` (#389) * Add new field `Args::roots` * Use `env::var_os` to fetch `CARGO_INSTALL_ROOTS` Previously, it uses `env::var`, which might reject valid path just because it is not utf-8 string. * Update manifest if `CARGO_INSTALL_ROOT` is specified * Add new fn `install_path::get_cargo_roots_path` * Fix updating manifest: Use `cargo_roots` instead of default path * Rm `helpers::statics::cargo_home` Signed-off-by: Jiahao XU --- crates/bin/src/args.rs | 13 ++++++ crates/bin/src/entry.rs | 28 +++++++++---- crates/bin/src/install_path.rs | 41 +++++++++++++------ crates/binstalk/src/helpers/statics.rs | 16 +------- crates/binstalk/src/lib.rs | 1 + .../src/manifests/binstall_crates_v1.rs | 3 +- .../binstalk/src/manifests/cargo_crates_v1.rs | 3 +- 7 files changed, 67 insertions(+), 38 deletions(-) diff --git a/crates/bin/src/args.rs b/crates/bin/src/args.rs index 27ef49b06..f5a21497d 100644 --- a/crates/bin/src/args.rs +++ b/crates/bin/src/args.rs @@ -144,6 +144,19 @@ pub struct Args { #[clap(help_heading = "Options", long)] pub install_path: Option, + /// Install binaries with a custom cargo root. + /// + /// By default, we use `$CARGO_INSTALL_ROOT` or `$CARGO_HOME` as the + /// cargo root and global metadata files are updated with the + /// package information. + /// + /// Specifying another path here would install the binaries and update + /// the metadata files inside the path you specified. + /// + /// NOTE that `--install-path` takes precedence over this option. + #[clap(help_heading = "Options", long)] + pub roots: Option, + /// Deprecated, here for back-compat only. Secure is now on by default. #[clap(hide(true), long)] pub secure: bool, diff --git a/crates/bin/src/entry.rs b/crates/bin/src/entry.rs index e878bfeb5..10fcee1fc 100644 --- a/crates/bin/src/entry.rs +++ b/crates/bin/src/entry.rs @@ -41,10 +41,17 @@ pub async fn install_crates(mut args: Args, jobserver_client: LazyJobserverClien // Initialize UI thread let mut uithread = UIThread::new(!args.no_confirm); - let (install_path, metadata, temp_dir) = block_in_place(|| -> Result<_> { + let (install_path, cargo_roots, metadata, temp_dir) = block_in_place(|| -> Result<_> { + // Compute cargo_roots + let cargo_roots = + install_path::get_cargo_roots_path(args.roots.take()).ok_or_else(|| { + error!("No viable cargo roots path found of specified, try `--roots`"); + miette!("No cargo roots path found or specified") + })?; + // Compute install directory let (install_path, custom_install_path) = - install_path::get_install_path(args.install_path.as_deref()); + install_path::get_install_path(args.install_path.as_deref(), Some(&cargo_roots)); let install_path = install_path.ok_or_else(|| { error!("No viable install path found of specified, try `--install-path`"); miette!("No install path found or specified") @@ -54,8 +61,12 @@ pub async fn install_crates(mut args: Args, jobserver_client: LazyJobserverClien // Load metadata let metadata = if !custom_install_path { - debug!("Reading binstall/crates-v1.json"); - Some(Records::load()?) + let metadata_dir = cargo_roots.join("binstall"); + fs::create_dir_all(&metadata_dir).map_err(BinstallError::Io)?; + let manifest_path = metadata_dir.join("crates-v1.json"); + + debug!("Reading {}", manifest_path.display()); + Some(Records::load_from_path(&manifest_path)?) } else { None }; @@ -71,7 +82,7 @@ pub async fn install_crates(mut args: Args, jobserver_client: LazyJobserverClien .map_err(BinstallError::from) .wrap_err("Creating a temporary directory failed.")?; - Ok((install_path, metadata, temp_dir)) + Ok((install_path, cargo_roots, metadata, temp_dir)) })?; // Remove installed crates @@ -206,12 +217,11 @@ pub async fn install_crates(mut args: Args, jobserver_client: LazyJobserverClien block_in_place(|| { if let Some(mut records) = metadata { - // If using standardised install path, - // then create_dir_all(&install_path) would also - // create .cargo. + // The cargo manifest path is already created when loading + // metadata. debug!("Writing .crates.toml"); - CratesToml::append(metadata_vec.iter())?; + CratesToml::append_to_path(cargo_roots.join(".crates.toml"), metadata_vec.iter())?; debug!("Writing binstall/crates-v1.json"); for metadata in metadata_vec { diff --git a/crates/bin/src/install_path.rs b/crates/bin/src/install_path.rs index a979ff777..50a3849ea 100644 --- a/crates/bin/src/install_path.rs +++ b/crates/bin/src/install_path.rs @@ -1,31 +1,48 @@ use std::{ + env::var_os, path::{Path, PathBuf}, sync::Arc, }; -use binstalk::helpers::statics::cargo_home; +use binstalk::home::cargo_home; use log::debug; +pub fn get_cargo_roots_path(cargo_roots: Option) -> Option { + if let Some(p) = cargo_roots { + return Some(p); + } + + // Environmental variables + if let Some(p) = var_os("CARGO_INSTALL_ROOT") { + let p = PathBuf::from(p); + debug!("using CARGO_INSTALL_ROOT ({})", p.display()); + return Some(p); + } + + if let Ok(p) = cargo_home() { + debug!("using ({}) as cargo home", p.display()); + Some(p) + } else { + None + } +} + /// Fetch install path from environment /// roughly follows /// /// Return (install_path, is_custom_install_path) -pub fn get_install_path>(install_path: Option

) -> (Option>, bool) { +pub fn get_install_path>( + install_path: Option

, + cargo_roots: Option

, +) -> (Option>, bool) { // Command line override first first if let Some(p) = install_path { return (Some(Arc::from(p.as_ref())), true); } - // Environmental variables - if let Ok(p) = std::env::var("CARGO_INSTALL_ROOT") { - debug!("using CARGO_INSTALL_ROOT ({p})"); - let b = PathBuf::from(p); - return (Some(Arc::from(b.join("bin"))), true); - } - - if let Ok(p) = cargo_home() { - debug!("using ({}) as cargo home", p.display()); - return (Some(p.join("bin").into()), false); + // Then cargo_roots + if let Some(p) = cargo_roots { + return (Some(Arc::from(p.as_ref().join("bin"))), false); } // Local executable dir if no cargo is found diff --git a/crates/binstalk/src/helpers/statics.rs b/crates/binstalk/src/helpers/statics.rs index d2ff70ad2..7d48aca1d 100644 --- a/crates/binstalk/src/helpers/statics.rs +++ b/crates/binstalk/src/helpers/statics.rs @@ -1,20 +1,6 @@ -use std::{ - io::Error, - ops::Deref, - path::{Path, PathBuf}, -}; - -use once_cell::sync::{Lazy, OnceCell}; +use once_cell::sync::Lazy; use url::Url; -pub fn cargo_home() -> Result<&'static Path, Error> { - static CARGO_HOME: OnceCell = OnceCell::new(); - - CARGO_HOME - .get_or_try_init(home::cargo_home) - .map(Deref::deref) -} - pub fn cratesio_url() -> &'static Url { static CRATESIO: Lazy Url> = Lazy::new(|| Url::parse("https://github.com/rust-lang/crates.io-index").unwrap()); diff --git a/crates/binstalk/src/lib.rs b/crates/binstalk/src/lib.rs index 273f4d97b..a4b00d857 100644 --- a/crates/binstalk/src/lib.rs +++ b/crates/binstalk/src/lib.rs @@ -8,3 +8,4 @@ pub mod manifests; pub mod ops; pub use detect_targets::{get_desired_targets, DesiredTargets}; +pub use home; diff --git a/crates/binstalk/src/manifests/binstall_crates_v1.rs b/crates/binstalk/src/manifests/binstall_crates_v1.rs index c343bc23b..69b3df801 100644 --- a/crates/binstalk/src/manifests/binstall_crates_v1.rs +++ b/crates/binstalk/src/manifests/binstall_crates_v1.rs @@ -15,11 +15,12 @@ use std::{ }; use fs_lock::FileLock; +use home::cargo_home; use miette::Diagnostic; use serde::Serialize; use thiserror::Error; -use crate::{fs::create_if_not_exist, helpers::statics::cargo_home}; +use crate::fs::create_if_not_exist; use super::crate_info::CrateInfo; diff --git a/crates/binstalk/src/manifests/cargo_crates_v1.rs b/crates/binstalk/src/manifests/cargo_crates_v1.rs index 5b2ca1109..aa1fa2a53 100644 --- a/crates/binstalk/src/manifests/cargo_crates_v1.rs +++ b/crates/binstalk/src/manifests/cargo_crates_v1.rs @@ -17,11 +17,12 @@ use std::{ use compact_str::CompactString; use fs_lock::FileLock; +use home::cargo_home; use miette::Diagnostic; use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::{fs::create_if_not_exist, helpers::statics::cargo_home}; +use crate::fs::create_if_not_exist; use super::crate_info::CrateInfo;