Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions src/commands/cleanup.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use anyhow::Result;
use clap::Args;

use crate::handle_commands::handle_cmd;
use crate::{handle_commands::handle_cmd, handlers::config::ConfigHandler};

use super::ComponentCommands;

/// Remove old release archives from the cache directory.
#[derive(Args, Debug)]
pub struct Command {
/// Days to keep files in cache
#[clap(long, short = 'd', default_value = "30")]
days: u32,
#[clap(long, short = 'd')]
days: Option<u32>,

/// Remove all cache files
#[clap(long, conflicts_with = "days")]
Expand All @@ -19,15 +19,34 @@ pub struct Command {
/// Show what would be removed without actually removing anything
#[clap(long, short = 'n')]
dry_run: bool,

/// Use Smart cleanup Startegy (removes oldest files first when size limit exceeded)
#[clap(long)]
smart: bool,
}

impl Command {
pub async fn exec(&self, github_token: &Option<String>) -> Result<()> {
// Resolve days setting: command line > config file > default
let days = if let Some(cmd_days) = self.days {
cmd_days
} else {
match ConfigHandler::new() {
Ok(config_handler) => {
let config = config_handler.get_config();
config.cache_days
}
Err(_) => 30, // Fallback to default if config can't be loaded
}
};


handle_cmd(
ComponentCommands::Cleanup {
all: self.all,
days: self.days,
days,
dry_run: self.dry_run,
smart: self.smart,
},
github_token.to_owned(),
)
Expand Down
114 changes: 114 additions & 0 deletions src/commands/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use clap::{Args, Subcommand};

use crate::handlers::config::{ConfigHandler, ConfigValue};

#[derive(Args, Debug)]
#[command(about = "Manage suiup configuration settings")]
#[command(
long_about = "Configure suiup behavior including mirror URLs, cache settings, default network, install paths, GitHub tokens, and update warnings.
Available configuration keys:
cache_days - Number of days to keep cached files (default: 30)
auto_cleanup - Enable automatic cache cleanup (default: false)
max_cache_size - Maximum cache size in bytes (default: 1073741824)
default_network - Default network for installations (default: testnet)
install_path - Custom installation path for binaries (default: system default)
disable_update_warnings - Disable update notifications (default: false)
github_token - GitHub API token for authenticated requests (default: None)
Examples:
suiup config list # Show all configuration
suiup config set cache_days 7 # Set cache retention
suiup config set auto_cleanup true # Enable auto cleanup
suiup config set disable_update_warnings true # Disable update warnings
suiup config set github_token ghp_xxxxxxxxxxxxxxxxxxxx # Set GitHub token
suiup config unset install_path # Reset to default
suiup config reset # Reset all to defaults"
)]
pub struct Command {
#[command(subcommand)]
command: ConfigCommands,
}

#[derive(Subcommand, Debug)]
pub enum ConfigCommands {
#[command(about = "Get a configuration value")]
#[command(long_about = "Display the current value of a configuration key.

Examples:
suiup config get default_network
suiup config get cache_days")]
Get {
#[arg(help = "Configuration key to get (e.g., install_path, cache_days, auto_cleanup)")]
key: String,
},

#[command(about = "Set a configuration value")]
#[command(long_about = "Set a configuration key to a new value.

Examples:
suiup config set cache_days 7
suiup config set auto_cleanup true
suiup config set default_network mainnet
suiup config set disable_update_warnings true
suiup config set github_token ghp_xxxxxxxxxxxxxxxxxxxx")]
Set {
#[arg(help = "Configuration key to set")]
key: String,
#[arg(help = "Configuration value to set")]
value: String,
},

#[command(about = "Remove a configuration setting (reset to default)")]
#[command(
long_about = "Remove a configuration setting and revert it to its default value.

Examples:
suiup config unset install_path # Use system default path
suiup config unset github_token # Use default ''"
)]
Unset {
#[arg(help = "Configuration key to reset to default")]
key: String,
},

#[command(about = "List all configuration values")]
#[command(long_about = "Display all current configuration settings with their values.")]
List,

#[command(about = "Reset all configuration to defaults")]
#[command(
long_about = "Reset all configuration settings to their default values.
This will remove any custom settings you have configured."
)]
Reset {
#[arg(long, help = "Reset without confirmation prompt")]
yes: bool,
},

#[command(about = "Validate current configuration")]
#[command(
long_about = "Check if all configuration values are valid and properly formatted.
This will verify URLs, file paths, and value ranges."
)]
Validate,
}

impl Command {
pub async fn exec(&self) -> Result<()> {
let mut handler = ConfigHandler::new()?;
match &self.command {
ConfigCommands::Get { key } => handler.get(key).await,
ConfigCommands::Set { key, value } => {
let config_value = ConfigValue::from_string(key, value)?;
handler.set(key, config_value).await
}
ConfigCommands::List => handler.list().await,
ConfigCommands::Unset { key } => handler.unset(key).await,
ConfigCommands::Reset { yes } => handler.reset(*yes).await,
ConfigCommands::Validate => handler.validate().await,
}
}
}
19 changes: 16 additions & 3 deletions src/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
use anyhow::Result;
use clap::Args;

use crate::handle_commands::handle_cmd;

use super::ComponentCommands;
use crate::handle_commands::handle_cmd;
use crate::handlers::config::ConfigHandler;

/// Install a binary.
#[derive(Args, Debug)]
Expand All @@ -29,16 +29,29 @@ pub struct Command {
/// Accept defaults without prompting
#[arg(short, long)]
yes: bool,
/// Custom installation path for the binary
#[arg(long, value_name = "path")]
path: Option<String>,
}

impl Command {
pub async fn exec(&self, github_token: &Option<String>) -> Result<()> {
let component = if self.component.contains('@') || self.component.contains('=') {
self.component.to_owned()
} else {
// If no version specified, use default network from config
let config_handler = ConfigHandler::new()?;
let config = config_handler.get_config();
format!("{}@{}", self.component, config.default_network)
};

handle_cmd(
ComponentCommands::Add {
component: self.component.to_owned(),
component,
nightly: self.nightly.to_owned(),
debug: self.debug.to_owned(),
yes: self.yes.to_owned(),
path: self.path.to_owned(),
},
github_token.to_owned(),
)
Expand Down
63 changes: 54 additions & 9 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

mod cleanup;
mod config;
mod default;
mod doctor;
mod install;
Expand All @@ -13,8 +14,9 @@ mod switch;
mod update;
mod which;

use crate::{handlers::self_::check_for_updates, types::BinaryVersion};

use crate::{
handlers::config::ConfigHandler, handlers::self_::check_for_updates, types::BinaryVersion,
};
use anyhow::{anyhow, bail, Result};
use clap::{Parser, Subcommand, ValueEnum};
use comfy_table::Table;
Expand Down Expand Up @@ -51,27 +53,61 @@ pub enum Commands {
Update(update::Command),
Which(which::Command),
Cleanup(cleanup::Command),
#[command(about = "Manage suiup configuration settings")]
Config(config::Command),
}

impl Command {
pub async fn exec(&self) -> Result<()> {
// Check for updates before executing any command (except self update to avoid recursion)
if !matches!(self.command, Commands::Self_(_)) && !self.disable_update_warnings {
// Priority: command line flag > config file setting
let should_check_updates = if !matches!(self.command, Commands::Self_(_)) {
if self.disable_update_warnings {
false // Command line flag takes precedence
} else {
// Check config file setting
match ConfigHandler::new() {
Ok(config_handler) => {
let config = config_handler.get_config();
!config.disable_update_warnings
}
Err(_) => true, // Default to enabled if config can't be loaded
}
}
} else {
false // Never check for updates when running self commands
};

if should_check_updates {
check_for_updates();
}

// Resolve GitHub token: command line > config file > environment
let github_token = if self.github_token.is_some() {
self.github_token.clone()
} else {
match ConfigHandler::new() {
Ok(config_handler) => {
let config = config_handler.get_config();
config.github_token.clone()
}
Err(_) => None, // Fallback to None if config can't be loaded
}
};

match &self.command {
Commands::Default(cmd) => cmd.exec(),
Commands::Doctor(cmd) => cmd.exec(&self.github_token).await,
Commands::Install(cmd) => cmd.exec(&self.github_token).await,
Commands::Remove(cmd) => cmd.exec(&self.github_token).await,
Commands::List(cmd) => cmd.exec(&self.github_token).await,
Commands::Doctor(cmd) => cmd.exec(&github_token).await,
Commands::Install(cmd) => cmd.exec(&github_token).await,
Commands::Remove(cmd) => cmd.exec(&github_token).await,
Commands::List(cmd) => cmd.exec(&github_token).await,
Commands::Self_(cmd) => cmd.exec().await,
Commands::Show(cmd) => cmd.exec(),
Commands::Switch(cmd) => cmd.exec(),
Commands::Update(cmd) => cmd.exec(&self.github_token).await,
Commands::Update(cmd) => cmd.exec(&github_token).await,
Commands::Which(cmd) => cmd.exec(),
Commands::Cleanup(cmd) => cmd.exec(&self.github_token).await,
Commands::Cleanup(cmd) => cmd.exec(&github_token).await,
Commands::Config(cmd) => cmd.exec().await,
}
}
}
Expand Down Expand Up @@ -105,6 +141,12 @@ pub enum ComponentCommands {
nightly: Option<String>,
#[arg(short, long, help = "Accept defaults without prompting")]
yes: bool,
#[arg(
long,
value_name = "path",
help = "Custom installation path for the binary"
)]
path: Option<String>,
},
#[command(
about = "Remove one. By default, the binary from each release will be removed. Use --version to specify which exact version to remove"
Expand All @@ -125,6 +167,9 @@ pub enum ComponentCommands {
/// Show what would be removed without actually removing anything
#[arg(long, short = 'n')]
dry_run: bool,
/// Use smart cleanup strategy (removes oldest files first when size limit exceeded)
#[arg(long)]
smart: bool,
},
}

Expand Down
11 changes: 10 additions & 1 deletion src/commands/self_/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ pub struct Command;

impl Command {
pub async fn exec(&self) -> Result<()> {
self_::handle_update().await
// Get GitHub token from config if available
let github_token = match crate::handlers::config::ConfigHandler::new() {
Ok(config_handler) => {
let config = config_handler.get_config();
config.github_token.clone()
}
Err(_) => None,
};

self_::handle_update(github_token).await
}
}
22 changes: 20 additions & 2 deletions src/component/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use anyhow::{anyhow, Result};
use std::fs::create_dir_all;

use crate::commands::BinaryName;
use crate::handlers::config::ConfigHandler;
use crate::handlers::install::{install_from_nightly, install_from_release, install_standalone};
use crate::paths::{binaries_dir, get_default_bin_dir};
use crate::types::{Repo, Version};
Expand All @@ -17,11 +18,28 @@ pub async fn install_component(
nightly: Option<String>,
debug: bool,
yes: bool,
path: Option<String>,
github_token: Option<String>,
) -> Result<()> {
// Handle custom installation path - priority: command line arg > config file > default
let install_path = if let Some(custom_path) = path {
std::path::PathBuf::from(custom_path)
} else {
// Check config file for install_path setting
match ConfigHandler::new() {
Ok(config_handler) => {
let config = config_handler.get_config();
if let Some(ref config_path) = config.install_path {
std::path::PathBuf::from(config_path)
} else {
get_default_bin_dir()
}
}
Err(_) => get_default_bin_dir(), // Fallback to default if config can't be loaded
}
};
// Ensure installation directories exist
let default_bin_dir = get_default_bin_dir();
create_dir_all(&default_bin_dir)?;
create_dir_all(&install_path)?;

let installed_bins_dir = binaries_dir();
create_dir_all(&installed_bins_dir)?;
Expand Down
Loading