Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions crates/vfox/plugins/dummy/hooks/pre_uninstall.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function PLUGIN:PreUninstall(ctx)
local main = ctx.main
local marker = main.path .. "/pre_uninstall_marker"
local marker_file = io.open(marker, "w")
if marker_file then
marker_file:write(main.name .. ":" .. main.version .. ":" .. string.gsub(main.path, "\\", "/"))
marker_file:close()
end
end
1 change: 1 addition & 0 deletions crates/vfox/src/hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ pub mod mise_path;
pub mod parse_legacy_file;
pub mod post_install;
pub mod pre_install;
pub mod pre_uninstall;
pub mod pre_use;
30 changes: 30 additions & 0 deletions crates/vfox/src/hooks/pre_uninstall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::Plugin;
use crate::error::Result;
use crate::sdk_info::SdkInfo;
use mlua::{IntoLua, Lua, Value};
use std::collections::BTreeMap;

impl Plugin {
pub async fn pre_uninstall(&self, ctx: PreUninstallContext) -> Result<()> {
debug!("[vfox:{}] pre_uninstall", &self.name);
self.exec_async(chunk! {
require "hooks/pre_uninstall"
PLUGIN:PreUninstall($ctx)
})
.await
}
}

pub struct PreUninstallContext {
pub main: SdkInfo,
pub sdk_info: BTreeMap<String, SdkInfo>,
}

impl IntoLua for PreUninstallContext {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
let table = lua.create_table()?;
table.set("main", self.main)?;
table.set("sdkInfo", self.sdk_info)?;
Ok(Value::Table(table))
}
}
2 changes: 1 addition & 1 deletion crates/vfox/src/snapshots/vfox__vfox__tests__metadata.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
source: crates/vfox/src/vfox.rs
expression: out
---
Metadata { name: "dummy", legacy_filenames: [".dummy-version"], depends: [], version: "0.3.0", description: Some("Dummy plugin for testing."), author: None, license: Some("Apache 2.0"), homepage: Some("https://github.com/version-fox/vfox-nodejs"), hooks: {"available", "env_keys", "parse_legacy_file", "post_install", "pre_install"} }
Metadata { name: "dummy", legacy_filenames: [".dummy-version"], depends: [], version: "0.3.0", description: Some("Dummy plugin for testing."), author: None, license: Some("Apache 2.0"), homepage: Some("https://github.com/version-fox/vfox-nodejs"), hooks: {"available", "env_keys", "parse_legacy_file", "post_install", "pre_install", "pre_uninstall"} }
41 changes: 41 additions & 0 deletions crates/vfox/src/vfox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::hooks::mise_path::MisePathContext;
use crate::hooks::parse_legacy_file::ParseLegacyFileResponse;
use crate::hooks::post_install::PostInstallContext;
use crate::hooks::pre_install::{PreInstall, PreInstallAttestation, VerifiedAttestation};
use crate::hooks::pre_uninstall::PreUninstallContext;
use crate::http::{CLIENT, retry_async};
use crate::metadata::Metadata;
use crate::plugin::Plugin;
Expand Down Expand Up @@ -234,6 +235,24 @@ impl Vfox {
})
}

pub async fn pre_uninstall<ID: AsRef<Path>>(
&self,
sdk: &str,
version: &str,
install_dir: ID,
) -> Result<()> {
let sdk = self.get_sdk_with_env(sdk)?;
if sdk.get_metadata()?.hooks.contains("pre_uninstall") {
let sdk_info = sdk.sdk_info(version.to_string(), install_dir.as_ref().to_path_buf())?;
sdk.pre_uninstall(PreUninstallContext {
main: sdk_info.clone(),
sdk_info: BTreeMap::from([(sdk_info.name.clone(), sdk_info)]),
})
.await?;
}
Ok(())
}

pub fn uninstall(&self, sdk: &str, version: &str) -> Result<()> {
let path = self.install_dir.join(sdk).join(version);
file::remove_dir_all(&path)?;
Expand Down Expand Up @@ -682,6 +701,28 @@ mod tests {
file::remove_dir_all(vfox.download_dir).unwrap();
}

#[tokio::test]
async fn test_pre_uninstall() {
let temp_dir = tempfile::tempdir().unwrap();
let mut vfox = Vfox::test();
vfox.install_dir = temp_dir.path().join("installs");
let install_dir = vfox.install_dir.join("dummy").join("1.0.0");
std::fs::create_dir_all(&install_dir).unwrap();

vfox.pre_uninstall("dummy", "1.0.0", &install_dir)
.await
.unwrap();

let marker = std::fs::read_to_string(install_dir.join("pre_uninstall_marker")).unwrap();
assert_eq!(
marker,
format!(
"dummy:1.0.0:{}",
install_dir.to_string_lossy().replace('\\', "/")
)
);
}

#[tokio::test]
#[ignore] // disable for now
async fn test_install_cmake() {
Expand Down
76 changes: 76 additions & 0 deletions e2e/backend/test_vfox_pre_uninstall
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash

PLUGIN_DIR="$PWD/vfox-pre-uninstall"
MARKER="$MISE_DATA_DIR/pre-uninstall-marker"

mkdir -p "$PLUGIN_DIR/hooks"

cat >"$PLUGIN_DIR/metadata.lua" <<'LUA'
PLUGIN = {}
PLUGIN.name = "pre-uninstall"
PLUGIN.version = "0.1.0"
PLUGIN.homepage = "https://example.com/pre-uninstall"
PLUGIN.license = "MIT"
PLUGIN.description = "pre uninstall test plugin"
LUA

cat >"$PLUGIN_DIR/hooks/available.lua" <<'LUA'
function PLUGIN:Available(ctx)
return {
{ version = "1.0.0" },
}
end
LUA

cat >"$PLUGIN_DIR/hooks/pre_install.lua" <<'LUA'
function PLUGIN:PreInstall(ctx)
return {
version = ctx.version,
}
end
LUA

cat >"$PLUGIN_DIR/hooks/post_install.lua" <<'LUA'
function PLUGIN:PostInstall(ctx)
os.execute("mkdir -p " .. ctx.rootPath .. "/bin")
local bin = io.open(ctx.rootPath .. "/bin/pre-uninstall", "w")
if bin then
bin:write("#!/bin/sh\necho pre-uninstall\n")
bin:close()
os.execute("chmod +x " .. ctx.rootPath .. "/bin/pre-uninstall")
end
end
LUA

cat >"$PLUGIN_DIR/hooks/env_keys.lua" <<'LUA'
function PLUGIN:EnvKeys(ctx)
return {
{ key = "PATH", value = ctx.path .. "/bin" },
}
end
LUA

cat >"$PLUGIN_DIR/hooks/pre_uninstall.lua" <<'LUA'
function PLUGIN:PreUninstall(ctx)
local marker = os.getenv("MISE_DATA_DIR") .. "/pre-uninstall-marker"
local file = io.open(marker, "w")
if file then
file:write(ctx.main.name .. ":" .. ctx.main.version .. ":" .. ctx.sdkInfo[ctx.main.name].path)
file:close()
end
end
LUA

git -C "$PLUGIN_DIR" init -q
git -C "$PLUGIN_DIR" add .
git -C "$PLUGIN_DIR" -c user.email=mise@example.com -c user.name=mise commit -m "init"

mise install "vfox:file://$PLUGIN_DIR@1.0.0"

mise uninstall "vfox:file://$PLUGIN_DIR@1.0.0" --dry-run
if [[ -f $MARKER ]]; then
fail "pre_uninstall hook ran during dry-run"
fi

mise uninstall "vfox:file://$PLUGIN_DIR@1.0.0"
assert_contains "cat '$MARKER'" "pre-uninstall:1.0.0:"
24 changes: 24 additions & 0 deletions src/backend/vfox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,30 @@ impl Backend for VfoxBackend {
Some(&self.plugin_enum)
}

async fn uninstall_version_impl(
&self,
config: &Arc<Config>,
_pr: &dyn crate::ui::progress_report::SingleReport,
tv: &ToolVersion,
) -> eyre::Result<()> {
if self.is_backend_plugin() || !self.plugin.is_installed() {
return Ok(());
}

let (mut vfox, log_rx) = self.plugin.vfox();
thread::spawn(|| {
for line in log_rx {
info!("{}", line);
}
});
if let Ok(dep_env) = self.dependency_env(config).await {
vfox.cmd_env = Some(dep_env.into_iter().collect());
}
vfox.pre_uninstall(&self.pathname, &tv.version, tv.install_path())
.await?;
Ok(())
}

async fn _idiomatic_filenames(&self) -> eyre::Result<Vec<String>> {
let (vfox, _log_rx) = self.plugin.vfox();

Expand Down
Loading