Skip to content

Commit

Permalink
new: Add "user" pin location. (#608)
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj authored Sep 6, 2024
1 parent 30f794b commit 43eafbb
Show file tree
Hide file tree
Showing 21 changed files with 378 additions and 91 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ jobs:
- uses: moonrepo/setup-rust@v1
with:
bins: cargo-wasi, cargo-nextest, just
cache: ${{ runner.os != 'Linux' }}
cache-base: "^(master|develop-)"
cache: false
# cache: ${{ runner.os != 'Linux' }}
# cache-base: "^(master|develop-)"
- if: ${{ runner.os != 'Windows' }}
run: just build-wasm
env:
Expand Down Expand Up @@ -95,7 +96,8 @@ jobs:
- uses: moonrepo/setup-rust@v1
with:
bins: cargo-wasi, just
cache-base: "^(master|develop-)"
cache: false
# cache-base: "^(master|develop-)"
- run: just build
- run: just build-wasm
- run: cargo run -- --help
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,16 @@

#### 🚀 Updates

- Added support for updating the `~/.prototools` file (root of user home directory).
- Added `--pin=user` to `proto install`.
- Added `--to=global|local|user` to `proto alias`, `pin`, and `plugin add`.
- Added `--from=global|local|user` to `proto unalias`, `unpin`, and `plugin remove`.
- Added aliases for pin locations.
- `cwd` -> `local`
- `home` -> `user`
- `store` -> `global`
- Added new `settings.offline` settings that control how offline checks work.
- Deprecated the `--global` flag.

#### ⚙️ Internal

Expand Down
31 changes: 18 additions & 13 deletions crates/cli/src/commands/alias.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::error::ProtoCliError;
use crate::helpers::{map_pin_type, PinOption};
use crate::session::ProtoSession;
use clap::Args;
use proto_core::{is_alias_name, Id, ProtoConfig, UnresolvedVersionSpec};
Expand All @@ -16,11 +17,11 @@ pub struct AliasArgs {
#[arg(required = true, help = "Version or alias to associate with")]
spec: UnresolvedVersionSpec,

#[arg(
long,
help = "Add to the global ~/.proto/.prototools instead of local ./.prototools"
)]
#[arg(long, group = "pin", help = "Add to the global ~/.proto/.prototools")]
global: bool,

#[arg(long, group = "pin", help = "Location of .prototools to add to")]
to: Option<PinOption>,
}

#[tracing::instrument(skip_all)]
Expand All @@ -40,16 +41,20 @@ pub async fn alias(session: ProtoSession, args: AliasArgs) -> AppResult {

let tool = session.load_tool(&args.id).await?;

let config_path = ProtoConfig::update(tool.proto.get_config_dir(args.global), |config| {
let tool_configs = config.tools.get_or_insert(Default::default());
let config_path = ProtoConfig::update(
tool.proto
.get_config_dir(map_pin_type(args.global, args.to)),
|config| {
let tool_configs = config.tools.get_or_insert(Default::default());

tool_configs
.entry(tool.id.clone())
.or_default()
.aliases
.get_or_insert(Default::default())
.insert(args.alias.clone(), args.spec.clone());
})?;
tool_configs
.entry(tool.id.clone())
.or_default()
.aliases
.get_or_insert(Default::default())
.insert(args.alias.clone(), args.spec.clone());
},
)?;

println!(
"Added alias {} ({}) to config {}",
Expand Down
23 changes: 9 additions & 14 deletions crates/cli/src/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::helpers::*;
use crate::session::ProtoSession;
use crate::shell::{self, Export};
use crate::telemetry::{track_usage, Metric};
use clap::{Args, ValueEnum};
use clap::Args;
use indicatif::ProgressBar;
use miette::IntoDiagnostic;
use proto_core::flow::install::{InstallOptions, InstallPhase};
Expand All @@ -19,12 +19,6 @@ use tokio::task::JoinSet;
use tokio::time::sleep;
use tracing::{debug, instrument};

#[derive(Clone, Debug, ValueEnum)]
pub enum PinOption {
Global,
Local,
}

#[derive(Args, Clone, Debug, Default)]
pub struct InstallArgs {
#[arg(help = "ID of a single tool to install")]
Expand Down Expand Up @@ -62,6 +56,7 @@ impl InstallArgs {
fn get_pin_type(&self) -> Option<PinType> {
self.pin.as_ref().map(|pin| match pin {
Some(PinOption::Global) => PinType::Global,
Some(PinOption::User) => PinType::User,
_ => PinType::Local,
})
}
Expand All @@ -82,30 +77,30 @@ async fn pin_version(
) -> miette::Result<bool> {
let config = tool.proto.load_config()?;
let spec = tool.get_resolved_version().to_unresolved_spec();
let mut global = false;
let mut pin_type = PinType::Local;
let mut pin = false;

// via `--pin` arg
if let Some(pin_type) = arg_pin_type {
global = matches!(pin_type, PinType::Global);
if let Some(custom_type) = arg_pin_type {
pin_type = *custom_type;
pin = true;
}
// Or the first time being installed
else if !config.versions.contains_key(&tool.id) {
global = true;
pin_type = PinType::Global;
pin = true;
}

// via `pin-latest` setting
if initial_version.is_latest() {
if let Some(pin_type) = &config.settings.pin_latest {
global = matches!(pin_type, PinType::Global);
if let Some(custom_type) = &config.settings.pin_latest {
pin_type = *custom_type;
pin = true;
}
}

if pin {
internal_pin(tool, &spec, global, true).await?;
internal_pin(tool, &spec, pin_type, true).await?;
}

Ok(pin)
Expand Down
20 changes: 11 additions & 9 deletions crates/cli/src/commands/pin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::helpers::{map_pin_type, PinOption};
use crate::session::ProtoSession;
use clap::Args;
use proto_core::{Id, ProtoConfig, Tool, UnresolvedVersionSpec};
use proto_core::{Id, PinType, ProtoConfig, Tool, UnresolvedVersionSpec};
use starbase::AppResult;
use starbase_styles::color;
use std::collections::BTreeMap;
Expand All @@ -15,28 +16,28 @@ pub struct PinArgs {
#[arg(required = true, help = "Version or alias of tool")]
pub spec: UnresolvedVersionSpec,

#[arg(
long,
help = "Pin to the global ~/.proto/.prototools instead of local ./.prototools"
)]
#[arg(long, group = "pin", help = "Pin to the global ~/.proto/.prototools")]
pub global: bool,

#[arg(long, help = "Resolve the version before pinning")]
pub resolve: bool,

#[arg(long, group = "pin", help = "Location of .prototools to pin to")]
pub to: Option<PinOption>,
}

pub async fn internal_pin(
tool: &mut Tool,
spec: &UnresolvedVersionSpec,
global: bool,
pin: PinType,
link: bool,
) -> miette::Result<PathBuf> {
// Create symlink to this new version
if global && link {
if pin == PinType::Global && link {
tool.symlink_bins(true).await?;
}

let config_path = ProtoConfig::update(tool.proto.get_config_dir(global), |config| {
let config_path = ProtoConfig::update(tool.proto.get_config_dir(pin), |config| {
config
.versions
.get_or_insert(BTreeMap::default())
Expand All @@ -63,7 +64,8 @@ pub async fn pin(session: ProtoSession, args: PinArgs) -> AppResult {
args.spec.clone()
};

let config_path = internal_pin(&mut tool, &spec, args.global, false).await?;
let config_path =
internal_pin(&mut tool, &spec, map_pin_type(args.global, args.to), false).await?;

println!(
"Pinned {} to {} in {}",
Expand Down
26 changes: 16 additions & 10 deletions crates/cli/src/commands/plugin/add.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::helpers::{map_pin_type, PinOption};
use crate::session::ProtoSession;
use clap::Args;
use proto_core::{Id, PluginLocator, ProtoConfig};
Expand All @@ -12,21 +13,26 @@ pub struct AddPluginArgs {
#[arg(required = true, help = "Locator string to find and load the plugin")]
plugin: PluginLocator,

#[arg(
long,
help = "Add to the global ~/.proto/.prototools instead of local ./.prototools"
)]
#[arg(long, group = "pin", help = "Add to the global ~/.proto/.prototools")]
global: bool,

#[arg(long, group = "pin", help = "Location of .prototools to add to")]
to: Option<PinOption>,
}

#[tracing::instrument(skip_all)]
pub async fn add(session: ProtoSession, args: AddPluginArgs) -> AppResult {
let config_path = ProtoConfig::update(session.env.get_config_dir(args.global), |config| {
config
.plugins
.get_or_insert(Default::default())
.insert(args.id.clone(), args.plugin.clone());
})?;
let config_path = ProtoConfig::update(
session
.env
.get_config_dir(map_pin_type(args.global, args.to)),
|config| {
config
.plugins
.get_or_insert(Default::default())
.insert(args.id.clone(), args.plugin.clone());
},
)?;

println!(
"Added plugin {} to config {}",
Expand Down
20 changes: 13 additions & 7 deletions crates/cli/src/commands/plugin/remove.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::error::ProtoCliError;
use crate::helpers::{map_pin_type, PinOption};
use crate::session::ProtoSession;
use clap::Args;
use proto_core::{Id, ProtoConfig, PROTO_CONFIG_NAME};
Expand All @@ -12,22 +13,27 @@ pub struct RemovePluginArgs {

#[arg(
long,
help = "Remove from the global ~/.proto/.prototools instead of local ./.prototools"
group = "pin",
help = "Remove from the global ~/.proto/.prototools"
)]
global: bool,

#[arg(long, group = "pin", help = "Location of .prototools to remove from")]
from: Option<PinOption>,
}

#[tracing::instrument(skip_all)]
pub async fn remove(session: ProtoSession, args: RemovePluginArgs) -> AppResult {
if !args.global {
let config_path = session.env.cwd.join(PROTO_CONFIG_NAME);
let config_dir = session
.env
.get_config_dir(map_pin_type(args.global, args.from));
let config_path = config_dir.join(PROTO_CONFIG_NAME);

if !config_path.exists() {
return Err(ProtoCliError::MissingToolsConfigInCwd { path: config_path }.into());
}
if !config_path.exists() {
return Err(ProtoCliError::MissingToolsConfigInCwd { path: config_path }.into());
}

let config_path = ProtoConfig::update(session.env.get_config_dir(args.global), |config| {
let config_path = ProtoConfig::update(config_dir, |config| {
if let Some(plugins) = &mut config.plugins {
plugins.remove(&args.id);
}
Expand Down
25 changes: 17 additions & 8 deletions crates/cli/src/commands/unalias.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::helpers::{map_pin_type, PinOption};
use crate::session::ProtoSession;
use clap::Args;
use proto_core::{Id, ProtoConfig};
Expand All @@ -15,25 +16,33 @@ pub struct UnaliasArgs {

#[arg(
long,
help = "Remove from the global ~/.proto/.prototools instead of local ./.prototools"
group = "pin",
help = "Remove from the global ~/.proto/.prototools"
)]
global: bool,

#[arg(long, group = "pin", help = "Location of .prototools to remove from")]
from: Option<PinOption>,
}

#[tracing::instrument(skip_all)]
pub async fn unalias(session: ProtoSession, args: UnaliasArgs) -> AppResult {
let tool = session.load_tool(&args.id).await?;
let mut value = None;

let config_path = ProtoConfig::update(tool.proto.get_config_dir(args.global), |config| {
if let Some(tool_configs) = &mut config.tools {
if let Some(tool_config) = tool_configs.get_mut(&tool.id) {
if let Some(aliases) = &mut tool_config.aliases {
value = aliases.remove(&args.alias);
let config_path = ProtoConfig::update(
tool.proto
.get_config_dir(map_pin_type(args.global, args.from)),
|config| {
if let Some(tool_configs) = &mut config.tools {
if let Some(tool_config) = tool_configs.get_mut(&tool.id) {
if let Some(aliases) = &mut tool_config.aliases {
value = aliases.remove(&args.alias);
}
}
}
}
})?;
},
)?;

let Some(value) = value else {
eprintln!(
Expand Down
31 changes: 20 additions & 11 deletions crates/cli/src/commands/unpin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::helpers::{map_pin_type, PinOption};
use crate::session::ProtoSession;
use clap::Args;
use proto_core::{Id, ProtoConfig};
Expand All @@ -12,26 +13,34 @@ pub struct UnpinArgs {

#[arg(
long,
help = "Unpin from the global ~/.proto/.prototools instead of local ./.prototools"
group = "pin",
help = "Unpin from the global ~/.proto/.prototools"
)]
pub global: bool,

#[arg(long, group = "pin", help = "Location of .prototools to unpin from")]
pub from: Option<PinOption>,
}

#[tracing::instrument(skip_all)]
pub async fn unpin(session: ProtoSession, args: UnpinArgs) -> AppResult {
let tool = session.load_tool(&args.id).await?;
let mut value = None;

let config_path = ProtoConfig::update(tool.proto.get_config_dir(args.global), |config| {
if let Some(versions) = &mut config.versions {
value = versions.remove(&tool.id);
}

// Remove these also just in case
if let Some(versions) = &mut config.unknown {
versions.remove(tool.id.as_str());
}
})?;
let config_path = ProtoConfig::update(
tool.proto
.get_config_dir(map_pin_type(args.global, args.from)),
|config| {
if let Some(versions) = &mut config.versions {
value = versions.remove(&tool.id);
}

// Remove these also just in case
if let Some(versions) = &mut config.unknown {
versions.remove(tool.id.as_str());
}
},
)?;

let Some(value) = value else {
eprintln!("No version pinned in config {}", color::path(config_path));
Expand Down
Loading

0 comments on commit 43eafbb

Please sign in to comment.