vfox/hooks/
parse_legacy_file.rs1use mlua::prelude::LuaError;
2use mlua::{FromLua, IntoLua, Lua, MultiValue, Value};
3use std::path::{Path, PathBuf};
4
5use crate::Plugin;
6use crate::error::Result;
7
8#[derive(Debug)]
9pub struct LegacyFileContext {
10 pub args: Vec<String>,
11 pub filepath: PathBuf,
12}
13
14#[derive(Debug)]
15pub struct ParseLegacyFileResponse {
16 pub version: Option<String>,
17}
18
19impl Plugin {
20 pub async fn parse_legacy_file(&self, legacy_file: &Path) -> Result<ParseLegacyFileResponse> {
21 debug!("[vfox:{}] parse_legacy_file", &self.name);
22 let ctx = LegacyFileContext {
23 args: vec![],
24 filepath: legacy_file.to_path_buf(),
25 };
26 let legacy_file_response = self
27 .eval_async(chunk! {
28 require "hooks/available"
29 require "hooks/parse_legacy_file"
30 return PLUGIN:ParseLegacyFile($ctx)
31 })
32 .await?;
33
34 Ok(legacy_file_response)
35 }
36}
37
38impl IntoLua for LegacyFileContext {
39 fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
40 let table = lua.create_table()?;
41 table.set("args", self.args)?;
42 table.set(
43 "filename",
44 self.filepath
45 .file_name()
46 .ok_or(LuaError::RuntimeError(String::from(
47 "No basename for legacy file",
48 )))?
49 .to_os_string()
50 .into_string()
51 .or(Err(LuaError::RuntimeError(String::from(
52 "Could not convert basename to string",
53 ))))?,
54 )?;
55 table.set("filepath", self.filepath.to_string_lossy().to_string())?;
56 table.set(
57 "getInstalledVersions",
58 lua.create_async_function(|lua, _input: MultiValue| async move {
59 let plugin_dir = lua.named_registry_value::<PathBuf>("plugin_dir")?;
60 Ok(Plugin::from_dir(plugin_dir.as_path())
61 .map_err(|e| LuaError::RuntimeError(e.to_string()))?
62 .available_async()
63 .await
64 .map_err(|e| LuaError::RuntimeError(e.to_string()))?
65 .into_iter()
66 .map(|v| v.version)
67 .collect::<Vec<String>>())
68 })?,
69 )?;
70 Ok(Value::Table(table))
71 }
72}
73
74impl FromLua for ParseLegacyFileResponse {
75 fn from_lua(value: Value, _: &Lua) -> std::result::Result<Self, LuaError> {
76 match value {
77 Value::Table(table) => Ok(ParseLegacyFileResponse {
78 version: table.get::<Option<String>>("version")?,
79 }),
80 _ => panic!("Expected table"),
81 }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::Vfox;
89
90 #[tokio::test]
91 async fn test_parse_legacy_file_test_nodejs() {
92 let vfox = Vfox::test();
93 let response = vfox
94 .parse_legacy_file("test-nodejs", Path::new("test/data/.node-version"))
95 .await
96 .unwrap();
97 let out = format!("{response:?}");
98 assert_snapshot!(out, @r###"ParseLegacyFileResponse { version: Some("20.0.0") }"###);
99 }
100
101 #[tokio::test]
102 async fn test_parse_legacy_file_dummy() {
103 let vfox = Vfox::test();
104 let response = vfox
105 .parse_legacy_file("dummy", Path::new("test/data/.dummy-version"))
106 .await
107 .unwrap();
108 let out = format!("{response:?}");
109 assert_snapshot!(out, @r###"ParseLegacyFileResponse { version: Some("1.0.0") }"###);
110 }
111}