Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- #1117: Add `sync` command for incremental loading of changed files in dev-mode modules. Detects modified files since last sync using SHA-1 hash and recompiles only what is stale. Supports `-delete` for processing removed files and `-test` for running changed test-phase unit tests.
- #106: A module can now specify `<SystemRequirements SYSNamespace="true"/>` to prevent installation in non-%SYS namespaces.
- #1081: Implement `locate-resource` command for resource-to-module mapping

### Fixed
- Performance: Studio project creation on package load in dev mode is now 80% faster.
Expand Down
23 changes: 23 additions & 0 deletions src/cls/IPM/Main.cls
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,13 @@ generate /my/path -export 00000,PacketName2,IgnorePacket2^00000,PacketName3,Igno
<example description="Display the current history retention setting.">config get HistoryRetain</example>
</command>

<command name="locate-resource" aliases="locate">
<description>Find the module that owns a specific resource.</description>
<parameter name="resource" required="true" description="resource: The full name of the resource (e.g., My.Class.cls, Utils.inc)." />
<example description="Finds the module containing the specified class.">locate-resource %IPM.Main.cls</example>
<example description="Finds the module containing the specified include file.">locate-resource %IPM.Common.inc</example>
</command>

</commands>
}

Expand Down Expand Up @@ -1113,6 +1120,8 @@ ClassMethod ShellInternal(
do ..History(.tCommandInfo)
} elseif (tCommandInfo = "sync") {
do ..Sync(.tCommandInfo)
} elseif (tCommandInfo = "locate-resource") {
do ..LocateResource(.tCommandInfo)
}
} catch pException {
if (pException.Code = $$$ERCTRLC) {
Expand Down Expand Up @@ -4383,6 +4392,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())
Expand Down
45 changes: 45 additions & 0 deletions tests/unit_tests/Test/PM/Unit/CLI.cls
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}

}