asimov_module_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 let module = modules.into_iter().find(|m| m.name == module_name);
67 module
68}
69
70pub async fn fetch_modules() -> Result<Vec<ModuleMetadata>, SysexitsError> {
71 // Disable registry modules temporarily.
72 return Ok(Vec::new());
73
74 // // Spawn tasks to fetch module package metadata:
75 // let rust_task = task::spawn(async {
76 // let result = registry::crates::fetch_current_modules()
77 // .await
78 // .map_err(|e| {
79 // tracing::error!("failed to fetch Rust module metadata: {e}");
80 // EX_UNAVAILABLE
81 // })?;
82 // registry::crates::extract_module_names(result).map_err(|e| {
83 // tracing::error!("failed to parse Rust module metadata: {e}");
84 // EX_DATAERR
85 // })
86 // });
87 // let ruby_task = task::spawn(async {
88 // let result = registry::rubygems::fetch_current_modules()
89 // .await
90 // .map_err(|e| {
91 // tracing::error!("failed to fetch Ruby module metadata: {e}");
92 // EX_UNAVAILABLE
93 // })?;
94 // registry::rubygems::extract_module_names(result).map_err(|e| {
95 // tracing::error!("failed to parse Ruby module metadata: {e}");
96 // EX_DATAERR
97 // })
98 // });
99 // let python_task = task::spawn(async {
100 // let result = registry::pypi::fetch_current_modules().await.map_err(|e| {
101 // tracing::error!("failed to fetch Python module metadata: {e}");
102 // EX_UNAVAILABLE
103 // })?;
104 // registry::pypi::extract_module_names(result).map_err(|e| {
105 // tracing::error!("failed to parse Python module metadata: {e}");
106 // EX_DATAERR
107 // })
108 // });
109
110 // // Await all tasks; note the double ?? to handle both `JoinError` and the
111 // // `Result` from the task:
112 // let rust_modules = rust_task.await.map_err(|e| {
113 // tracing::error!("failed to join Rust module task: {e}");
114 // EX_SOFTWARE
115 // })??;
116 // let ruby_modules = ruby_task.await.map_err(|e| {
117 // tracing::error!("failed to join Ruby module task: {e}");
118 // EX_SOFTWARE
119 // })??;
120 // let python_modules = python_task.await.map_err(|e| {
121 // tracing::error!("failed to join Python module task: {e}");
122 // EX_SOFTWARE
123 // })??;
124
125 // let mut all_modules: Vec<ModuleMetadata> = rust_modules
126 // .iter()
127 // .chain(ruby_modules.iter())
128 // .chain(python_modules.iter())
129 // .cloned()
130 // .collect();
131
132 // all_modules.sort_by_key(|m| m.name.clone());
133
134 // Ok(all_modules)
135}