Skip to main content

vfox/hooks/
parse_legacy_file.rs

1use 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}