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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- #1122: Packaging should recognize resources in dependency modules set to deploy
- #1119: The update command should check version requirements using post-update values instead of what's currently installed
- #1097: The Test resource processor now supports nested tests
- #1116: Fix behavior inconsistencies between install and uninstall for package name casing.

### Security
- requests Python wheel updated to 2.33.0
Expand Down
10 changes: 6 additions & 4 deletions src/cls/IPM/Storage/ResourceReference.cls
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,15 @@ ClassMethod GetChildren(
set tResourceCache($$$lcase(tCacheResult.%Get("UniqueName"))) = ""
}
}
// include hidden files by temporarily enable showHidden global for Studio search
// Include hidden files by temporarily enabling showHidden global for Studio search.
// Use %SQLUPPER for case-insensitive package prefix matching instead of relying on
// StudioOpenDialog's built-in prefix filter, which is case-sensitive.
set tHidden = $get(^%SYS("Studio", "ShowHidden"), $char(0))
set ^%SYS("Studio","ShowHidden") = 1
// PKG extension should only cover .CLS files
set tFilesResult = ##class(%SQL.Statement).%ExecDirect(,
"select Name from %Library.RoutineMgr_StudioOpenDialog(?,'',1,1,1,0,0)",
tPackage_"*.cls,"_tPackage_"*.mac,"_tPackage_"*.int,"_tPackage_"*.inc")
"select Name from %Library.RoutineMgr_StudioOpenDialog(?,'',1,1,1,0,0) "
_"where %SQLUPPER(Name) %STARTSWITH %SQLUPPER(?)",
"*.cls,*.mac,*.int,*.inc", tPackage)
if (tFilesResult.%SQLCODE < 0) {
set tSC = $$$ERROR($$$SQLCode,tFilesResult.%SQLCODE,tFilesResult.%Message)
quit
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/// Tests that uninstall correctly handles PKG resources where the casing of the package
/// name in module.xml differs from the casing of the stored class/routine/include names,
/// and that resources owned by other modules within the same package are not deleted.
Class Test.PM.Integration.PkgCaseUninstall Extends Test.PM.Integration.Base
{

/// module.xml declares Test.PKGCASE.PKG (uppercase) but actual resources are Test.PkgCase.*
Parameter ModuleName = "pkg-case-test";

Method TestPkgCaseMismatchUninstall()
{
set moduleDir = ..GetModuleDir(..#ModuleName)
do $$$AssertStatusOK(##class(%IPM.Main).Shell("load " _ moduleDir), "Loaded pkg-case-test")

// Confirm resources were loaded
do $$$AssertTrue(##class(%Dictionary.ClassDefinition).%ExistsId("Test.PkgCase.MyClass"), "Class exists after load")
do $$$AssertTrue(##class(%Library.Routine).Exists("Test.PkgCase.MyRoutine.MAC"), "Routine exists after load")
do $$$AssertTrue(##class(%Library.Routine).Exists("Test.PkgCase.MyInclude.INC"), "Include exists after load")

do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall " _ ..#ModuleName), "Uninstalled pkg-case-test")

// All three resource types must be removed despite the casing mismatch in module.xml
do $$$AssertNotTrue(##class(%Dictionary.ClassDefinition).%ExistsId("Test.PkgCase.MyClass"), "Class removed after uninstall")
do $$$AssertNotTrue(##class(%Library.Routine).Exists("Test.PkgCase.MyRoutine.MAC"), "Routine removed after uninstall")
do $$$AssertNotTrue(##class(%Library.Routine).Exists("Test.PkgCase.MyInclude.INC"), "Include removed after uninstall")
}

/// Verifies that uninstalling a PKG module with a casing mismatch does not delete resources
/// owned by a different module that happen to fall within the same package prefix.
Method TestPkgCaseOwnershipExclusion()
{
set moduleDirA = ..GetModuleDir(..#ModuleName)
set moduleDirB = ..GetModuleDir("pkg-case-extra")
do $$$AssertStatusOK(##class(%IPM.Main).Shell("load " _ moduleDirA), "Loaded pkg-case-test")
do $$$AssertStatusOK(##class(%IPM.Main).Shell("load " _ moduleDirB), "Loaded pkg-case-extra")

do $$$AssertTrue(##class(%Dictionary.ClassDefinition).%ExistsId("Test.PkgCase.ExtraClass"), "ExtraClass exists after load")

do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall " _ ..#ModuleName), "Uninstalled pkg-case-test")

// ExtraClass belongs to pkg-case-extra and must survive uninstall of pkg-case-test
do $$$AssertTrue(##class(%Dictionary.ClassDefinition).%ExistsId("Test.PkgCase.ExtraClass"), "ExtraClass not removed by uninstall of pkg-case-test")

do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall pkg-case-extra"), "Uninstalled pkg-case-extra")

// ExtraClass should now be removed after uninstalling its owning module
do $$$AssertNotTrue(##class(%Dictionary.ClassDefinition).%ExistsId("Test.PkgCase.ExtraClass"), "ExtraClass removed by uninstall of pkg-case-extra")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Class Test.PkgCase.ExtraClass
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="pkg-case-extra.ZPM"><Module>
<Name>pkg-case-extra</Name>
<Version>0.0.1</Version>
<Resources>
<Resource Name="Test.PkgCase.ExtraClass.CLS"/>
</Resources>
</Module>
</Document></Export>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Class Test.PkgCase.MyClass
{

ClassMethod Hello() As %String
{
quit "hello"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
^INC^Save for Source Control^^~Format=Cache.S~^UTF8
%RO
Test.PkgCase.MyInclude^INC^^^0
#define PkgCaseValue 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ROUTINE Test.PkgCase.MyRoutine
write !, "Hello from Test.PkgCase.MyRoutine"
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="pkg-case-test.ZPM"><Module>
<Name>pkg-case-test</Name>
<Version>0.0.1</Version>
<Resources>
<Resource Name="Test.PKGCASE.PKG"/>
</Resources>
</Module>
</Document></Export>
Loading