diff --git a/CHANGELOG.md b/CHANGELOG.md index b5c4c8a7..fd5f7fe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - #1178: Add `-password-env` and `-token-env` modifiers to the `repo` command to read the password/token from a named environment variable (secure alternatives to `-password` and `-token`). +- #1081: Implement locate-resource command for resource-to-module mapping ## [0.10.8] - 2026-07-08 diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index 98d1fd40..3f1ee058 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -810,6 +810,13 @@ generate /my/path -export 00000,PacketName2,IgnorePacket2^00000,PacketName3,Igno config get HistoryRetain + + Find the module that owns a specific resource. + + locate-resource %IPM.Main.cls + locate-resource %IPM.Common.inc + + } @@ -1098,6 +1105,8 @@ ClassMethod ShellInternal( do ..Information(.tCommandInfo) } elseif (tCommandInfo = "history") { do ..History(.tCommandInfo) + } elseif (tCommandInfo = "locate-resource") { + do ..LocateResource(.tCommandInfo) } } catch pException { if (pException.Code = $$$ERCTRLC) { @@ -4325,6 +4334,20 @@ ClassMethod Update(ByRef pCommandInfo) } } +ClassMethod LocateResource(ByRef CommandInfo) +{ + set resource = $get(CommandInfo("parameters","resource")) + set moduleName = ##class(%IPM.ExtensionBase.Utils).GetHomeModuleName(resource) + if (moduleName="") { + write $$$FormattedLine($$$Red, "Resource '"_ resource_"' is not currently part of an installed module.") + quit + } + set showFields = "" + write ! + do ..GetListModules(,moduleName, .list) + do ..DisplayModules(.list,,,, .tModifiers) +} + ClassMethod GetPythonInstalledLibs(Output list) { set target = ##class(%File).NormalizeDirectory("python", $system.Util.ManagerDirectory()) diff --git a/tests/unit_tests/Test/PM/Unit/CLI.cls b/tests/unit_tests/Test/PM/Unit/CLI.cls index 04f45ed3..cf137bfd 100644 --- a/tests/unit_tests/Test/PM/Unit/CLI.cls +++ b/tests/unit_tests/Test/PM/Unit/CLI.cls @@ -658,4 +658,49 @@ Method TestSortListVersionPrerelease() do $$$AssertEquals($listget(sorted(6),1), "snap", "version desc: snap (1.0.0-SNAPSHOT)") } +Method TestLocateCommand() +{ + set ipmModule = ##class(%IPM.Storage.Module).NameOpen("zpm",,.sc) + do $$$AssertStatusOK(sc, "Opened zpm module to get version") + set ipmVersion = ipmModule.VersionString + + do $$$LogMessage("Testing locate-resource with .inc resource") + do ##class(%IPM.Utils.Module).BeginCaptureOutput(.cookie) + set status = ##class(%IPM.Main).Shell("locate-resource %IPM.Common.inc") + do ##class(%IPM.Utils.Module).EndCaptureOutput(cookie, .output) + do $$$AssertStatusOK(status, "locate-resource %IPM.Common.inc executed successfully") + set content = "" + set i = "" + for { + set i = $order(output(i)) + quit:i="" + set content = content _ output(i) _ $char(10) + } + do $$$AssertTrue(content [ "zpm", "output contains module name 'zpm'") + do $$$AssertTrue(content [ ipmVersion, "output contains IPM version "_ipmVersion) + + do $$$LogMessage("Testing locate-resource with .cls resource") + do ##class(%IPM.Utils.Module).BeginCaptureOutput(.cookie) + set status = ##class(%IPM.Main).Shell("locate-resource %IPM.Main.cls") + do ##class(%IPM.Utils.Module).EndCaptureOutput(cookie, .output) + do $$$AssertStatusOK(status, "locate-resource %IPM.Main.cls executed successfully") + set content = "" + set i = "" + for { + set i = $order(output(i)) + quit:i="" + set content = content _ output(i) _ $char(10) + } + do $$$AssertTrue(content [ "zpm", "output contains module name 'zpm'") + do $$$AssertTrue(content [ ipmVersion, "output contains IPM version "_ipmVersion) + + do $$$LogMessage("Testing locate-resource with non-existing resource") + set status = ..RunCommand("locate-resource Test.Sample.inc") + do $$$AssertStatusOK(status, "Gracefully handled non-existing resource") + + do $$$LogMessage("Testing locate-resource without required argument") + set status = ..RunCommand("locate-resource") + do $$$AssertStatusNotOK(status, "Handled missing argument") +} + }