Skip to content

Commit

Permalink
Ability to compile Go-based tools using an RTA-installed Go toolchain (
Browse files Browse the repository at this point in the history
  • Loading branch information
kevgo authored Oct 22, 2024
1 parent f80f8de commit 2e17987
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/apps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod dprint;
mod exhaustruct;
mod gh;
mod ghokin;
mod go;
pub mod go;
mod goda;
mod gofmt;
mod gofumpt;
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/available.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn available(args: &Args) -> Result<ExitCode> {
let config_file = config::File::load(&apps)?;
let versions = RequestedVersions::determine(&args.app_name, &args.version, &config_file)?;
for version in versions {
if load_or_install(app, &version, platform, &yard, log)?.is_some() {
if load_or_install(app, &version, platform, &yard, &config_file, log)?.is_some() {
return Ok(ExitCode::SUCCESS);
}
}
Expand Down
24 changes: 19 additions & 5 deletions src/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn run(args: &Args) -> Result<ExitCode> {
let config_file = config::File::load(&apps)?;
let versions = RequestedVersions::determine(&args.app_name, &args.version, &config_file)?;
for version in versions {
if let Some(executable) = load_or_install(app, &version, platform, &yard, log)? {
if let Some(executable) = load_or_install(app, &version, platform, &yard, &config_file, log)? {
if args.error_on_output {
return subshell::execute_check_output(&executable, &args.app_args);
}
Expand Down Expand Up @@ -54,10 +54,17 @@ pub struct Args {
pub verbose: bool,
}

pub fn load_or_install(app: &dyn App, version: &RequestedVersion, platform: Platform, yard: &Yard, log: Log) -> Result<Option<Executable>> {
pub fn load_or_install(
app: &dyn App,
version: &RequestedVersion,
platform: Platform,
yard: &Yard,
config_file: &config::File,
log: Log,
) -> Result<Option<Executable>> {
match version {
RequestedVersion::Path(version) => load_from_path(app, version, platform, log),
RequestedVersion::Yard(version) => load_or_install_from_yard(app, version, platform, yard, log),
RequestedVersion::Yard(version) => load_or_install_from_yard(app, version, platform, yard, config_file, log),
}
}

Expand Down Expand Up @@ -97,7 +104,14 @@ fn load_from_path(app: &dyn App, range: &semver::VersionReq, platform: Platform,
}
}

fn load_or_install_from_yard(app: &dyn App, version: &Version, platform: Platform, yard: &Yard, log: Log) -> Result<Option<Executable>> {
fn load_or_install_from_yard(
app: &dyn App,
version: &Version,
platform: Platform,
yard: &Yard,
config_file: &config::File,
log: Log,
) -> Result<Option<Executable>> {
// try to load the app
if let Some(executable) = install::load(app.install_methods(), version, platform, yard, log) {
return Ok(Some(executable));
Expand All @@ -107,7 +121,7 @@ fn load_or_install_from_yard(app: &dyn App, version: &Version, platform: Platfor
return Ok(None);
}
// app not installed and installable --> try to install
if install::any(app.install_methods(), version, platform, yard, log)?.success() {
if install::any(app.install_methods(), version, platform, yard, config_file, log)?.success() {
return Ok(install::load(app.install_methods(), version, platform, yard, log));
}

Expand Down
5 changes: 3 additions & 2 deletions src/cmd/test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::apps::AnalyzeResult;
use crate::config::AppName;
use crate::config::{self, AppName};
use crate::logger::Event;
use crate::prelude::*;
use crate::subshell::Executable;
Expand All @@ -14,6 +14,7 @@ pub fn test(args: &mut Args) -> Result<ExitCode> {
let platform = platform::detect(log)?;
let temp_folder = tempfile::tempdir().map_err(|err| UserError::CannotCreateTempDir { err: err.to_string() })?;
let yard = yard::load_or_create(temp_folder.path())?;
let config_file = config::File::load(&apps)?;
for app in apps {
if let Some(start_app_name) = &args.start_at_app {
if app.name() != start_app_name {
Expand All @@ -29,7 +30,7 @@ pub fn test(args: &mut Args) -> Result<ExitCode> {
version: &latest_version,
method: &install_method,
});
if !install::install(&install_method, &latest_version, platform, &yard, log)?.success() {
if !install::install(&install_method, &latest_version, platform, &yard, &config_file, log)?.success() {
continue;
}
let executable_location = install_method.executable_location(&latest_version, platform);
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/which.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn which(args: &Args) -> Result<ExitCode> {
let config_file = config::File::load(&apps)?;
let versions = RequestedVersions::determine(&args.app_name, &args.version, &config_file)?;
for version in versions {
if let Some(executable) = load_or_install(app, &version, platform, &yard, log)? {
if let Some(executable) = load_or_install(app, &version, platform, &yard, &config_file, log)? {
println!("{}", executable.0.to_string_lossy());
return Ok(ExitCode::SUCCESS);
}
Expand Down
2 changes: 1 addition & 1 deletion src/config/requested_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::prelude::*;

/// a collection of Version instances
#[derive(Debug, PartialEq)]
pub struct RequestedVersions(Vec<RequestedVersion>);
pub struct RequestedVersions(pub Vec<RequestedVersion>);

impl RequestedVersions {
/// Provides the version to use: if the user provided a version to use via CLI, use it.
Expand Down
36 changes: 30 additions & 6 deletions src/install/compile_go.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use super::Outcome;
use crate::apps::App;
use crate::config::Version;
use crate::apps::{self, App};
use crate::config::{RequestedVersion, RequestedVersions, Version};
use crate::logger::{Event, Log};
use crate::platform::Platform;
use crate::prelude::*;
use crate::yard::Yard;
use crate::{cmd, config};
use std::io::ErrorKind;
use std::path::PathBuf;
use std::process::Command;
use which::which;

Expand All @@ -16,13 +19,18 @@ pub trait CompileGoSource: App {
}

/// installs the given Go-based application by compiling it from source
pub fn run(app: &dyn CompileGoSource, version: &Version, yard: &Yard, log: Log) -> Result<Outcome> {
let Ok(go_path) = which("go") else {
return Ok(Outcome::NotInstalled);
};
pub fn run(app: &dyn CompileGoSource, platform: Platform, version: &Version, config_file: &config::File, yard: &Yard, log: Log) -> Result<Outcome> {
let target_folder = yard.create_app_folder(&app.name(), version)?;
let import_path = app.import_path(version);
let go_args = vec!["install", &import_path];
let go_path = if let Ok(system_go_path) = which("go") {
system_go_path
} else {
let Some(rta_path) = load_rta_go(platform, config_file, yard, log)? else {
return Ok(Outcome::NotInstalled);
};
rta_path
};
log(Event::CompileGoBegin {
go_path: go_path.to_string_lossy(),
args: &go_args,
Expand All @@ -45,3 +53,19 @@ pub fn run(app: &dyn CompileGoSource, version: &Version, yard: &Yard, log: Log)
log(Event::CompileGoSuccess);
Ok(Outcome::Installed)
}

fn load_rta_go(platform: Platform, config_file: &config::File, yard: &Yard, log: Log) -> Result<Option<PathBuf>> {
let go = apps::go::Go {};
let requested_go_versions = if let Some(versions) = config_file.lookup(&go.name()) {
versions
} else {
let versions = go.installable_versions(3, log)?;
&RequestedVersions::new(versions.into_iter().map(RequestedVersion::from).collect())
};
for requested_go_version in &requested_go_versions.0 {
if let Some(executable) = cmd::run::load_or_install(&go, requested_go_version, platform, yard, config_file, log)? {
return Ok(Some(executable.0));
}
}
Ok(None)
}
12 changes: 6 additions & 6 deletions src/install/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub mod download_archive;
pub mod download_executable;
pub mod other_app_folder;

use crate::config::{AppName, Version};
use crate::config::{self, AppName, Version};
use crate::logger::{Event, Log};
use crate::platform::Platform;
use crate::prelude::*;
Expand Down Expand Up @@ -71,22 +71,22 @@ impl<'a> Method<'a> {
}

/// installs an app using the first of its installation methods that works
pub fn any(install_methods: Vec<Method>, version: &Version, platform: Platform, yard: &Yard, log: Log) -> Result<Outcome> {
pub fn any(install_methods: Vec<Method>, version: &Version, platform: Platform, yard: &Yard, config_file: &config::File, log: Log) -> Result<Outcome> {
for install_method in install_methods {
if install(&install_method, version, platform, yard, log)?.success() {
if install(&install_method, version, platform, yard, config_file, log)?.success() {
return Ok(Outcome::Installed);
}
}
Ok(Outcome::NotInstalled)
}

pub fn install(install_method: &Method, version: &Version, platform: Platform, yard: &Yard, log: Log) -> Result<Outcome> {
pub fn install(install_method: &Method, version: &Version, platform: Platform, yard: &Yard, config_file: &config::File, log: Log) -> Result<Outcome> {
match install_method {
Method::DownloadArchive(app) => download_archive::run(*app, version, platform, yard, log),
Method::DownloadExecutable(app) => download_executable::install(*app, version, platform, yard, log),
Method::CompileGoSource(app) => compile_go::run(*app, version, yard, log),
Method::CompileGoSource(app) => compile_go::run(*app, platform, version, config_file, yard, log),
Method::CompileRustSource(app) => compile_rust::run(*app, version, yard, log),
Method::InstallAnotherApp(app) => other_app_folder::install_other_app(*app, version, platform, yard, log),
Method::InstallAnotherApp(app) => other_app_folder::install_other_app(*app, version, platform, yard, config_file, log),
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/install/other_app_folder.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use super::Outcome;
use crate::apps;
use crate::apps::App;
use crate::cmd::run::load_or_install;
use crate::config::{RequestedVersion, Version};
use crate::logger::Log;
use crate::platform::Platform;
use crate::prelude::*;
use crate::yard::Yard;
use crate::{apps, config};

/// defines the information needed for apps whose executable is shipped as part of another app
pub trait ViaAnotherApp: App {
Expand All @@ -17,13 +17,13 @@ pub trait ViaAnotherApp: App {
fn executable_path_in_other_app_yard(&self, version: &Version, platform: Platform) -> String;
}

pub fn install_other_app(app: &dyn ViaAnotherApp, version: &Version, platform: Platform, yard: &Yard, log: Log) -> Result<Outcome> {
pub fn install_other_app(app: &dyn ViaAnotherApp, version: &Version, platform: Platform, yard: &Yard, config_file: &config::File, log: Log) -> Result<Outcome> {
let app_to_install = app.app_to_install();
let all_apps = apps::all();
let app = all_apps.lookup(&app_to_install.name())?;
// Note: we know it must be the Yard variant here.
// At this point we are installing the app.
// Only Yard variants get installed. The Path variant doesn't get installed.
load_or_install(app, &RequestedVersion::Yard(version.to_owned()), platform, yard, log)?;
load_or_install(app, &RequestedVersion::Yard(version.to_owned()), platform, yard, config_file, log)?;
Ok(Outcome::Installed)
}

0 comments on commit 2e17987

Please sign in to comment.