Skip to content

Commit

Permalink
refactor: split asdf into forge+plugin (#2225)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx authored May 31, 2024
1 parent 8e774ba commit f1683a6
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 34 deletions.
39 changes: 24 additions & 15 deletions src/cli/plugins/ls.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use std::collections::BTreeSet;
use std::sync::Arc;

use eyre::Result;
use rayon::prelude::*;
use tabled::{Table, Tabled};

use crate::config::Config;
use crate::forge::asdf::Asdf;
use crate::plugins;
use crate::plugins::asdf_plugin::AsdfPlugin;
use crate::plugins::PluginType;
use crate::ui::table;

Expand Down Expand Up @@ -47,34 +44,46 @@ pub struct PluginsLs {

impl PluginsLs {
pub fn run(self, config: &Config) -> Result<()> {
let mut tools = plugins::list().into_iter().collect::<BTreeSet<_>>();
let mut tools = plugins::list2()?;

if self.all {
for (plugin, url) in config.get_shorthands() {
let mut ep = Asdf::new(plugin.clone());
let mut ep = AsdfPlugin::new(plugin.to_string());
ep.repo_url = Some(url.to_string());
tools.insert(Arc::new(ep));
tools.insert(ep.name.clone(), Box::new(ep));
}
} else if self.user && self.core {
} else if self.core {
tools.retain(|p| matches!(p.get_plugin_type(), PluginType::Core));
tools.retain(|_, p| matches!(p.get_plugin_type(), PluginType::Core));
} else {
tools.retain(|p| matches!(p.get_plugin_type(), PluginType::Asdf));
tools.retain(|_, p| matches!(p.get_plugin_type(), PluginType::Asdf));
}

if self.urls || self.refs {
let data = tools
.into_par_iter()
.map(|p| {
.map(|(name, p)| {
let remote_url = p.get_remote_url().unwrap_or_else(|e| {
warn!("{name}: {e:?}");
None
});
let abbrev_ref = p.current_abbrev_ref().unwrap_or_else(|e| {
warn!("{name}: {e:?}");
None
});
let sha_short = p.current_sha_short().unwrap_or_else(|e| {
warn!("{name}: {e:?}");
None
});
let mut row = Row {
plugin: p.id().to_string(),
url: p.get_remote_url().unwrap_or_default(),
plugin: name,
url: remote_url.unwrap_or_default(),
ref_: String::new(),
sha: String::new(),
};
if p.is_installed() {
row.ref_ = p.current_abbrev_ref().unwrap_or_default();
row.sha = p.current_sha_short().unwrap_or_default();
row.ref_ = abbrev_ref.unwrap_or_default();
row.sha = sha_short.unwrap_or_default();
}
row
})
Expand All @@ -83,7 +92,7 @@ impl PluginsLs {
table::default_style(&mut table, false);
miseprintln!("{table}");
} else {
for tool in tools {
for tool in tools.values() {
miseprintln!("{tool}");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashSet};
use std::io::Write;
use std::iter::once;
#[cfg(unix)]
use std::os::unix::prelude::ExitStatusExt;
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{exit, Stdio};
use std::sync::atomic::{AtomicUsize, Ordering};
Expand Down
10 changes: 0 additions & 10 deletions src/forge/asdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,16 +501,6 @@ impl Forge for Asdf {
git.get_remote_url().or_else(|| self.repo_url.clone())
}

fn current_sha_short(&self) -> Result<String> {
let git = Git::new(self.plugin_path.to_path_buf());
git.current_sha_short()
}

fn current_abbrev_ref(&self) -> Result<String> {
let git = Git::new(self.plugin_path.to_path_buf());
git.current_abbrev_ref()
}

fn is_installed(&self) -> bool {
self.plugin_path.exists()
}
Expand Down
6 changes: 0 additions & 6 deletions src/forge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,6 @@ pub trait Forge: Debug + Send + Sync {
fn get_remote_url(&self) -> Option<String> {
None
}
fn current_sha_short(&self) -> eyre::Result<String> {
Ok(String::from(""))
}
fn current_abbrev_ref(&self) -> eyre::Result<String> {
Ok(String::from(""))
}
fn is_installed(&self) -> bool {
true
}
Expand Down
7 changes: 7 additions & 0 deletions src/git.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::fmt::Debug;
use std::path::PathBuf;

use duct::Expression;
Expand Down Expand Up @@ -217,6 +218,12 @@ fn get_git_version() -> Result<String> {
Ok(version.trim().into())
}

impl Debug for Git {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Git").field("dir", &self.dir).finish()
}
}

// #[cfg(test)]
// mod tests {
// use tempfile::tempdir;
Expand Down
69 changes: 69 additions & 0 deletions src/plugins/asdf_plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use crate::config::Settings;
use crate::dirs;
use crate::git::Git;
use crate::plugins::{Plugin, PluginList, PluginType};
use rayon::prelude::*;
use xx::file;

#[derive(Debug)]
pub struct AsdfPlugin {
pub name: String,
pub repo: Git,
pub repo_url: Option<String>,
}

impl AsdfPlugin {
pub fn new(name: String) -> Self {
let dir = dirs::PLUGINS.join(&name);
Self {
name,
repo: Git::new(dir),
repo_url: None,
}
}

pub fn list() -> eyre::Result<PluginList> {
let settings = Settings::get();
Ok(file::ls(*dirs::PLUGINS)?
.into_par_iter()
.map(|dir| {
let name = dir.file_name().unwrap().to_string_lossy().to_string();
Box::new(AsdfPlugin::new(name)) as Box<dyn Plugin>
})
.filter(|p| !settings.disable_tools.contains(p.name()))
.collect())
}
}

impl Plugin for AsdfPlugin {
fn name(&self) -> &str {
&self.name
}

fn get_plugin_type(&self) -> PluginType {
PluginType::Asdf
}

fn get_remote_url(&self) -> eyre::Result<Option<String>> {
let url = self.repo.get_remote_url();
Ok(url.or(self.repo_url.clone()))
}

fn current_abbrev_ref(&self) -> eyre::Result<Option<String>> {
if !self.is_installed() {
return Ok(None);
}
self.repo.current_abbrev_ref().map(Some)
}

fn current_sha_short(&self) -> eyre::Result<Option<String>> {
if !self.is_installed() {
return Ok(None);
}
self.repo.current_sha_short().map(Some)
}

fn is_installed(&self) -> bool {
self.repo.exists()
}
}
36 changes: 36 additions & 0 deletions src/plugins/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::plugins::core::java::JavaPlugin;
use crate::plugins::core::node::NodePlugin;
use crate::plugins::core::ruby::RubyPlugin;
use crate::plugins::core::zig::ZigPlugin;
use crate::plugins::{Plugin, PluginList, PluginType};
use crate::timeout::run_with_timeout;
use crate::toolset::ToolVersion;

Expand Down Expand Up @@ -59,6 +60,15 @@ pub struct CorePlugin {
}

impl CorePlugin {
pub fn list() -> PluginList {
let settings = Settings::get();
CORE_PLUGINS
.iter()
.map(|f| Box::new(CorePlugin::new(f.name().to_string().into())) as Box<dyn Plugin>)
.filter(|p| !settings.disable_tools.contains(p.name()))
.collect()
}

pub fn new(fa: ForgeArg) -> Self {
Self {
remote_version_cache: CacheManager::new(
Expand Down Expand Up @@ -96,3 +106,29 @@ impl CorePlugin {
Ok(Some(versions))
}
}

impl Plugin for CorePlugin {
fn name(&self) -> &str {
&self.fa.name
}

fn get_plugin_type(&self) -> PluginType {
PluginType::Core
}

fn get_remote_url(&self) -> Result<Option<String>> {
Ok(None)
}

fn current_abbrev_ref(&self) -> Result<Option<String>> {
Ok(None)
}

fn current_sha_short(&self) -> Result<Option<String>> {
Ok(None)
}

fn is_installed(&self) -> bool {
true
}
}
57 changes: 55 additions & 2 deletions src/plugins/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::Debug;
use std::collections::BTreeMap;
use std::fmt::{Debug, Display};

use once_cell::sync::Lazy;
use regex::Regex;
Expand All @@ -8,7 +9,10 @@ pub use script_manager::{Script, ScriptManager};
use crate::cli::args::ForgeArg;
use crate::forge;
use crate::forge::{AForge, ForgeList, ForgeType};
use crate::plugins::asdf_plugin::AsdfPlugin;
use crate::plugins::core::CorePlugin;

pub mod asdf_plugin;
pub mod core;
pub mod mise_plugin_toml;
pub mod script_manager;
Expand Down Expand Up @@ -37,19 +41,68 @@ pub fn list() -> ForgeList {
.collect()
}

pub fn list2() -> eyre::Result<PluginMap> {
let core = CorePlugin::list()
.into_iter()
.map(|p| (p.name().to_string(), p));
let asdf = AsdfPlugin::list()?
.into_iter()
.map(|p| (p.name().to_string(), p));
Ok(core.chain(asdf).collect())
}

pub fn list_external() -> ForgeList {
list()
.into_iter()
.filter(|tool| tool.get_plugin_type() == PluginType::Asdf)
.collect()
}

pub type APlugin = Box<dyn Plugin>;
pub type PluginMap = BTreeMap<String, APlugin>;
pub type PluginList = Vec<APlugin>;

pub trait Plugin: Debug + Send {
fn name(&self) -> &str;
fn get_plugin_type(&self) -> PluginType;
fn get_remote_url(&self) -> eyre::Result<Option<String>>;
fn current_abbrev_ref(&self) -> eyre::Result<Option<String>>;
fn current_sha_short(&self) -> eyre::Result<Option<String>>;
fn is_installed(&self) -> bool;
}

impl Ord for APlugin {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name().cmp(other.name())
}
}

impl PartialOrd for APlugin {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl PartialEq for APlugin {
fn eq(&self, other: &Self) -> bool {
self.name() == other.name()
}
}

impl Eq for APlugin {}

impl Display for APlugin {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name())
}
}

#[cfg(test)]
mod tests {
use crate::forge::asdf::Asdf;
use pretty_assertions::assert_str_eq;
use test_log::test;

use crate::forge::asdf::Asdf;
use crate::forge::Forge;
use crate::test::reset;

Expand Down

0 comments on commit f1683a6

Please sign in to comment.