From f264c1257e5f86142cd65c97718e907445832adc Mon Sep 17 00:00:00 2001 From: kiyer Date: Tue, 16 Sep 2025 10:02:23 -0400 Subject: [PATCH 1/7] Update CLI commands to deprecate synchronous flag --- src/cls/IPM/CLI.cls | 17 +++++++++++++++++ src/cls/IPM/CLI/Commands.cls | 21 ++++++++++++++++----- src/cls/IPM/Main.cls | 30 +++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/cls/IPM/CLI.cls b/src/cls/IPM/CLI.cls index 838c96ba..06a487fa 100644 --- a/src/cls/IPM/CLI.cls +++ b/src/cls/IPM/CLI.cls @@ -401,7 +401,9 @@ ClassMethod %HelpForCommandExamples( /// Parses a command, validating it based on the Commands XData block and structuring output as follows: /// pCommandInfo = "" /// pCommandInfo("modifiers","") = "" +/// pCommandInfo("modifiers","","deprecated") = 0/1 /// pCommandInfo("parameters","") = "" +/// pCommandInfo("parameters","","deprecated") = 0/1 /// pCommandInfo("data","") = "" ClassMethod %ParseCommandInput( pCommandString As %String, @@ -646,6 +648,21 @@ ClassMethod %ParseCommandInput( } } + // Add in deprecated info to parameters and modifiers + set tCommandName = $get(pCommandInfo) + if (tCommandName '= "") { + for tType="parameters","modifiers" { + set tKey = "" + while 1 { + set tKey = $order(pCommandInfo(tType,tKey)) + if (tKey = "") { + quit + } + set pCommandInfo(tType,tKey,"deprecated") = $get(tCommandStructure(tCommandName,tType,tKey,"deprecated"),0) + } + } + } + // TODO: Extra validation. } catch e { if e.%IsA("%Exception.SystemException") { diff --git a/src/cls/IPM/CLI/Commands.cls b/src/cls/IPM/CLI/Commands.cls index 5906f410..79f0c2ef 100644 --- a/src/cls/IPM/CLI/Commands.cls +++ b/src/cls/IPM/CLI/Commands.cls @@ -48,6 +48,9 @@ XData Schema [ Internal, MimeType = application/xml ] + + + @@ -92,16 +95,19 @@ XData Schema [ Internal, MimeType = application/xml ] - + + + + - + @@ -159,7 +165,7 @@ XData Schema [ Internal, MimeType = application/xml ] } -/// Turns the Comomand XData block into a subscripted array as follows: +/// Turns the Command XData block into a subscripted array as follows: /// pCommandStructure(1, "") = "" /// pCommandStructure("") -> /// "description" = describes the command @@ -173,11 +179,13 @@ XData Schema [ Internal, MimeType = application/xml ] /// "aliases" = aliases for the modifier /// "description" = describes the modifier /// "required" = whether or not modifier is required for the command +/// "deprecated" = whether or not modifier is deprecated for the command /// "trailing" = whether modifier is a trailing modifier /// "parameters": /// "": /// "description" = description of parameter /// "required" = is parameter required +/// "deprecated" = whether or not parameter is deprecated for the command ClassMethod %GetOneCommandStructure(Output pCommandStructure) [ CodeMode = objectgenerator ] { #define DefaultGroup "-" @@ -315,9 +323,10 @@ ClassMethod %GetOneCommandStructure(Output pCommandStructure) [ CodeMode = objec do %code.WriteLine(" Set pCommandStructure("_tName_","_$$$QUOTE(tMap(tCommChild))_") = "_tDescContent) } } else { - // Common: name, required, description + // Common to bother modifier and parameter set tChildName = $$$QUOTE(tMap(tCommChild,"a","name")) set tRequired = $case($get(tMap(tCommChild,"a","required")),"true":1,:0) + set tDeprecated = $case($get(tMap(tCommChild,"a","deprecated")),"true":1,:0) if (tMap(tCommChild) = "modifier") { // Also: aliases, value, valueList @@ -337,17 +346,19 @@ ClassMethod %GetOneCommandStructure(Output pCommandStructure) [ CodeMode = objec do %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""group"") = "_tGroupName) do %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""value"") = "_$case(tValue,"true":1,:0)) do %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""required"") = "_tRequired) + do %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""deprecated"") = "_tDeprecated) do:(tDesc'=$$$empty) %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""description"") = "_tDesc) do:(tValueList'=$$$empty) %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""valueList"") = "_tValueList) do:(tDataAlias'=$$$empty) %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""dataAlias"") = "_tDataAlias) do:(tDataValue'=$$$empty) %code.WriteLine(" Set pCommandStructure("_tName_",""modifiers"","_tChildName_",""dataValue"") = "_tDataValue) - } elseif (tMap(tCommChild) = "parameter") { + } elseif (tMap(tCommChild) = "parameter") { // Also: example set tExample = $$$QUOTE($get(tMap(tCommChild,"a","example"))) set tTrailing = $case($get(tMap(tCommChild,"a","trailing")),"true":1,:0) do %code.WriteLine(" Set pCommandStructure("_tName_",""parameters"",$i(pCommandStructure("_tName_",""parameters""))) = "_tChildName) do %code.WriteLine(" Set pCommandStructure("_tName_",""parameters"","_tChildName_",""trailing"") = "_tTrailing) do %code.WriteLine(" Set pCommandStructure("_tName_",""parameters"","_tChildName_",""required"") = "_tRequired) + do %code.WriteLine(" Set pCommandStructure("_tName_",""parameters"","_tChildName_",""deprecated"") = "_tDeprecated) do:(tDesc'=$$$empty) %code.WriteLine(" Set pCommandStructure("_tName_",""parameters"","_tChildName_",""description"") = "_tDesc) do:(tExample'=$$$empty) %code.WriteLine(" Set pCommandStructure("_tName_",""parameters"","_tChildName_",""example"") = "_tExample) } diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index fbb94b38..5255085d 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -262,7 +262,7 @@ load C:\module\root\path -env C:\path\to\env1.json;C:\path\to\env2.json - + @@ -338,7 +338,6 @@ run C:\Temp\MyCommands.json, where contents of the file are as follows: "latest": "" }, "custom_modifiers": { - "NoMapping": 1, "Deploy.Parameter": "TESTDEPLOY" } } @@ -385,7 +384,7 @@ install -env /path/to/env1.json;/path/to/env2.json example-package - + @@ -896,6 +895,9 @@ ClassMethod ShellInternal( // Parse command $$$ThrowOnError(..%ParseCommandInput(tCommand,.tParsedCommandInfo)) + // Warn for deprecated parameters/modifiers + do ..WarnOnDeprecatedModifiersOrParameters(.tParsedCommandInfo) + // Merge defaults first so they can be overwritten by commands do ..GetNamespaceDefaultModifiers(.tDefaultArray) merge tCommandInfo("data") = tDefaultArray @@ -976,6 +978,22 @@ ClassMethod ShellInternal( } } +/// Warn for deprecated parameters/modifiers +ClassMethod WarnOnDeprecatedModifiersOrParameters(ByRef pCommandInfo) [ Internal, Private ] +{ + for key = "modifiers", "parameters" { + set name = "" + for { + set name = $order(pCommandInfo(key,name)) + quit:name="" + if ($get(pCommandInfo(key,name,"deprecated"),0)) { + set singularKey = $zconvert($extract(key,1),"U") _ $extract(key,2,*-1) + write !,$$$FormattedLine($$$Yellow, $$$FormatText("WARNING: %1 '%2' is deprecated and will be removed in future versions. Run 'help ' to view further details.",singularKey,name)),! + } + } + } +} + ClassMethod DisplayError(pStatus As %Status) { if $$$ISERR(pStatus) { @@ -2111,7 +2129,6 @@ ClassMethod LoadFromRepo( ClassMethod Load(ByRef pCommandInfo) [ Internal ] { set tDirectoryName = $get(pCommandInfo("parameters","path")) - set tSynchronous = $$$HasModifier(pCommandInfo,"synchronous") merge tParams = pCommandInfo("data") set tParams("cmd") = "load" do ##class(%Net.URLParser).Decompose(tDirectoryName, .tComponents) @@ -2155,7 +2172,7 @@ ClassMethod Load(ByRef pCommandInfo) [ Internal ] set tTargetDirectory = $get(tTargetDirectory, tDirectoryName) set dotModules = ##class(%File).NormalizeDirectory(".modules", tTargetDirectory) set tmpRepoMgr = ##class(%IPM.General.TempLocalRepoManager).%New(dotModules, 1) - set tSC = ##class(%IPM.Utils.Module).LoadNewModule(tTargetDirectory, .tParams, , tSynchronous) + set tSC = ##class(%IPM.Utils.Module).LoadNewModule(tTargetDirectory, .tParams) set tSC = $$$ADDSC(tSC, tmpRepoMgr.CleanUp()) $$$ThrowOnError(tSC) } @@ -2197,7 +2214,6 @@ ClassMethod Install(ByRef pCommandInfo) [ Internal ] set tVersion = $get(pCommandInfo("parameters","version")) set tKeywords = $$$GetModifier(pCommandInfo,"keywords") - set tSynchronous = $$$HasModifier(pCommandInfo,"synchronous") set tSearchCriteria = ##class(%IPM.Repo.SearchCriteria).%New() set tSearchCriteria.Registry = tRegistry @@ -2241,7 +2257,7 @@ ClassMethod Install(ByRef pCommandInfo) [ Internal ] $$$ThrowStatus($$$ERROR($$$GeneralError, "Deployed package '" _ tModuleName _ "' " _ tResult.VersionString _ " not supported on this platform " _ platformVersion _ ".")) } } - $$$ThrowOnError(##class(%IPM.Utils.Module).LoadQualifiedReference(tResult, .tParams, , tSynchronous)) + $$$ThrowOnError(##class(%IPM.Utils.Module).LoadQualifiedReference(tResult, .tParams)) } } else { set tPrefix = "" From fe5bbf4dbd8f7ef4f85d7695c5ba7ad84e0886fa Mon Sep 17 00:00:00 2001 From: kiyer Date: Tue, 16 Sep 2025 10:27:44 -0400 Subject: [PATCH 2/7] Remove various LoadDependencies() calls as this should just be handled at install time. Convert default to sync loading. Remove InstallContext as its no longer needed. --- src/cls/IPM/General/InstallContext.cls | 72 ------ src/cls/IPM/Lifecycle/Base.cls | 16 +- src/cls/IPM/Storage/Module.cls | 178 ++++----------- src/cls/IPM/Utils/Module.cls | 298 ++----------------------- src/inc/IPM/Common.inc | 7 +- 5 files changed, 72 insertions(+), 499 deletions(-) delete mode 100644 src/cls/IPM/General/InstallContext.cls diff --git a/src/cls/IPM/General/InstallContext.cls b/src/cls/IPM/General/InstallContext.cls deleted file mode 100644 index 9ab5cdc3..00000000 --- a/src/cls/IPM/General/InstallContext.cls +++ /dev/null @@ -1,72 +0,0 @@ -Include %IPM.Common - -Class %IPM.General.InstallContext Extends %IPM.General.Singleton -{ - -/// If set to 1, calls to %Get must return an instance of this class created in the current namespace; a new instance will be created if none exists. -Parameter NAMESPACESCOPE As BOOLEAN = 1; - -Property DependencyGraph [ MultiDimensional, Private ]; - -Property CacheTempIndex As %Integer [ Private ]; - -Method SetGraph(ByRef pDependencyGraph) -{ - kill ..DependencyGraph - merge ..DependencyGraph = pDependencyGraph -} - -Method SetCacheTempIndex(pIndex As %Integer = "") -{ - set ..CacheTempIndex = pIndex -} - -Method GetModuleList() As %List -{ - set tList = "" - set tModuleName = "" - for { - set tModuleName = $order(..DependencyGraph(tModuleName)) - if (tModuleName = "") { - quit - } - set tList = tList_$listbuild(tModuleName) - } - quit tList -} - -Method ModuleIsDependency(pModuleName As %String) As %Boolean -{ - quit ($data(..DependencyGraph(pModuleName)) > 0) -} - -Method GetPendingModuleList() As %List -{ - if (..CacheTempIndex = "") { - quit "" - } - - // The caller should have the temp global locked, but just in case... - merge tGraph = $$$ZPMTempLoadGraph(..CacheTempIndex) - - set tList = "" - set tModuleName = "" - for { - set tModuleName = $order(tGraph(tModuleName)) - if (tModuleName = "") { - quit - } - set tList = tList_$listbuild(tModuleName) - } - quit tList -} - -Method ModuleIsPending(pModuleName As %String) As %Boolean -{ - if (..CacheTempIndex = "") { - quit 0 - } - quit ($data($$$ZPMTempLoadGraph(..CacheTempIndex,pModuleName)) > 0) -} - -} diff --git a/src/cls/IPM/Lifecycle/Base.cls b/src/cls/IPM/Lifecycle/Base.cls index 7e5f4f02..cdfb70fc 100644 --- a/src/cls/IPM/Lifecycle/Base.cls +++ b/src/cls/IPM/Lifecycle/Base.cls @@ -900,10 +900,6 @@ Method %Compile(ByRef pParams) As %Status $$$ThrowOnError(##class(%Studio.SourceControl.Interface).SourceControlCreate()) } - // Load dependencies correctly for the requested phases. (This will be a no-op in most cases.) - set tSC = ..Module.LoadDependencies(..PhaseList,.pParams) - $$$ThrowOnError(tSC) - // Compile items within the module that are compilable using OnPhase set orderedResourceList = ..Module.GetOrderedResourceList() set tKey = "" @@ -1078,10 +1074,6 @@ Method %Test(ByRef pParams) As %Status { set tSC = $$$OK try { - // Load dependencies correctly for the requested phases. (This will be a no-op in most cases.) - set tSC = ..Module.LoadDependencies(..PhaseList,.pParams) - $$$ThrowOnError(tSC) - set orderedResourceList = ..Module.GetOrderedResourceList() set tKey = "" for { @@ -1129,7 +1121,7 @@ Method %Export( } set tExportDependencies = $get(pParams("ExportDependencies"), ..#EXPORTDEPENDENCIES) - set tSC = ..Module.GetResolvedReferences(.tResourceArray, tExportDependencies,..PhaseList,1,.pDependencyGraph) + set tSC = ..Module.GetResolvedReferences(.tResourceArray, tExportDependencies,..PhaseList,.pDependencyGraph) if $$$ISERR(tSC) { quit } @@ -1318,10 +1310,6 @@ Method %Verify(ByRef pParams) As %Status } } - // Load dependencies correctly for the requested phases. (This will be a no-op in most cases.) - set tSC = ..Module.LoadDependencies(..PhaseList,.pParams) - $$$ThrowOnError(tSC) - set orderedResourceList = ..Module.GetOrderedResourceList() set tKey = "" for { @@ -1602,7 +1590,7 @@ Method %MakeDeployed(ByRef pParams) As %Status // Default implementation: see which resources are expicitly flagged with Deploy = true. // Build an array of those, then mark them as deployed. - $$$ThrowOnError(..Module.GetResolvedReferences(.tResourceArray,tLockedDependencies,..PhaseList,1,.pDependencyGraph)) + $$$ThrowOnError(..Module.GetResolvedReferences(.tResourceArray,tLockedDependencies,..PhaseList,.pDependencyGraph)) set tModuleKey = "" for { diff --git a/src/cls/IPM/Storage/Module.cls b/src/cls/IPM/Storage/Module.cls index e59baf3b..6fd0990b 100644 --- a/src/cls/IPM/Storage/Module.cls +++ b/src/cls/IPM/Storage/Module.cls @@ -356,16 +356,7 @@ ClassMethod ExecutePhases( // Report timing subject to parameter; overall timing if only one phase has yet been tracked in context // (e.g., set up in multithreaded load) and more than one phase is to be executed. set tTiming = $get(pParams("Timing"),0) - set tOverallTiming = tTiming && ($listlength(tPhases) > 1) && ($listlength($get($$$ZPMHandledModules($namespace,pModuleName))) < 2) - - // Subscript by namespace to handle application build and integration testing processes, which may - // load a module in a different namespace (and call ExecutePhases there) at a lower stack level than the - // initial call to ExecutePhases - if '$data($$$ZPMHandledModules($namespace)) { - new $$$ZPMHandledModules - } else { - set $$$ZPMHandledModules($namespace,pModuleName) = $get($$$ZPMHandledModules($namespace,pModuleName))_tPhases - } + set tOverallTiming = tTiming && ($listlength(tPhases) > 1) // Execute resolved phases in sequence set tLifecycle.PhaseList = tPhases @@ -629,67 +620,45 @@ ClassMethod HasScope( quit $listfind(tPhases, scopeItem) > 0 } -Method LoadDependencies( - pPhaseList As %List, - ByRef pParams) As %Status -{ - set tSC = $$$OK - try { - set tVerbose = $get(pParams("Verbose")) - - if '$data(pParams("qstruct")) { - set qstruct = "ck"_$select(tVerbose:"d",1:"-d") - } else { - merge qstruct = pParams("qstruct") - } - - // Resolve and validate dependencies - set tReloadSnapshots = +$get(pParams("UpdateSnapshots")) - set tPermitDowngrade = +$get(pParams("PermitDowngrade")) - set tSC = ..BuildDependencyGraph(.tDependencyGraph,,tReloadSnapshots,.qstruct,pPhaseList,,,,,,tPermitDowngrade) - if $$$ISERR(tSC) { - quit - } - - if $data(tDependencyGraph) { - set tOptimizeInstalled = 'tReloadSnapshots - write:tVerbose !,"Dependencies:" - set tModuleLoop = "" - for { - set tModuleLoop = $order(tDependencyGraph(tModuleLoop),1,tValue) - quit:tModuleLoop="" - - if (tOptimizeInstalled) && '$data($$$ZPMHandledModules($namespace,tModuleLoop)) { - // Optimize for exact version matches that are already installed. - if ##class(%IPM.Storage.Module).NameExists(tModuleLoop) { - set tMod = ##class(%IPM.Storage.Module).NameOpen(tModuleLoop,,.tSC) - $$$ThrowOnError(tSC) - if (tMod.VersionString = $listget(tValue,3)) { - set $list(tValue,2) = "" - set $list(tDependencyGraph(tModuleLoop),2) = "" - } - } - } - - set tServer = $case($listget(tValue,2),"":" (installed)",:" @ "_$listget(tValue,2)) - write:tVerbose !,tModuleLoop," ",$listget(tValue,3),tServer - } - - // Download dependencies. - kill tParams - merge tParams("qstruct") = qstruct - merge tParams = pParams - set tSC = ##class(%IPM.Utils.Module).LoadDependencies(.tDependencyGraph,.tParams) - if $$$ISERR(tSC) { - quit - } - } - } catch e { - set tSC = e.AsStatus() - } - quit tSC -} - +/// Builds a dependency graph for this module, recursively resolving dependencies to the specified depth. +/// The dependency graph is returned in pDependencyGraph, which is an array where the keys are module names and the values are lists of three items: +///
    +///
  • Depth in the dependency tree (1 for direct dependencies, 2 for dependencies of dependencies, etc.)
  • +///
  • Server from which the module will be (or was) obtained; empty string if already installed
  • +///
  • Version string of the module to be installed
  • +///
+///

+/// If pDepth is 1, only direct dependencies are resolved. +/// If it is 2, dependencies of dependencies are also resolved, and so on. +/// If it is 0, dependencies are resolved to any depth. +///

+/// If pForceSnapshotReload is 1, then any cached snapshot of available modules is reloaded from the repository server(s). +///

+/// qstruct is passed to the repository manager to control which repositories are queried. +///

+/// pPhases is a list of lifecycle phases that will be executed for the module. +/// This is used to determine whether scoped dependencies should be considered. +/// If empty, all dependencies are considered. +///

+/// pSubModules is an output parameter that returns a list of submodules that were found. +///

+/// pPass controls whether exact version dependencies (1) or fuzzy version dependencies (2) are processed. +/// The method is typically called twice, once for each pass. +///

+/// pModulePath is used internally to track the path of modules being processed, to detect cyclic dependencies. +///

+/// If pIgnoreInstalledModules is 1, then already-installed modules are not considered when resolving dependencies. +///

+/// pKnownDependencies is a list of modules that are known dependencies of the root module being installed. +/// This is used to avoid considering these modules as already-installed when resolving dependencies. +///

+/// If pPermitDowngrade is 1, then dependencies that require downgrading an already-installed module are permitted. +///

+/// If pCheckNestedScoped is 1, then scoped dependencies of dependencies are checked against the phases of the root module being installed. +///

+/// pSearchList is an output parameter that returns a list of repository servers that were searched. +///

+/// If pIncludeDisplayName is 1, then the display name of each module is included in the output list for informational purposes. Method BuildDependencyGraph( ByRef pDependencyGraph, pDepth As %Integer = 1, @@ -704,7 +673,7 @@ Method BuildDependencyGraph( pPermitDowngrade As %Boolean = 0, pCheckNestedScoped As %Boolean = 0, ByRef pSearchList, - pIncludeDisplayName As %Boolean = 0) As %Status + pIncludeDisplayName As %Boolean = 0) As %Status [ Internal ] { #define EXACT 1 #define FUZZY 2 @@ -719,10 +688,6 @@ Method BuildDependencyGraph( set tRepositoryManager = ##class(%IPM.Repo.Manager).%Get(.tSC) $$$ThrowOnError(tSC) - // Disregard violation of dependencies of pending modules - set tInstallContext = ##class(%IPM.General.InstallContext).%Get(.tSC) - $$$ThrowOnError(tSC) - // May want to pass phases to subsequent calls set tPhases = $case(pCheckNestedScoped, 1: pPhases, : "") for i=1:1:..Dependencies.Count() { @@ -772,9 +737,8 @@ Method BuildDependencyGraph( if 'pIgnoreInstalledModules { // Also apply requirements presented by other installed modules, with the exception of those that are: // * Known as dependencies of the root module being installed (and thus eligible for upgrade) - // * Pending (re)installation // * Already in the dependency graph - set tOtherDeps = pKnownDependencies_tInstallContext.GetPendingModuleList() + set tOtherDeps = pKnownDependencies set tExistingDepKey = "" for { set tExistingDepKey = $order(pDependencyGraph(tExistingDepKey)) @@ -807,13 +771,6 @@ Method BuildDependencyGraph( // The "clean" phase can be used to bypass this (by removing modules from the current namespace) // Forcing an update from disk can also override this, although we ensure that the same module is // not loaded multiple times in a given operation. - set tForceSnapshotReload = pForceSnapshotReload - if tForceSnapshotReload && $data($$$ZPMHandledModules($namespace,tDep.Name),tHandled) { - if $listfind(tHandled,"Activate") { - // If we have already activated the given module, don't do so again. - set tForceSnapshotReload = 0 - } - } if ('pIgnoreInstalledModules) && ..NameExists(tDep.Name) { set tLocalObj = ..NameOpen(tDep.Name,,.tSC) if $$$ISERR(tSC) { @@ -821,7 +778,7 @@ Method BuildDependencyGraph( } set tInstalledVersionValid = tLocalObj.Version.Satisfies(tSearchExpr) && ((tVersion = "") || (tVersion = tLocalObj.VersionString)) - if tInstalledVersionValid && '(tLocalObj.Version.IsSnapshot() && tForceSnapshotReload) { + if tInstalledVersionValid && '(tLocalObj.Version.IsSnapshot() && pForceSnapshotReload) { set tLocalMod = 1 set tDepth = $select(tPreviousDepth=0:pDepth,tPreviousDepth>pDepth:tPreviousDepth,1:pDepth) set pDependencyGraph(tDep.Name) = $listbuild(pDepth,"",tLocalObj.VersionString) @@ -1086,7 +1043,6 @@ Method GetResolvedReferences( Output pReferenceArray, pLockedDependencies As %Boolean = 0, pPhases As %List = "", - pSkipDependencies As %Boolean = 0, ByRef pDependencyGraph) As %Status { set tSC = $$$OK @@ -1098,16 +1054,6 @@ Method GetResolvedReferences( } } - if 'pSkipDependencies { - kill tParams - set tParams("Verbose") = 0 - set tParams("qstruct") = "k" - set tSC = ##class(%IPM.Utils.Module).LoadDependencies(.pDependencyGraph,.tParams) - if $$$ISERR(tSC) { - quit - } - } - set pReferenceArray(..Name, ..Name_".ZPM") = "" set orderedResourceList = ..GetOrderedResourceList() @@ -1151,7 +1097,7 @@ Method GetResolvedReferences( // pLockedDependencies=0 to avoid duplicating effort on nested dependencies; // this loop will already get all of them. - set tSC = tModule.GetResolvedReferences(.pReferenceArray,0,,1) + set tSC = tModule.GetResolvedReferences(.pReferenceArray,0) if $$$ISERR(tSC) { quit } @@ -1289,11 +1235,6 @@ Method %OnValidateObject() As %Status [ Private, ServerOnly = 1 ] quit } - // Pre-check for uniqueness among resources (make sure there are no collisions and report descriptive errors if there are). - // This is simpler than trying to interpret a unique index violation later, and will work in all cases where we're updating modules. - set tInstallContext = ##class(%IPM.General.InstallContext).%Get(.tSC) - $$$ThrowOnError(tSC) - set tSC = $$$OK set orderedResourceList = ..GetOrderedResourceList() set tKey = "" @@ -1309,10 +1250,6 @@ Method %OnValidateObject() As %Status [ Private, ServerOnly = 1 ] if $$$ISERR(tSC) { quit } - if tInstallContext.ModuleIsPending(tOtherResource.Module.Name) { - // %OnAddToSaveSet will correct for this condition. - continue - } if (tResource.Name = tResource.UniqueName) { // Common case: classes, packages, include files, etc. set tMsg = $$$FormatText("Resource '%1' is already defined as part of module '%2'; cannot also be listed in module '%3'",tResource.Name,tOtherResource.Module.Name,..Name) @@ -1372,33 +1309,6 @@ Method %OnAddToSaveSet( set ..Hash = tHash set ..LastModifiedTimestamp = $zdatetime($horolog,3) } - - // Deal with resources moving from a module dependent on the current module that hasn't been reloaded yet - set tInstallContext = ##class(%IPM.General.InstallContext).%Get(.tSC) - $$$ThrowOnError(tSC) - - set tSC = $$$OK - set orderedResourceList = ..GetOrderedResourceList() - set tKey = "" - for { - set tResource = orderedResourceList.GetNext(.tKey) - quit:(tKey="") - - // If it hasn't been saved yet (to account for module renames)... - if (tResource.%Id() = "") && (tResource.UniqueName '= "") { - // ... see if some other resource exists with the same name. - if ##class(%IPM.Storage.ResourceReference).ResourceNameExists(tResource.UniqueName,.tResourceId) { - set tOtherResource = ##class(%IPM.Storage.ResourceReference).%OpenId(tResourceId,,.tSC) - $$$ThrowOnError(tSC) - - if tInstallContext.ModuleIsPending(tOtherResource.Module.Name) { - // Delete the resource. If the pending module still contains it, there will be an error when that module is loaded. - set tSC = ##class(%IPM.Storage.ResourceReference).%DeleteId(tResourceId) - $$$ThrowOnError(tSC) - } - } - } - } } catch e { set tSC = e.AsStatus() } diff --git a/src/cls/IPM/Utils/Module.cls b/src/cls/IPM/Utils/Module.cls index 4579de49..763ae404 100644 --- a/src/cls/IPM/Utils/Module.cls +++ b/src/cls/IPM/Utils/Module.cls @@ -20,212 +20,16 @@ ClassMethod CreateAndGetSSLConfig(ByRef pProperties) As %String return name } -/// Format of pDependencyGraph: -/// pDependencyGraph("module name") = $ListBuild(,,) -/// pDependencyGraph("module name"," ") = -ClassMethod LoadDependencies( - ByRef pDependencyGraph, - ByRef pParams, - pWorkQueue As %SYSTEM.WorkMgr) -{ - // Suspend the error count to avoid spurious messages about errors being detected in load/compile. - $$$SuspendErrorCount - set tSC = $$$OK - set tLocked = 0 - set tRestoreParams = 0 - try { - set initWorkQueueManager = '$data(pParams("Multicompile","CacheTempIndex"),tCacheTempIndex) || '$isobject($get(pWorkQueue)) - if initWorkQueueManager { - if '$isobject($get(pWorkQueue)) { - // There may be one at a higher stack level. - // Deal with dependencies here, and ensure that previous CacheTempIndex can be restored at the end. - merge tParamBackup = pParams - set tRestoreParams = 1 - } - - if ($get(pParams("Threads")) = 1) || ($tlevel > 0) { - set tNumWorkers = -1 // Disable multithreading. - } else { - set tNumWorkers = $get(pParams("Threads"),1) // Enable multicompile - } - - set pWorkQueue = ##class(%SYSTEM.WorkMgr).Initialize("/multicompile="_tNumWorkers,.tSC) - $$$ThrowOnError(tSC) - - set tModuleName = "" - for { - set tModuleName = $order(pDependencyGraph(tModuleName),1,tData) - quit:tModuleName="" - - // List modules to avoid duplicate loads. - set pParams("Multicompile","ModuleContext",tModuleName) = $listbuild("Activate") - - // Invert dependency graph, subscripts (,) - set tInvertedDependencyGraph(tModuleName) = $list(tData,2,*) - - set tDependentKey = "" - for { - set tDependentKey = $order(pDependencyGraph(tModuleName,tDependentKey)) - quit:tDependentKey="" - - set tInvertedDependencyGraph($piece(tDependentKey," "),tModuleName) = "" - } - } - - set tCacheTempIndex = $increment($$$ZPMTempLoadGraphRoot) - set pParams("Multicompile","CacheTempIndex") = tCacheTempIndex - kill $$$ZPMTempLoadGraph(tCacheTempIndex) - merge $$$ZPMTempLoadGraph(tCacheTempIndex) = tInvertedDependencyGraph - } else { - lock +$$$ZPMTempLoadGraph(tCacheTempIndex):$$$LockTimeout - if $test { - set tLocked = 1 - } else { - $$$ThrowStatus($$$ERROR($$$GeneralError,"Failed to obtain lock on dependency graph.")) - } - merge tInvertedDependencyGraph = $$$ZPMTempLoadGraph(tCacheTempIndex) - } - - // Queue load of modules without uninstalled dependencies. - set tModuleName = "" - for { - set tModuleName = $order(tInvertedDependencyGraph(tModuleName),1,tData) - quit:tModuleName="" - - // Check if ALL subnode modules have no server name in the top level node of those modules - // in the inverted dependency graph (which means they are already installed) - // ONLY want to check on the initial version of the graph because nodes are killed as modules are installed - if initWorkQueueManager { - set tHasUninstalledDependency = 0 - set tSubnode = "" - while 1 { - set tSubnode = $order(tInvertedDependencyGraph(tModuleName, tSubnode)) - if (tSubnode = "") { - quit - } - // Check if subnode exists. If it doesn't, then its already been installed because subnodes are killed - set tSubnodeServerName = $listget($get(tInvertedDependencyGraph(tSubnode)), 1) - if (tSubnodeServerName '= "") { - set tHasUninstalledDependency = 1 - quit - } - } - } else { - set tHasUninstalledDependency = ($data(tInvertedDependencyGraph(tModuleName)) >= 10) - } - // If no uninstalled dependencies remain... - if 'tHasUninstalledDependency { - set $listbuild(tServerName, tVersion, tDeployed, tPlatformVersion) = tData - zkill $$$ZPMTempLoadGraph(tCacheTempIndex,tModuleName) - - // Missing server name indicates that it's already present locally; nothing to do in that case. - if (tServerName '= "") { - if ($tlevel = 0) && ($get(pParams("Multicompile","Verbose"),$get(pParams("Verbose"),0))) { - write !,"Queuing module load: ",tModuleName," ",tVersion," @ ",tServerName - } - set tSC = pWorkQueue.QueueCallback( - "##class("_$classname()_").LoadModuleReference", - "##class("_$classname()_").LoadCompleted", - tServerName, tModuleName, tVersion, $get(tDeployed), $get(tPlatformVersion), .pParams, .pDependencyGraph) - $$$ThrowOnError(tSC) - } else { - // Remove this module from dependencies. - set tDependentKey = "" - for { - set tDependentKey = $order($$$ZPMTempLoadGraph(tCacheTempIndex,tDependentKey)) - quit:tDependentKey="" - - kill $$$ZPMTempLoadGraph(tCacheTempIndex,tDependentKey,tModuleName) - } - } - } - } - if (tLocked) { - lock -$$$ZPMTempLoadGraph(tCacheTempIndex) - set tLocked = 0 - } else { - // Only call WaitForComplete once (!!!) - // Recursive calls will do repeat execution of previously-queued jobs. - set tSC = pWorkQueue.WaitForComplete() - $$$ThrowOnError(tSC) - } - - merge $$$ZPMHandledModules($namespace) = pParams("Multicompile","ModuleContext") - } catch e { - if (e.Name["ZSOAP") { - set tSC = $get(%objlasterror,e.AsStatus()) - } else { - set tSC = e.AsStatus() - } - } - if tRestoreParams { - kill pParams - merge pParams = tParamBackup - } - if (tLocked) { - lock -$$$ZPMTempLoadGraph(tCacheTempIndex) - } - quit tSC -} - -/// Intended to be invoked only as a work queue callback (so %status and %workqueue will be defined) -/// Signature must match LoadModuleReference per work queue manager conventions. -ClassMethod LoadCompleted( - pServerName As %String, - pModuleName As %String, - pVersion As %String, - pDeployed As %String, - pPlatformVersion As %String, - ByRef pParams, - ByRef pDependencyGraph) As %Status -{ - // Suspend the error count to avoid spurious messages about errors being detected in load/compile. - $$$SuspendErrorCount - set tSC = $$$OK - set tLocked = 0 - try { - $$$ThrowOnError(%status) - if $$$ISOK(tSC) && $data(pParams("Multicompile","CacheTempIndex"),tCacheTempIndex) { - // Remove loaded dependency from dependencies subscript. - lock +$$$ZPMTempLoadGraph(tCacheTempIndex):$$$LockTimeout - if $test { - set tLocked = 1 - } else { - $$$ThrowStatus($$$ERROR($$$GeneralError,"Failed to obtain lock on dependency graph.")) - } - set tDependentKey = "" - for { - set tDependentKey = $order($$$ZPMTempLoadGraph(tCacheTempIndex,tDependentKey)) - quit:tDependentKey="" - - kill $$$ZPMTempLoadGraph(tCacheTempIndex,tDependentKey,pModuleName) - } - lock -$$$ZPMTempLoadGraph(tCacheTempIndex) - set tLocked = 0 - - // Schedule load of any other modules that may need to be scheduled. - set tSC = ..LoadDependencies(.pDependencyGraph,.pParams,%workqueue) - } - } catch e { - set tSC = e.AsStatus() - } - if (tLocked) { - lock -$$$ZPMTempLoadGraph(tCacheTempIndex) - } - quit tSC -} - ClassMethod LoadQualifiedReference( pReference As %IPM.Storage.QualifiedModuleInfo, ByRef pParams, - ByRef pDependencyGraph, - pSynchronous As %Boolean = 0) As %Status + ByRef pDependencyGraph) As %Status { set tSC = $$$OK try { #dim tReference As %IPM.Storage.QualifiedModuleInfo set tReference = pReference.%ConstructClone() - set tSC = ..LoadModuleReference(tReference.ServerName, tReference.Name, tReference.VersionString, tReference.Deployed, tReference.PlatformVersion, .pParams, .pDependencyGraph, pSynchronous) + set tSC = ..LoadModuleReference(tReference.ServerName, tReference.Name, tReference.VersionString, tReference.Deployed, tReference.PlatformVersion, .pParams, .pDependencyGraph) } catch e { set tSC = e.AsStatus() } @@ -239,14 +43,11 @@ ClassMethod LoadModuleReference( pDeployed As %Boolean, pPlatformVersion As %String, ByRef pParams, - ByRef pDependencyGraph, - pSynchronous As %Boolean = 0) As %Status + ByRef pDependencyGraph) As %Status { // Keep a reference of the singleton in this process (which can be a new process!), so subsequent .%Get() calls return the same instance set configReference = ##class(%IPM.General.EnvironmentConfig).%Get() - // Suspend the error count to avoid spurious messages about errors being detected in load/compile. - $$$SuspendErrorCount #dim tExpression As %IPM.General.SemanticVersionExpression set tSC = $$$OK try { @@ -263,23 +64,11 @@ ClassMethod LoadModuleReference( merge qstruct = pParams("qstruct") } - // Use % variables that intentionally leak in worker processes, to avoid duplicate work when they go out of scope. - #dim %installcontext As %IPM.General.InstallContext - #dim %manager As %IPM.Repo.Manager - if '$$$IsISCWorker { - new %installcontext - new %manager - } - set %installcontext = ##class(%IPM.General.InstallContext).%Get(.tSC) - $$$ThrowOnError(tSC) - do %installcontext.SetGraph(.pDependencyGraph) - merge tIndex = pParams("Multicompile","CacheTempIndex") - do %installcontext.SetCacheTempIndex(.tIndex) - - set %manager = $select($isobject($get(%manager)):%manager,1:##class(%IPM.Repo.Manager).%Get(.tSC)) + #dim manager As %IPM.Repo.Manager + set manager = ##class(%IPM.Repo.Manager).%Get(.tSC) $$$ThrowOnError(tSC) - set tClient = %manager.CheckServiceCache(pServerName,.tAvailable) + set tClient = manager.CheckServiceCache(pServerName,.tAvailable) if 'tAvailable { set tSC = $$$ERROR($$$GeneralError,$$$FormatText("Repository '%1' is unavailable.",pServerName)) quit @@ -313,7 +102,7 @@ ClassMethod LoadModuleReference( // Ensure requested versions match those required by other modules in the namespace, excluding versions currently being installed // (the requirements of such modules are already known to be satisfied) - set tSC = ..GetRequiredVersionExpression(pModuleName,%installcontext.GetPendingModuleList(),.tExpression,.tSourceList) + set tSC = ..GetRequiredVersionExpression(pModuleName,,.tExpression,.tSourceList) if $$$ISERR(tSC) { quit } @@ -334,7 +123,7 @@ ClassMethod LoadModuleReference( } set dotModules = ##class(%File).NormalizeDirectory(".modules", tDirectory) set tmpRepoMgr = ##class(%IPM.General.TempLocalRepoManager).%New(dotModules, 0) - set tSC = ..LoadModuleFromDirectory(tDirectory,.pParams,tDeveloperMode,pServerName,pSynchronous) + set tSC = ..LoadModuleFromDirectory(tDirectory,.pParams,tDeveloperMode,pServerName) set tSC = $$$ADDSC(tSC, tmpRepoMgr.CleanUp()) } else { set tAsArchive = -1 @@ -368,7 +157,7 @@ ClassMethod LoadModuleReference( do tTmpStream.CopyFromAndSave(tPayload) if (tAsArchive) { - set tSC = ..LoadModuleFromArchive(tModRef.Name,tModRef.VersionString,tTmpStream,.pParams, pServerName,pSynchronous) + set tSC = ..LoadModuleFromArchive(tModRef.Name,tModRef.VersionString,tTmpStream,.pParams, pServerName) } else { // Old format (TODO: officially deprecate): try loading a .xml file @@ -410,8 +199,7 @@ ClassMethod LoadModuleFromArchive( pModuleVersion As %String, pArchiveStream As %Stream.Object, ByRef pParams, - pRepository As %String = "", - pSynchronous As %Boolean = 0) As %Status + pRepository As %String = "") As %Status { set tSC = $$$OK try { @@ -442,7 +230,7 @@ ClassMethod LoadModuleFromArchive( set dotModules = ##class(%File).NormalizeDirectory(".modules", tTargetDirectory) set tmpRepoMgr = ##class(%IPM.General.TempLocalRepoManager).%New(dotModules, 0) - set tSC = ..LoadModuleFromDirectory(tTargetDirectory, .pParams, , pRepository,pSynchronous) + set tSC = ..LoadModuleFromDirectory(tTargetDirectory, .pParams, , pRepository) set tSC = $$$ADDSC(tSC, tmpRepoMgr.CleanUp()) if $$$ISERR(tSC) { quit @@ -464,8 +252,7 @@ ClassMethod LoadModuleFromDirectory( pDirectory As %String, ByRef pParams, pOverrideDeveloperMode As %Boolean = 0, - pRepository As %String = "", - pSynchronous As %Boolean = 0) As %Status + pRepository As %String = "") As %Status { set tSC = $$$OK try { @@ -493,7 +280,7 @@ ClassMethod LoadModuleFromDirectory( merge tParams("AngularArtifact") = pParams("AngularArtifact") merge tParams("EnvFiles") = pParams("EnvFiles") } - set tSC = ..LoadNewModule(pDirectory,.tParams,pRepository,pSynchronous) + set tSC = ..LoadNewModule(pDirectory,.tParams,pRepository) if $$$ISERR(tSC) { quit } @@ -1250,12 +1037,18 @@ ClassMethod ExportDocumentForObject( ClassMethod LoadNewModule( pDirectory As %String, ByRef pParams, - pRepository As %String = "", - pSynchronous As %Boolean = 0) As %Status + pRepository As %String = "") As %Status { set tSC = $$$OK set tInitTLevel = $tlevel try { + if ($get(pParams("Install"),0) || $get(pParams("Update",0))) { + // For top level installation, ensure we check license key. + set tLicenseIsValid = ..CheckLicenseKey() + if 'tLicenseIsValid { + write !,"WARNING: Continuing module load without a valid license." + } + } // check module.xml for defaults do ..GetModuleDefaultsFromXML(pDirectory, .defaults) merge params = defaults @@ -1267,15 +1060,6 @@ ClassMethod LoadNewModule( set qstruct = "ck"_$select(tVerbose:"d",1:"-d") } - // Check for valid license key prior to top-level module load - // This may throw an exception. - if '$data($$$ZPMHandledModules($namespace)) { - set tLicenseIsValid = ..CheckLicenseKey() - if 'tLicenseIsValid { - write !,"WARNING: Continuing module load without a valid license." - } - } - // Create a singleton instance for logging of warnings/error messages set tLogManager = ##class(%IPM.General.LogManager).%Get(.tSC) $$$ThrowOnError(tSC) @@ -1349,35 +1133,9 @@ ClassMethod LoadNewModule( tstart } - if '$data($$$ZPMHandledModules($namespace)) { - // The purpose of this NEW command is to make sure that the % variable $$$ZPMHandledModules refers to doesn't leak outside this scope. - // This only happens for the first module to be loaded in a set of dependencies (using zpm "load ..." or zpm "install ...") - // $$$ZPMHandledModules is also used in the ExecutePhases method of %IPM.Storage.Module to - // cover cases where new dependencies are added and a module is compiled without reloading, and in the BuildDependencyGraph - // method to treat installed snapshot versions as installed rather than forcing reload if they have been reloaded - // as part of the same root module operation. - new $$$ZPMHandledModules - set $$$ZPMHandledModules($namespace) = "" //Initialize. - } - merge $$$ZPMHandledModules($namespace) = params("Multicompile","ModuleContext") - $$$ThrowOnError(##class(%IPM.Storage.Module).CheckSystemRequirements(tModuleName)) - #dim tInstallContext As %IPM.General.InstallContext - set tInstallContext = ##class(%IPM.General.InstallContext).%Get(.tSC) - $$$ThrowOnError(tSC) - if 'tInstallContext.ModuleIsDependency(tModuleName) { - if 'pSynchronous { - // Regular async multi-threaded loading of dependencies - set tSC = tModule.LoadDependencies("",.params) - $$$ThrowOnError(tSC) - } else { - // Temporary custom loading of dependencies in a synchronous - // manner to prevent lock timeouts until lifecycle rework - // is complete (HSIEO-4450) - do ..SyncLoadDependencies(tModule, .params) - } - } + do ..LoadDependencies(tModule, .params) set tSC = $system.OBJ.Load(pDirectory_"module.xml",$select(tVerbose:"d",1:"-d"),,.tLoadedList) $$$ThrowOnError(tSC) @@ -1408,18 +1166,13 @@ ClassMethod LoadNewModule( quit tSC } -/// Temporary workaround to synchronously load dependencies. Can be removed once -/// HSIEO-4450 is complete. -ClassMethod SyncLoadDependencies( +/// Load dependencies of a module in a synchronous manner, one at a time, in the correct order. +ClassMethod LoadDependencies( pModule As %IPM.Storage.Module, ByRef pParams) { set isVerbose = $get(pParams("Verbose"),0) - /* - * Call to BuildDependencyGraph copied from %IPM.Storage.Module:LoadDependencies - */ - set reloadSnapshots = +$get(pParams("UpdateSnapshots")) set permitDowngrade = +$get(pParams("PermitDowngrade")) set ignoreInstalled = +$get(pParams("IgnoreInstalled")) @@ -1428,9 +1181,6 @@ ClassMethod SyncLoadDependencies( $$$ThrowOnError(sc) write "Done." - /* This setting is copied from %IPM.Main:Install */ - set pParams("Install") = 1 - do ..ConstructInvertedDependencyGraph(.depdendencyGraph, .invertedDependencyGraph) if isVerbose { write !, "Created inverted dependency graph from dependency graph" diff --git a/src/inc/IPM/Common.inc b/src/inc/IPM/Common.inc index 7c7d6ffa..649fca42 100644 --- a/src/inc/IPM/Common.inc +++ b/src/inc/IPM/Common.inc @@ -5,9 +5,6 @@ ROUTINE %IPM.Common [Type=INC] #; Helper for XML import of documents #define ZPMStudioDocumentModule %IPMStudioDocumentModule -#; Local % Variable to track modules already handled for a given end goal -#define ZPMHandledModules %IPMHandledModules - #; Local % Variable to indicate that ^Sources update trigger should not be run for modifications to individual resources #define ZPMDeferModifyResources %IPMDeferModifyResources @@ -38,8 +35,8 @@ ROUTINE %IPM.Common [Type=INC] #; Log levels #define ZPMLogTRACE 0 -#define ZPMLogINFO 1 -#define ZPMLogWARNING 2 +#define ZPMLogINFO 1 +#define ZPMLogWARNING 2 #define ZPMLogERROR 3 #; System method/special variable wrappers From 65382f408e729902cfeeafc8fc54be02d2745fd1 Mon Sep 17 00:00:00 2001 From: kiyer Date: Wed, 17 Sep 2025 10:23:12 -0400 Subject: [PATCH 3/7] Add unit test for paser and only include deprecated if relevant --- src/cls/IPM/CLI.cls | 6 +- tests/unit_tests/Test/PM/Unit/CLI.cls | 244 +++++++++++++------------- 2 files changed, 128 insertions(+), 122 deletions(-) diff --git a/src/cls/IPM/CLI.cls b/src/cls/IPM/CLI.cls index 06a487fa..6bcac4c9 100644 --- a/src/cls/IPM/CLI.cls +++ b/src/cls/IPM/CLI.cls @@ -658,7 +658,11 @@ ClassMethod %ParseCommandInput( if (tKey = "") { quit } - set pCommandInfo(tType,tKey,"deprecated") = $get(tCommandStructure(tCommandName,tType,tKey,"deprecated"),0) + // Only include deprecated subscript if command is deprecated + set tIsDeprecated = $get(tCommandStructure(tCommandName,tType,tKey,"deprecated"),0) + if tIsDeprecated { + set pCommandInfo(tType,tKey,"deprecated") = 1 + } } } } diff --git a/tests/unit_tests/Test/PM/Unit/CLI.cls b/tests/unit_tests/Test/PM/Unit/CLI.cls index c4d973ff..cd2daaa7 100644 --- a/tests/unit_tests/Test/PM/Unit/CLI.cls +++ b/tests/unit_tests/Test/PM/Unit/CLI.cls @@ -4,89 +4,91 @@ Class Test.PM.Unit.CLI Extends %UnitTest.TestCase Method TestParser() { - + // Test cases - Set tCommands($i(tCommands)) = "help -v repo" - Set tResults(tCommands)="help" - Set tResults(tCommands,"modifiers","verbose")="" - Set tResults(tCommands,"parameters","command")="repo" - - Set tCommands($i(tCommands)) = "repo -name UTFILE -fs -path ""C:\\Program Files\\stuff\\"" -depth 42" - Set tResults(tCommands)="repo" - Set tResults(tCommands,"modifiers","depth")=42 - Set tResults(tCommands,"modifiers","filesystem")="" - Set tResults(tCommands,"modifiers","name")="UTFILE" - Set tResults(tCommands,"modifiers","path")="C:\Program Files\stuff\" - - Set tCommands($i(tCommands)) = "ZPM activate -dev -DUIFW.force=1" + set tCommands($increment(tCommands)) = "help -v repo" + set tResults(tCommands)="help" + set tResults(tCommands,"modifiers","verbose")="" + set tResults(tCommands,"parameters","command")="repo" + + set tCommands($increment(tCommands)) = "repo -name UTFILE -fs -path ""C:\\Program Files\\stuff\\"" -depth 42" + set tResults(tCommands)="repo" + set tResults(tCommands,"modifiers","depth")=42 + set tResults(tCommands,"modifiers","filesystem")="" + set tResults(tCommands,"modifiers","name")="UTFILE" + set tResults(tCommands,"modifiers","path")="C:\Program Files\stuff\" + + set tCommands($increment(tCommands)) = "ZPM activate -dev -DUIFW.force=1" // Old behavior: /* Set tResults(tCommands)="module-action" Set tResults(tCommands,"parameters","actions")="activate -dev -DUIFW.force=1" Set tResults(tCommands,"parameters","module")="ZPM" */ - Set tResults(tCommands)="module-action" - Set tResults(tCommands,"parameters","actions")="activate" - Set tResults(tCommands,"parameters","module")="ZPM" - Set tResults(tCommands,"data","DeveloperMode")=1 - Set tResults(tCommands,"data","UIFW","force")=1 - - Set tCommands($i(tCommands)) = "ZPM clean install -dev -DUIFW.force=1 -DSomething=""quoted\"" value""" + set tResults(tCommands)="module-action" + set tResults(tCommands,"parameters","actions")="activate" + set tResults(tCommands,"parameters","module")="ZPM" + set tResults(tCommands,"data","DeveloperMode")=1 + set tResults(tCommands,"data","UIFW","force")=1 + + set tCommands($increment(tCommands)) = "ZPM clean install -dev -DUIFW.force=1 -DSomething=""quoted\"" value""" // Old behavior: /* Set tResults(tCommands)="module-action" Set tResults(tCommands,"parameters","actions")="clean install -dev -DUIFW.force=1 -DSomething=""quoted"" value""" Set tResults(tCommands,"parameters","module")="ZPM" */ - Set tResults(tCommands)="module-action" - Set tResults(tCommands,"parameters","actions")="clean install" - Set tResults(tCommands,"parameters","module")="ZPM" - Set tResults(tCommands,"data","DeveloperMode")=1 - Set tResults(tCommands,"data","UIFW","force")=1 - Set tResults(tCommands,"data","zpm","Something")="quoted"" value" - Set tResults(tCommands,"data","Something")="quoted"" value" - - Set tCommands($i(tCommands)) = "module-action isc-dev publish" - Set tResults(tCommands)="module-action" - Set tResults(tCommands,"parameters","actions")="publish" - Set tResults(tCommands,"parameters","module")="isc-dev" - - Set tCommands($i(tCommands)) = "list-installed -t" - Set tResults(tCommands)="list-installed" - Set tResults(tCommands,"modifiers","tree")="" - - Set tCommands($i(tCommands)) = "install SomeModule" - Set tResults(tCommands)="install" - Set tResults(tCommands,"parameters","module")="SomeModule" - - Set tCommands($i(tCommands)) = "install SomeModule 0.0.1-prerelease.42+snapshot" - Set tResults(tCommands)="install" - Set tResults(tCommands,"parameters","module")="SomeModule" - Set tResults(tCommands,"parameters","version")="0.0.1-prerelease.42+snapshot" - - Set tCommands($i(tCommands)) = "repo -r -n registry -url http://iris-test:52774/registry/ -user ""user"" -pass ""pass""" - Set tResults(tCommands)="repo" - Set tResults(tCommands,"modifiers","name")="registry" - Set tResults(tCommands,"modifiers","remote")="" - Set tResults(tCommands,"modifiers","url")="http://iris-test:52774/registry/" - Set tResults(tCommands,"modifiers","username")="user" - Set tResults(tCommands,"modifiers","password")="pass" - + set tResults(tCommands)="module-action" + set tResults(tCommands,"parameters","actions")="clean install" + set tResults(tCommands,"parameters","module")="ZPM" + set tResults(tCommands,"data","DeveloperMode")=1 + set tResults(tCommands,"data","UIFW","force")=1 + set tResults(tCommands,"data","zpm","Something")="quoted"" value" + set tResults(tCommands,"data","Something")="quoted"" value" + + set tCommands($increment(tCommands)) = "module-action isc-dev publish" + set tResults(tCommands)="module-action" + set tResults(tCommands,"parameters","actions")="publish" + set tResults(tCommands,"parameters","module")="isc-dev" + + set tCommands($increment(tCommands)) = "list-installed -t" + set tResults(tCommands)="list-installed" + set tResults(tCommands,"modifiers","tree")="" + + set tCommands($increment(tCommands)) = "install SomeModule -synchronous" + set tResults(tCommands)="install" + set tResults(tCommands,"parameters","module")="SomeModule" + set tResults(tCommands,"modifiers","synchronous")="" + set tResults(tCommands,"modifiers","synchronous","deprecated")=1 + + set tCommands($increment(tCommands)) = "install SomeModule 0.0.1-prerelease.42+snapshot" + set tResults(tCommands)="install" + set tResults(tCommands,"parameters","module")="SomeModule" + set tResults(tCommands,"parameters","version")="0.0.1-prerelease.42+snapshot" + + set tCommands($increment(tCommands)) = "repo -r -n registry -url http://iris-test:52774/registry/ -user ""user"" -pass ""pass""" + set tResults(tCommands)="repo" + set tResults(tCommands,"modifiers","name")="registry" + set tResults(tCommands,"modifiers","remote")="" + set tResults(tCommands,"modifiers","url")="http://iris-test:52774/registry/" + set tResults(tCommands,"modifiers","username")="user" + set tResults(tCommands,"modifiers","password")="pass" + /* - Set tCommands($i(tCommands)) = + Set tCommands($i(tCommands)) = Set tResults(tCommands)= Set tResults(tCommands, */ - + // Verify output matches - For i=1:1:tCommands { - Kill tParsedCommandInfo,tExpectedCommandInfo - Do $$$AssertStatusOK(##class(%IPM.Main).%ParseCommandInput(tCommands(i),.tParsedCommandInfo)) - Merge tExpectedCommandInfo = tResults(i) - If '$$$AssertTrue(..CompareArrays(.tParsedCommandInfo,.tExpectedCommandInfo,.tMessage),"Parsed correctly: "_tCommands(i)) { - Do $$$LogMessage(tMessage) - Write !,"Expected:",! zw tExpectedCommandInfo - Write !,"Actual:",! zw tParsedCommandInfo + for i=1:1:tCommands { + kill tParsedCommandInfo,tExpectedCommandInfo + do $$$AssertStatusOK(##class(%IPM.Main).%ParseCommandInput(tCommands(i),.tParsedCommandInfo)) + merge tExpectedCommandInfo = tResults(i) + if '$$$AssertTrue(..CompareArrays(.tParsedCommandInfo,.tExpectedCommandInfo,.tMessage),"Parsed correctly: "_tCommands(i)) { + do $$$LogMessage(tMessage) + write !,"Expected:",! zwrite tExpectedCommandInfo + write !,"Actual:",! zwrite tParsedCommandInfo } } } @@ -94,29 +96,29 @@ Method TestParser() Method TestRepository() { // Cleanup - Do ..RunCommand("repo -delete-all") - Do ..RunCommand("repo -list") - + do ..RunCommand("repo -delete-all") + do ..RunCommand("repo -list") + // Create repositories - Set tDir = ##class(%File).ManagerDirectory() - Do ##class(%Studio.General).GetWebServerPort(.tPort) - Set tUrl = "https://pm.community.intersystems.com/" - Do ..AssertNoException("repo -name UTFILE -fs -path "_tDir_" -depth 1") - Do ..AssertNoException("repo -n UTSERVER -r -url "_tUrl) - Do ..RunCommand("repo -list") - + set tDir = ##class(%File).ManagerDirectory() + do ##class(%Studio.General).GetWebServerPort(.tPort) + set tUrl = "https://pm.community.intersystems.com/" + do ..AssertNoException("repo -name UTFILE -fs -path "_tDir_" -depth 1") + do ..AssertNoException("repo -n UTSERVER -r -url "_tUrl) + do ..RunCommand("repo -list") + // Update repositories - Do ..AssertNoException("repo -n UTFILE -fs -snapshots 0") - Do ..AssertNoException("repo -name UTSERVER -r -prereleases 0 -url http://registry/") - Do ..AssertNoException("repo -name TEST -r -prereleases 0 -url http://newregistry/ -publish 1") - Do ..RunCommand("repo -list") - + do ..AssertNoException("repo -n UTFILE -fs -snapshots 0") + do ..AssertNoException("repo -name UTSERVER -r -prereleases 0 -url http://registry/") + do ..AssertNoException("repo -name TEST -r -prereleases 0 -url http://newregistry/ -publish 1") + do ..RunCommand("repo -list") + // Cleanup (again) - Do ..RunCommand("repo -n UTFILE -delete") - Do ..RunCommand("repo -name UTSERVER -delete") - Do ..RunCommand("repo -name TEST -delete") + do ..RunCommand("repo -n UTFILE -delete") + do ..RunCommand("repo -name UTSERVER -delete") + do ..RunCommand("repo -name TEST -delete") - Do ..RunCommand("repo -r -name registry -reset-defaults") + do ..RunCommand("repo -r -name registry -reset-defaults") } Method TestModifiers() @@ -139,24 +141,24 @@ Method CompareModifiers( do ##class(%IPM.Main).%ParseCommandInput(module_" "_phase_" "+commandModifiers,.info1) do ##class(%IPM.Main).%ParseCommandInput(phase_" "_module_" "+commandModifiers,.info2) - If '$$$AssertTrue(..CompareArrays(.info1,.info2,.tMessage),"module-action and lifecycle phase allow for same modifiers") { - Do $$$LogMessage(tMessage) - Write !,"module-action accepted modifiers:",! zw info1 - Write !,phase_" accepted modifiers:",! zw info2 + if '$$$AssertTrue(..CompareArrays(.info1,.info2,.tMessage),"module-action and lifecycle phase allow for same modifiers") { + do $$$LogMessage(tMessage) + write !,"module-action accepted modifiers:",! zwrite info1 + write !,phase_" accepted modifiers:",! zwrite info2 } } Method RunCommand(pCommand As %String) { - Do ##class(%IPM.Main).Shell(pCommand) - Do $$$LogMessage("Run command: "_pCommand) + do ##class(%IPM.Main).Shell(pCommand) + do $$$LogMessage("Run command: "_pCommand) } Method AssertNoException(pCommand As %String) { - Do ##class(%IPM.Main).ShellInternal(pCommand,.tException) - If '$$$AssertEquals(tException,"","No exceptions occurred running command: "_pCommand) { - Do $$$LogMessage(tException.DisplayString()) + do ##class(%IPM.Main).ShellInternal(pCommand,.tException) + if '$$$AssertEquals(tException,"","No exceptions occurred running command: "_pCommand) { + do $$$LogMessage(tException.DisplayString()) } } @@ -171,47 +173,47 @@ Method CompareArrays( ByRef second, Output pMessage) As %Boolean [ PublicList = (tRef1, tRef2, first, second) ] { - New tRef1,tRef2 - Set pMessage = "" - Set tEqual = 1 - Set tRef1 = "first" - Set tRef2 = "second" - While (tRef1 '= "") || (tRef2 '= "") { + new tRef1,tRef2 + set pMessage = "" + set tEqual = 1 + set tRef1 = "first" + set tRef2 = "second" + while (tRef1 '= "") || (tRef2 '= "") { #; See if the subscript is the same for both arrays. #; If not, one of them has a subscript the other doesn't, and they're not equal. - If ($Piece(tRef1,"first",2) '= $Piece(tRef2,"second",2)) { - Set tEqual = 0 - Set pMessage = "Different subscripts encountered by $Query: "_ - $Case(tRef1,"":"",:tRef1)_"; "_$Case(tRef2,"":"",:tRef2) - Quit + if ($piece(tRef1,"first",2) '= $piece(tRef2,"second",2)) { + set tEqual = 0 + set pMessage = "Different subscripts encountered by $Query: "_ + $case(tRef1,"":"",:tRef1)_"; "_$case(tRef2,"":"",:tRef2) + quit } - - Kill tRef1Value,tRef2Value - Set tRef1Data = $Data(@tRef1,tRef1Value) - Set tRef2Data = $Data(@tRef2,tRef2Value) + + kill tRef1Value,tRef2Value + set tRef1Data = $data(@tRef1,tRef1Value) + set tRef2Data = $data(@tRef2,tRef2Value) #; See if the $Data values are the same for the two. #; This is really only useful to detect if one of the arrays is undefined on the first pass; #; $Query only returns subscripts with data. #; This will catch only one being defined, or one being an array and #; ​the other being a regular variable. - If (tRef1Data '= tRef2Data) { - Set tEqual = 0 - Set pMessage = "$Data("_tRef1_")="_tRef1Data_"; $Data("_tRef2_")="_tRef2Data - Quit - } ElseIf (tRef1Data#2) && (tRef2Data#2) { + if (tRef1Data '= tRef2Data) { + set tEqual = 0 + set pMessage = "$Data("_tRef1_")="_tRef1Data_"; $Data("_tRef2_")="_tRef2Data + quit + } elseif (tRef1Data#2) && (tRef2Data#2) { #; See if the value at the subscript is the same for both arrays. #; If not, they're not equal. - If (tRef1Value '= tRef2Value) { - Set tEqual = 0 - Set pMessage = tRef1_"="_@tRef1_"; "_tRef2_"="_@tRef2 - Quit + if (tRef1Value '= tRef2Value) { + set tEqual = 0 + set pMessage = tRef1_"="_@tRef1_"; "_tRef2_"="_@tRef2 + quit } } - - Set tRef1 = $Query(@tRef1) - Set tRef2 = $Query(@tRef2) + + set tRef1 = $query(@tRef1) + set tRef2 = $query(@tRef2) } - Quit tEqual + quit tEqual } } From 9c78274611177e8ae2a32ced6072bdbb3a905caf Mon Sep 17 00:00:00 2001 From: kiyer Date: Tue, 21 Oct 2025 17:46:00 -0400 Subject: [PATCH 4/7] Remove missed InstallContext refs --- src/cls/IPM/Utils/Module.cls | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cls/IPM/Utils/Module.cls b/src/cls/IPM/Utils/Module.cls index b4f6fa03..b2041055 100644 --- a/src/cls/IPM/Utils/Module.cls +++ b/src/cls/IPM/Utils/Module.cls @@ -1113,11 +1113,7 @@ ClassMethod LoadNewModule( set tDisplayName = $piece(tFirstLoaded, ".", 1, *-1) set tModuleName = $$$lcase(tDisplayName) - #dim tInstallContext As %IPM.General.InstallContext - set tInstallContext = ##class(%IPM.General.InstallContext).%Get(.tSC) - $$$ThrowOnError(tSC) - - if foundNewModuleObj && 'tInstallContext.ModuleIsDependency(tModuleName) { + if foundNewModuleObj { // Check that on an update command with -path flag, the module in the path matches the base module specified for update. if (commandLineModuleName '= "") && (newModuleObj.Name '= commandLineModuleName) { set msg = $$$FormatText("The specified path does not contain a module matching the specified module to update. Module in path = %1. Specified module = %2.",newModuleObj.Name,commandLineModuleName) From 40b6112c032a64aa9a45563663a04a7694a4a701 Mon Sep 17 00:00:00 2001 From: kiyer Date: Wed, 22 Oct 2025 09:50:25 -0400 Subject: [PATCH 5/7] Update changelog, remove $$$IsISCWorker references that are no longer valid. Remove command line module name from dependency loads (only needed for initial check when running load/update) --- CHANGELOG.md | 19 +++++++++++++++++++ src/cls/IPM/Lifecycle/Base.cls | 7 ------- src/cls/IPM/Repo/Filesystem/Definition.cls | 8 ++------ src/cls/IPM/Storage/Module.cls | 1 - src/cls/IPM/Utils/Module.cls | 5 +++-- .../Test/PM/Integration/Update.cls | 3 +++ 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba6c7705..91c42f8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.10.5] - Unreleased + +### Added + +### Changed +- #885: Always synchronously load dependencies and let each module do multi-threading as needed +to load using multicompile instead of trying to do own multi-threading of item load which causes +lock contention by bypassing IRIS compiler. + +### Deprecated +- #885: `-synchronous` flag since loading dependencies synchronously is now the default behavior. + +### Removed + +### Fixed + +### Security + + ## [0.10.4] - 2025-10-21 ### Added diff --git a/src/cls/IPM/Lifecycle/Base.cls b/src/cls/IPM/Lifecycle/Base.cls index 81483627..a0f3137c 100644 --- a/src/cls/IPM/Lifecycle/Base.cls +++ b/src/cls/IPM/Lifecycle/Base.cls @@ -1014,13 +1014,6 @@ Method %Compile(ByRef pParams) As %Status } set tNoCompileLock = '$get(pParams("NoLock")) - if $$$IsISCWorker && 'tNoCompileLock { - // Customized locking - takes out shared locks on dependencies to avoid conflicts between parallel module loads. - set tSC = ##class(%IPM.Utils.LockManager).LockClassesRecursive(.tLockManager,.tCompileArray,.tLockedClasses) - $$$ThrowOnError(tSC) - set tNoCompileLock = 1 - } - // Actually do the compile if $data(tCompileArray)>1 { set tCompiledSomething = 1 diff --git a/src/cls/IPM/Repo/Filesystem/Definition.cls b/src/cls/IPM/Repo/Filesystem/Definition.cls index 49d3b7dc..b99b7d67 100644 --- a/src/cls/IPM/Repo/Filesystem/Definition.cls +++ b/src/cls/IPM/Repo/Filesystem/Definition.cls @@ -51,11 +51,7 @@ Method RootSet(%val) As %Status /// Returns a client to interact with this server. Method GetPackageService() As %IPM.Repo.IPackageService { - set tService = ##class(%IPM.Repo.Filesystem.PackageService).%New(..Root) - if '$$$IsISCWorker && tService.IsAvailable() { - $$$ThrowOnError(..BuildCache()) - } - quit tService + return ##class(%IPM.Repo.Filesystem.PackageService).%New(..Root) } /// Handles modifiers/data attributes provided from the package manager shell. @@ -119,7 +115,7 @@ Trigger RootChanged [ Event = UPDATE, Foreach = row/object ] } Method BuildCache( - pPurge As %Boolean = {'$$$IsISCWorker}, + pPurge As %Boolean = 1, pVerbose As %Integer = 0, pAutoDetectDepth As %Boolean = 0) As %Status { diff --git a/src/cls/IPM/Storage/Module.cls b/src/cls/IPM/Storage/Module.cls index 9d081514..d271279c 100644 --- a/src/cls/IPM/Storage/Module.cls +++ b/src/cls/IPM/Storage/Module.cls @@ -1214,7 +1214,6 @@ ClassMethod GetKnownDependencies(pModuleName As %String) As %List /// @Argument pReferenceArray Array of all module's resources (including resources that compose a resource) that contain the appropriate phase scope.
/// @Argument pLockedDependencies Whether method should be recursively applied to the module's dependencies (true = yes).
/// @Argument pPhases List of IPM lifecycle phases to be applied to the current module.
-/// @Argument pSkipDependencies Whether to skip loading uninstalled dependency modules.
/// @Argument pDependencyGraph Tree of module's dependencies.
Method GetResolvedReferences( Output pReferenceArray, diff --git a/src/cls/IPM/Utils/Module.cls b/src/cls/IPM/Utils/Module.cls index b2041055..d3abef37 100644 --- a/src/cls/IPM/Utils/Module.cls +++ b/src/cls/IPM/Utils/Module.cls @@ -916,7 +916,7 @@ ClassMethod GetModuleNameFromXML( /// 1 /// /// ``` -/// +/// /// Returns results as multidimensional array ClassMethod GetModuleDefaultsFromXML( pDirectory As %String, @@ -1160,6 +1160,7 @@ ClassMethod LoadNewModule( $$$ThrowOnError(##class(%IPM.Storage.Module).CheckSystemRequirements(tModuleName)) + kill params("ModuleName") // Ensure module name is not passed down to dependency loads do ..LoadDependencies(tModule, .params) set tSC = $system.OBJ.Load(pDirectory_"module.xml",$select(tVerbose:"d",1:"-d"),,.tLoadedList) @@ -1308,7 +1309,7 @@ ClassMethod CheckLicenseKey() As %Boolean // Limit the number of attempts in case this somehow ends up running in a non-interactive process. #define MaxTries 5 set tValidLicense = ($system.License.GetKeyStatus() '= "Invalid") - while ('tValidLicense) && $$$InProgrammerMode && ('$$$IsISCWorker) && ($increment(tTries) <= $$$MaxTries) { + while ('tValidLicense) && $$$InProgrammerMode && ($increment(tTries) <= $$$MaxTries) { write !!,"Your system has no (valid) license key present" write !,"Copy a valid license key into "_$system.Util.ManagerDirectory() write !,"and then enter 'y' to activate it. Enter 'n' to continue without a license key, " diff --git a/tests/integration_tests/Test/PM/Integration/Update.cls b/tests/integration_tests/Test/PM/Integration/Update.cls index 7df68f60..ded93493 100644 --- a/tests/integration_tests/Test/PM/Integration/Update.cls +++ b/tests/integration_tests/Test/PM/Integration/Update.cls @@ -46,6 +46,7 @@ Method OnBeforeAllTests() As %Status Method TestAllNoErrorModulesNoMirror() { if $system.Mirror.IsMember() { + do $$$AssertSkipped("Skipping test since this is a mirror member") return } // Simple module without dependencies @@ -57,6 +58,7 @@ Method TestAllNoErrorModulesNoMirror() set updateStepsToSeed = updateStepsToSeed.addAll([["UpdateDeps.UpdatePackage.V1", "MethodA", 0]]) set updateStepsToRun = updateStepsToRun.addAll([["UpdateDeps.UpdatePackage.V1", "MethodB", 1], ["UpdateDeps.UpdatePackage.V1", "MethodC", 1], ["UpdateDeps.UpdatePackage.V2", "MethodA", 1], ["UpdateDeps.UpdatePackage.V2", "MethodC", 1], ["UpdateDeps.UpdatePackage.V2", "MethodB", 0]]) do ..NormalUpdateTestSuite(..#ModuleWithDependencies, updateStepsToSeed, updateStepsToRun, ..#ModuleOneVersion, ..#ModuleTwoVersion) + break // Module with dependencies added in new version set updateStepsToSeed = [["UpdateDepsAdded.UpdatePackage.V1", "MethodA", 1]] @@ -79,6 +81,7 @@ Method TestAllNoErrorModulesNoMirror() set updateStepsToRun = [["UpdateSeededStepErrors.UpdatePackage.V2", "MethodA", 1]] do ..SingleNormalUpdateTest(..#ModuleSeededStepErrors, updateStepsToSeed, updateStepsToRun, ..#ModuleOneVersion, ..#ModuleTwoVersion, 0) do ..CleanUp() + break } Method TestAllErrorModulesNoMirror() From a18535e69370d5eaf8af313539696317184e83a5 Mon Sep 17 00:00:00 2001 From: kiyer Date: Wed, 22 Oct 2025 10:00:29 -0400 Subject: [PATCH 6/7] Update module version --- module.xml | 92 +++++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/module.xml b/module.xml index defbb43f..e6153cca 100644 --- a/module.xml +++ b/module.xml @@ -1,49 +1,57 @@ - - ZPM - 0.10.4-SNAPSHOT - IPM - InterSystems Package Manager (IPM) provides development tools and infrastructure for defining, building, distributing, and installing modules and applications. - Package Manager - - InterSystems Corporation - - module - src - - - - - - - - - - - - ${verbose} - + + + ZPM + 0.10.5-SNAPSHOT + IPM + InterSystems Package Manager (IPM) provides development tools and + infrastructure for defining, building, distributing, and installing modules and + applications. + Package Manager + + InterSystems Corporation + + module + src + + + + + + + + + + + + ${verbose} + - - + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + +
+ + \ No newline at end of file From e896271b4550162a33a993274431d7ce4aec64d6 Mon Sep 17 00:00:00 2001 From: kiyer Date: Wed, 22 Oct 2025 10:11:40 -0400 Subject: [PATCH 7/7] remove debug breaks --- tests/integration_tests/Test/PM/Integration/Update.cls | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/integration_tests/Test/PM/Integration/Update.cls b/tests/integration_tests/Test/PM/Integration/Update.cls index ded93493..513c2a34 100644 --- a/tests/integration_tests/Test/PM/Integration/Update.cls +++ b/tests/integration_tests/Test/PM/Integration/Update.cls @@ -58,7 +58,6 @@ Method TestAllNoErrorModulesNoMirror() set updateStepsToSeed = updateStepsToSeed.addAll([["UpdateDeps.UpdatePackage.V1", "MethodA", 0]]) set updateStepsToRun = updateStepsToRun.addAll([["UpdateDeps.UpdatePackage.V1", "MethodB", 1], ["UpdateDeps.UpdatePackage.V1", "MethodC", 1], ["UpdateDeps.UpdatePackage.V2", "MethodA", 1], ["UpdateDeps.UpdatePackage.V2", "MethodC", 1], ["UpdateDeps.UpdatePackage.V2", "MethodB", 0]]) do ..NormalUpdateTestSuite(..#ModuleWithDependencies, updateStepsToSeed, updateStepsToRun, ..#ModuleOneVersion, ..#ModuleTwoVersion) - break // Module with dependencies added in new version set updateStepsToSeed = [["UpdateDepsAdded.UpdatePackage.V1", "MethodA", 1]] @@ -81,7 +80,6 @@ Method TestAllNoErrorModulesNoMirror() set updateStepsToRun = [["UpdateSeededStepErrors.UpdatePackage.V2", "MethodA", 1]] do ..SingleNormalUpdateTest(..#ModuleSeededStepErrors, updateStepsToSeed, updateStepsToRun, ..#ModuleOneVersion, ..#ModuleTwoVersion, 0) do ..CleanUp() - break } Method TestAllErrorModulesNoMirror()