asimov_cli/registry.rs
1// This is free and unencumbered software released into the public domain.
2
3pub mod crates;
4pub mod http;
5pub mod pypi;
6pub mod rubygems;
7
8use crate::{
9 SysexitsError::{self},
10 registry,
11};
12use asimov_env::{
13 env::Env,
14 envs::{PythonEnv, RubyEnv},
15};
16use derive_more::Display;
17
18#[derive(Clone, Debug)]
19pub struct ModuleMetadata {
20 pub name: String,
21 pub version: String,
22 pub r#type: ModuleType,
23 pub url: String,
24}
25
26impl ModuleMetadata {
27 pub fn is_installed(&self) -> std::io::Result<bool> {
28 match self.r#type {
29 ModuleType::Rust => {
30 let command_name = format!("{}-module", self.name); // FIXME
31 Ok(clientele::SubcommandsProvider::find("asimov-", &command_name).is_some())
32 },
33 ModuleType::Ruby => RubyEnv::default().is_module_installed(&self.name),
34 ModuleType::Python => PythonEnv::default().is_module_installed(&self.name),
35 }
36 }
37}
38
39#[derive(Clone, Display, Debug)]
40pub enum ModuleType {
41 #[display("rust")]
42 Rust,
43 #[display("ruby")]
44 Ruby,
45 #[display("python")]
46 Python,
47}
48
49impl ModuleType {
50 pub fn origin(&self) -> &'static str {
51 use ModuleType::*;
52 match self {
53 Rust => "Cargo",
54 Ruby => "RubyGems",
55 Python => "PyPI",
56 }
57 }
58}
59
60pub fn is_enabled(_module_name: &str) -> bool {
61 true // TODO
62}
63
64pub async fn fetch_module(module_name: &str) -> Option<ModuleMetadata> {
65 let modules = registry::fetch_modules().await.ok()?;
66 modules.into_iter().find(|m| m.name == module_name)
67}
68
69pub async fn fetch_modules() -> Result<Vec<ModuleMetadata>, SysexitsError> {
70 // Disable registry modules temporarily.
71 Ok(Vec::new())
72
73 // // Spawn tasks to fetch module package metadata:
74 // let rust_task = task::spawn(async {
75 // let result = registry::crates::fetch_current_modules()
76 // .await
77 // .map_err(|e| {
78 // tracing::error!("failed to fetch Rust module metadata: {e}");
79 // EX_UNAVAILABLE
80 // })?;
81 // registry::crates::extract_module_names(result).map_err(|e| {
82 // tracing::error!("failed to parse Rust module metadata: {e}");
83 // EX_DATAERR
84 // })
85 // });
86 // let ruby_task = task::spawn(async {
87 // let result = registry::rubygems::fetch_current_modules()
88 // .await
89 // .map_err(|e| {
90 // tracing::error!("failed to fetch Ruby module metadata: {e}");
91 // EX_UNAVAILABLE
92 // })?;
93 // registry::rubygems::extract_module_names(result).map_err(|e| {
94 // tracing::error!("failed to parse Ruby module metadata: {e}");
95 // EX_DATAERR
96 // })
97 // });
98 // let python_task = task::spawn(async {
99 // let result = registry::pypi::fetch_current_modules().await.map_err(|e| {
100 // tracing::error!("failed to fetch Python module metadata: {e}");
101 // EX_UNAVAILABLE
102 // })?;
103 // registry::pypi::extract_module_names(result).map_err(|e| {
104 // tracing::error!("failed to parse Python module metadata: {e}");
105 // EX_DATAERR
106 // })
107 // });
108
109 // // Await all tasks; note the double ?? to handle both `JoinError` and the
110 // // `Result` from the task:
111 // let rust_modules = rust_task.await.map_err(|e| {
112 // tracing::error!("failed to join Rust module task: {e}");
113 // EX_SOFTWARE
114 // })??;
115 // let ruby_modules = ruby_task.await.map_err(|e| {
116 // tracing::error!("failed to join Ruby module task: {e}");
117 // EX_SOFTWARE
118 // })??;
119 // let python_modules = python_task.await.map_err(|e| {
120 // tracing::error!("failed to join Python module task: {e}");
121 // EX_SOFTWARE
122 // })??;
123
124 // let mut all_modules: Vec<ModuleMetadata> = rust_modules
125 // .iter()
126 // .chain(ruby_modules.iter())
127 // .chain(python_modules.iter())
128 // .cloned()
129 // .collect();
130
131 // all_modules.sort_by_key(|m| m.name.clone());
132
133 // Ok(all_modules)
134}