Skip to content

Commit

Permalink
Add huak-toolchain (789)
Browse files Browse the repository at this point in the history
  • Loading branch information
cnpryer committed Nov 6, 2023
1 parent a5f01c1 commit f5c20f8
Show file tree
Hide file tree
Showing 38 changed files with 2,031 additions and 99 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ license = "MIT"
clap = { version = "4.4.2", features = ["cargo", "derive"] }
colored = "2.0.4"
glob = "0.3.1"
hex = "0.4.3"
human-panic = "1.1.5"
lazy_static = "1.4.0"
pep440_rs = "0.3.11"
pep508_rs = "0.2.1"
regex = "1.10.2"
sha2 = "0.10.8"
tempfile = "3.7.1"
termcolor = "1.2.0"
thiserror = "1.0.48"
Expand Down
1 change: 1 addition & 0 deletions crates/huak-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ colored.workspace = true
huak-home = { path = "../huak-home" }
huak-package-manager = { path = "../huak-package-manager"}
huak-python-manager = { path = "../huak-python-manager" }
huak-toolchain = { path = "../huak-toolchain" }
human-panic.workspace = true
# included to build PyPi Wheels (see .github/workflow/README.md)
openssl = { version = "0.10.57", features = ["vendored"], optional = true }
Expand Down
98 changes: 86 additions & 12 deletions crates/huak-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use huak_package_manager::{
Verbosity, WorkspaceOptions,
};
use huak_python_manager::RequestedVersion;
use huak_toolchain::{Channel, LocalTool};
use std::{env::current_dir, path::PathBuf, process::ExitCode, str::FromStr};
use termcolor::ColorChoice;

Expand Down Expand Up @@ -156,6 +157,12 @@ enum Commands {
#[arg(last = true)]
trailing: Option<Vec<String>>,
},
/// Manage toolchains.
#[clap(alias = "tc")]
Toolchain {
#[command(subcommand)]
command: Toolchain,
},
/// Update the project's dependencies.
Update {
#[arg(num_args = 0..)]
Expand Down Expand Up @@ -188,21 +195,69 @@ enum Python {

#[derive(Subcommand)]
enum Toolchain {
/// List available toolchains.
List,
/// Use an available toolchain.
Use {
/// The version of Python to use.
#[arg(required = true)]
version: RequestedVersion,
/// Add a tool to a toolchain.
Add {
/// A tool to add.
tool: LocalTool,
/// Add a tool to a specific channel.
#[arg(long, required = false)]
channel: Option<Channel>,
},
/// Display information about a toolchain.
Info {
/// The toolchain channel to display information for.
#[arg(long, required = false)]
channel: Option<Channel>,
},
/// Install a toolchain.
Install {
/// The version of Python to install.
#[arg(required = true)]
version: RequestedVersion,
/// The toolchain channel to install.
#[arg(required = false)]
channel: Option<Channel>,
/// The path to install a toolchain to.
target: PathBuf,
#[arg(required = false)]
target: Option<PathBuf>, // TODO(cnpryer): Could default to home dir toolchains dir.
},
/// List available toolchains.
List,
/// Remove a tool from a toolchain.
Remove {
/// A tool to add.
tool: LocalTool,
/// Remove a tool from a specific channel.
#[arg(long, required = false)]
channel: Option<Channel>,
},
/// Run a tool installed to a toolchain.
Run {
/// The tool to run.
tool: LocalTool,
/// The toolchain channel to run a tool from.
#[arg(long, required = false)]
channel: Option<Channel>,
/// Args to run the tool with.
#[arg(num_args = 1.., required = false)]
trailing: Option<Vec<String>>,
},
/// Uninstall a toolchain.
Uninstall {
/// The toolchain channel to uninstall.
#[arg(required = false)]
channel: Option<Channel>,
},
/// Update the current toolchain.
Update {
/// A tool to update.
#[arg(required = false)]
tool: Option<LocalTool>, // TODO(cnpryer): Either include @version or add version arg.
/// The toolchain channel to update.
#[arg(long, required = false)]
channel: Option<Channel>,
},
/// Use an available toolchain.
Use {
/// The toolchain channel to use.
channel: Channel,
},
}

Expand Down Expand Up @@ -345,6 +400,7 @@ fn exec_command(cmd: Commands, config: &mut Config) -> HuakResult<()> {
};
test(config, &options)
}
Commands::Toolchain { command } => toolchain(command, config),
Commands::Update {
dependencies,
trailing,
Expand Down Expand Up @@ -459,7 +515,7 @@ fn python(command: Python, config: &Config) -> HuakResult<()> {
match command {
Python::List => ops::list_python(config),
Python::Use { version } => ops::use_python(&version, config),
Python::Install { version } => ops::install_python(&version),
Python::Install { version } => ops::install_python(version),
}
}

Expand All @@ -475,6 +531,24 @@ fn test(config: &Config, options: &TestOptions) -> HuakResult<()> {
ops::test_project(config, options)
}

fn toolchain(command: Toolchain, config: &Config) -> HuakResult<()> {
match command {
Toolchain::Add { tool, channel } => ops::add_tool(tool, channel, config),
Toolchain::Info { channel } => ops::toolchain_info(channel, config),
Toolchain::Install { channel, target } => ops::install_toolchain(channel, target, config),
Toolchain::List => ops::list_toolchains(config),
Toolchain::Remove { tool, channel } => ops::remove_tool(tool, channel, config),
Toolchain::Run {
tool,
channel,
trailing,
} => ops::run_tool(tool, channel, trailing, config),
Toolchain::Uninstall { channel } => ops::uninstall_toolchain(channel, config),
Toolchain::Update { tool, channel } => ops::update_toolchain(tool, channel, config),
Toolchain::Use { channel } => ops::use_toolchain(channel, config),
}
}

fn update(
dependencies: Option<Vec<String>>,
config: &Config,
Expand Down
29 changes: 28 additions & 1 deletion crates/huak-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ mod cli;
use clap::Parser;
use cli::Cli;
use colored::Colorize;
use huak_home::huak_home_dir;
use human_panic::setup_panic;
use std::process::{exit, ExitCode};
use std::{
env,
fs::create_dir_all,
process::{exit, ExitCode},
};

mod error;

Expand All @@ -16,6 +21,28 @@ mod error;
pub fn main() -> ExitCode {
setup_panic!();

// Get home directory path.
let Some(home) = huak_home_dir() else {
eprintln!(
"{}{} failed to resolve huak's home directory",
"error".red(),
":".bold()
);
return ExitCode::FAILURE;
};

// If the home directory doesn't exist then spawn one. We only report an error if the
// spawn fails due to anything other than the directory already existing.
if !home.exists() {
if let Err(e) = create_dir_all(home) {
if e.kind() != std::io::ErrorKind::AlreadyExists {
eprintln!("{}{} {}", "error".red(), ":".bold(), e);
return ExitCode::FAILURE;
}
}
}

// Capture and run CLI input.
match Cli::parse().run() {
Ok(0) => ExitCode::SUCCESS,
// Lazy-like exit of a subprocess failure. TODO: https://github.com/cnpryer/huak/issues/631
Expand Down
7 changes: 5 additions & 2 deletions crates/huak-home/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::{env, path::PathBuf};

/// Huak's home directory is located at ~/.huak.
///
Expand All @@ -11,7 +11,10 @@ use std::path::PathBuf;
/// On windows the `USERPROFILE` environment variable is used if it exists.
#[must_use]
pub fn huak_home_dir() -> Option<PathBuf> {
home_dir().map(|p| p.join(".huak"))
env::var("HUAK_HOME")
.ok()
.map(PathBuf::from)
.or(home_dir().map(|p| p.join(".huak")))
}

#[cfg(windows)]
Expand Down
3 changes: 3 additions & 0 deletions crates/huak-package-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ regex.workspace = true
huak-python-manager = { path = "../huak-python-manager" }
huak-home = { path = "../huak-home" }
lazy_static.workspace = true
huak-toolchain = { path = "../huak-toolchain" }
hex.workspace = true
sha2.workspace = true

[dev-dependencies]
huak-dev = { path = "../huak-dev" }
Expand Down
3 changes: 1 addition & 2 deletions crates/huak-package-manager/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::path::PathBuf;

use huak_home::huak_home_dir;
use std::path::PathBuf;

use crate::{sys::Terminal, workspace::Workspace, TerminalOptions};

Expand Down
12 changes: 12 additions & 0 deletions crates/huak-package-manager/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use thiserror::Error as ThisError;

pub type HuakResult<T> = Result<T, Error>;

// TODO(cnpryer): If errors are given "a problem..." prompts there could be redundancy in messages.
// These prompts feel more like application experience than library needs.
#[derive(ThisError, Debug)]
pub enum Error {
#[error("a problem with argument parsing occurred: {0}")]
Expand All @@ -22,8 +24,16 @@ pub enum Error {
HuakConfigurationError(String),
#[error("a problem occurred resolving huak's home directory")]
HuakHomeNotFound,
#[error("a toolchain cannot be found")]
HuakToolchainNotFound,
#[error("{0}")] // See TODO note above.
HuakToolchainError(#[from] huak_toolchain::Error),
#[error("a toolchain already exists: {0}")]
LocalToolchainExists(PathBuf),
#[error("a problem with huak's internals occurred: {0}")]
InternalError(String),
#[error("a checksum is invalid: {0}")]
InvalidChecksum(String),
#[error("a version number could not be parsed: {0}")]
InvalidVersionString(String),
#[error("a problem occurred with json deserialization: {0}")]
Expand Down Expand Up @@ -60,6 +70,8 @@ pub enum Error {
TOMLDeserializationError(#[from] toml::de::Error),
#[error("a problem with toml serialization occurred {0}")]
TOMLSerializationError(#[from] toml::ser::Error),
#[error("{0}")]
TOMLEditError(#[from] toml_edit::TomlError),
#[error("a problem with toml deserialization occurred: {0}")]
TOMLEditDeserializationError(#[from] toml_edit::de::Error),
#[error("a problem with toml serialization occurred {0}")]
Expand Down
4 changes: 2 additions & 2 deletions crates/huak-package-manager/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ pub fn copy_dir<T: Into<PathBuf>>(from: T, to: T, options: &CopyDirOptions) -> R

if from.is_dir() {
for entry in fs::read_dir(from)?.filter_map(Result::ok) {
let entry_path = entry.path();
if options.exclude.contains(&entry_path) {
let entry_as_path = entry.path();
if options.exclude.contains(&entry_as_path) {
continue;
}

Expand Down
1 change: 1 addition & 0 deletions crates/huak-package-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ mod metadata;
pub mod ops;
mod package;
mod python_environment;
mod settings;
mod sys;
mod workspace;

Expand Down
4 changes: 4 additions & 0 deletions crates/huak-package-manager/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ impl Metadata {
.entry(name.to_string())
.or_insert(entrypoint.to_string());
}

pub fn tool(&self) -> Option<&Table> {
self.tool.as_ref()
}
}

impl Default for Metadata {
Expand Down
5 changes: 5 additions & 0 deletions crates/huak-package-manager/src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod python;
mod remove;
mod run;
mod test;
mod toolchain;
mod update;
mod version;

Expand All @@ -33,6 +34,10 @@ pub use remove::{remove_project_dependencies, RemoveOptions};
pub use run::run_command_str;
use std::{path::PathBuf, process::Command};
pub use test::{test_project, TestOptions};
pub use toolchain::{
add_tool, install_toolchain, list_toolchains, remove_tool, run_tool, toolchain_info,
uninstall_toolchain, update_toolchain, use_toolchain,
};
pub use update::{update_project_dependencies, UpdateOptions};
pub use version::display_project_version;

Expand Down
Loading

0 comments on commit f5c20f8

Please sign in to comment.