From a342c261a70f3fe680e5ec8746e530c8ebff75b6 Mon Sep 17 00:00:00 2001 From: Han Li Date: Mon, 22 Apr 2024 16:30:11 +0800 Subject: [PATCH] feat: add a new hook `PreUninstall` (#223) * tmp * feat: add a new hook `PreUninstall` This is called before the SDK is uninstalled. If the plugin needs to perform some operations before uninstalling, it can implement this hook function. For example, cleaning up the cache, deleting configuration files, etc. fix #208 --- docs/plugins/create/howto.md | 21 +++++++++++++ docs/zh-hans/plugins/create/howto.md | 25 +++++++++++++-- internal/interfaces.go | 5 +++ internal/plugin.go | 31 +++++++++++++++++++ internal/plugin_test.go | 27 ++++++++++++++++ internal/sdk.go | 17 +++++++--- .../testdata/plugins/java_with_main/main.lua | 12 +++++++ .../hooks/pre_uninstall.lua | 14 +++++++++ 8 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 internal/testdata/plugins/java_with_metadata/hooks/pre_uninstall.lua diff --git a/docs/plugins/create/howto.md b/docs/plugins/create/howto.md index 47f2b640..86b984f8 100644 --- a/docs/plugins/create/howto.md +++ b/docs/plugins/create/howto.md @@ -44,6 +44,7 @@ The full list of hooks callable from vfox. | [hooks/post_install.lua](#postinstall) | ❌ | Execute additional operations after install, such as compiling source code, etc | | [hooks/pre_use.lua](#preuse) | ❌ | An opportunity to change the version before using it | | [hooks/parse_legacy_file.lua](#parselegacyfile) | ❌ | Custom parser for legacy version files | +| [hooks/pre_uninstall.lua](#preuninstall) | ❌ | Perform some operations before uninstalling targeted version | ## Required hook functions @@ -237,6 +238,26 @@ function PLUGIN:ParseLegacyFile(ctx) end ``` +### PreUninstall + +This is called before the SDK is uninstalled. If the plugin needs to perform some operations before +uninstalling, it can implement this hook function. For example, cleaning up the cache, deleting configuration files, etc. + +**Location**: `hooks/pre_uninstall.lua` +```lua +function PLUGIN:PreUninstall(ctx) + local mainSdkInfo = ctx.main + local mainPath = mainSdkInfo.path + local mversion = mainSdkInfo.version + local mname = mainSdkInfo.name + --- Other SDK information, the `addition` field returned in PreInstall, obtained by name + local sdkInfo = ctx.sdkInfo['sdk-name'] + local path = sdkInfo.path + local version = sdkInfo.version + local name = sdkInfo.name +end +``` + ## Test Plugin Currently, VersionFox plugin testing is straightforward. You only need to place the plugin file in the diff --git a/docs/zh-hans/plugins/create/howto.md b/docs/zh-hans/plugins/create/howto.md index 742d68a7..6be1e928 100644 --- a/docs/zh-hans/plugins/create/howto.md +++ b/docs/zh-hans/plugins/create/howto.md @@ -44,6 +44,7 @@ | [hooks/post_install.lua](#postinstall) | ❌ | 执行额外的操作, 如编译源码等 | | [hooks/pre_use.lua](#preuse) | ❌ | 在切换版本之前, 提供修改版本的机会 | | [hooks/parse_legacy_file.lua](#parselegacyfile) | ❌ | 自定义解析遗留文件 | +| [hooks/pre_uninstall.lua](#preuninstall) | ❌ | 删除之前进行额外操作 | ## 必须实现的钩子函数 @@ -114,8 +115,10 @@ end **位置**: `hooks/env_keys.lua` ```lua function PLUGIN:EnvKeys(ctx) - --- this variable is same as ctx.sdkInfo['plugin-name'].path - local mainPath = ctx.path + local mainSdkInfo = ctx.main + local mainPath = mainSdkInfo.path + local mversion = mainSdkInfo.version + local mname = mainSdkInfo.name local sdkInfo = ctx.sdkInfo['sdk-name'] local path = sdkInfo.path local version = sdkInfo.version @@ -225,6 +228,24 @@ function PLUGIN:ParseLegacyFile(ctx) end ``` +### PreUninstall + +在卸载 SDK 之前执行的钩子函数。如果插件需要在卸载之前执行一些操作,可以实现这个钩子函数。例如清理缓存、删除配置文件等。 + +**位置**: `hooks/pre_uninstall.lua` +```lua +function PLUGIN:PreUninstall(ctx) + local mainSdkInfo = ctx.main + local mainPath = mainSdkInfo.path + local mversion = mainSdkInfo.version + local mname = mainSdkInfo.name + --- 其他 SDK 信息, PreInstall中返回的`addition`字段, 通过name获取 + local sdkInfo = ctx.sdkInfo['sdk-name'] + local path = sdkInfo.path + local version = sdkInfo.version + local name = sdkInfo.name +end +``` ## 测试插件 diff --git a/internal/interfaces.go b/internal/interfaces.go index d84dc1dd..a51cd1f3 100644 --- a/internal/interfaces.go +++ b/internal/interfaces.go @@ -165,6 +165,11 @@ type ParseLegacyFileResult struct { Version string `luai:"version"` } +type PreUninstallHookCtx struct { + Main *Info `luai:"main"` + SdkInfo map[string]*Info `luai:"sdkInfo"` +} + type LuaPluginInfo struct { Name string `luai:"name"` Version string `luai:"version"` diff --git a/internal/plugin.go b/internal/plugin.go index 654ad590..19e68519 100644 --- a/internal/plugin.go +++ b/internal/plugin.go @@ -52,6 +52,7 @@ var ( "PostInstall": {Name: "PostInstall", Required: false, Filename: "post_install"}, "PreUse": {Name: "PreUse", Required: false, Filename: "pre_use"}, "ParseLegacyFile": {Name: "ParseLegacyFile", Required: false, Filename: "parse_legacy_file"}, + "PreUninstall": {Name: "PreUninstall", Required: false, Filename: "pre_uninstall"}, } ) @@ -377,6 +378,36 @@ func (l *LuaPlugin) ParseLegacyFile(path string, installedVersions func() []Vers } +// PreUninstall executes the PreUninstall hook function. +func (l *LuaPlugin) PreUninstall(p *Package) error { + if !l.HasFunction("PreUninstall") { + logger.Debug("plugin does not have PreUninstall function") + return nil + } + + L := l.vm.Instance + + ctx := &PreUninstallHookCtx{ + Main: p.Main, + SdkInfo: make(map[string]*Info), + } + logger.Debugf("PreUninstallHookCtx: %+v \n", ctx) + + for _, v := range p.Additions { + ctx.SdkInfo[v.Name] = v + } + + ctxTable, err := luai.Marshal(L, ctx) + if err != nil { + return err + } + + if err = l.CallFunction("PreUninstall", ctxTable); err != nil { + return err + } + return nil +} + func (l *LuaPlugin) CallFunction(funcName string, args ...lua.LValue) error { logger.Debugf("CallFunction: %s\n", funcName) if err := l.vm.CallFunction(l.pluginObj.RawGetString(funcName), append([]lua.LValue{l.pluginObj}, args...)...); err != nil { diff --git a/internal/plugin_test.go b/internal/plugin_test.go index 02856734..eeafb186 100644 --- a/internal/plugin_test.go +++ b/internal/plugin_test.go @@ -325,4 +325,31 @@ func testHookFunc(t *testing.T, factory func() (*LuaPlugin, error)) { } }) + + t.Run("PreUninstall", func(t *testing.T) { + plugin, err := factory() + if err != nil { + t.Fatal(err) + } + + err = plugin.PreUninstall(&Package{ + Main: &Info{ + Name: "java", + Version: "1.0.0", + Path: "/path/to/java", + Note: "xxxx", + }, + Additions: []*Info{ + { + Name: "sdk-name", + Version: "9.0.0", + Path: "/path/to/sdk", + Note: "xxxx", + }, + }, + }) + if err != nil { + t.Fatal(err) + } + }) } diff --git a/internal/sdk.go b/internal/sdk.go index 7922b9fc..c55c432c 100644 --- a/internal/sdk.go +++ b/internal/sdk.go @@ -192,7 +192,7 @@ func (b *Sdk) preInstallSdk(info *Info, sdkDestPath string) (string, error) { } } -func (b *Sdk) Uninstall(version Version) error { +func (b *Sdk) Uninstall(version Version) (err error) { label := b.label(version) if !b.CheckExists(version) { return fmt.Errorf("%s is not installed", pterm.Red(label)) @@ -201,12 +201,21 @@ func (b *Sdk) Uninstall(version Version) error { b.clearEnvConfig(version) } path := b.VersionPath(version) - err := os.RemoveAll(path) + sdkPackage, err := b.GetLocalSdkPackage(version) if err != nil { - return err + return + } + // Give the plugin a chance before actually uninstalling targeted version. + err = b.Plugin.PreUninstall(sdkPackage) + if err != nil { + return + } + err = os.RemoveAll(path) + if err != nil { + return } pterm.Printf("Uninstalled %s successfully!\n", label) - return nil + return } func (b *Sdk) Available(args []string) ([]*Package, error) { diff --git a/internal/testdata/plugins/java_with_main/main.lua b/internal/testdata/plugins/java_with_main/main.lua index 07b287f2..cfae0def 100644 --- a/internal/testdata/plugins/java_with_main/main.lua +++ b/internal/testdata/plugins/java_with_main/main.lua @@ -188,3 +188,15 @@ function PLUGIN:ParseLegacyFile(ctx) end end + +function PLUGIN:PreUninstall(ctx) + printTable(ctx) + local mainSdkInfo = ctx.main + local mpath = mainSdkInfo.path + local mversion = mainSdkInfo.version + local mname = mainSdkInfo.name + local sdkInfo = ctx.sdkInfo['sdk-name'] + local path = sdkInfo.path + local version = sdkInfo.version + local name = sdkInfo.name +end diff --git a/internal/testdata/plugins/java_with_metadata/hooks/pre_uninstall.lua b/internal/testdata/plugins/java_with_metadata/hooks/pre_uninstall.lua new file mode 100644 index 00000000..22ac5b60 --- /dev/null +++ b/internal/testdata/plugins/java_with_metadata/hooks/pre_uninstall.lua @@ -0,0 +1,14 @@ + + + +function PLUGIN:PreUninstall(ctx) + printTable(ctx) + local mainSdkInfo = ctx.main + local mpath = mainSdkInfo.path + local mversion = mainSdkInfo.version + local mname = mainSdkInfo.name + local sdkInfo = ctx.sdkInfo['sdk-name'] + local path = sdkInfo.path + local version = sdkInfo.version + local name = sdkInfo.name +end \ No newline at end of file