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 @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- #959: In ORAS repos, external name can now be used interchangeably with (default) name for `install` and `update`, i.e. a module published with its (default) name can be installed using its external name.
- #951: The `unpublish` command will skip user confirmation prompt if the `-force` flag is provided.
- #1018: Require module name for uninstall when not using the -all flag
- #1027: Add -bypass-deps flag to skip install the IPM dependencies

### Changed
- #316: All parameters, except developer mode, included with a `load`, `install` or `update` command will be propagated to dependencies
Expand Down
9 changes: 6 additions & 3 deletions src/cls/IPM/Main.cls
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ load C:\module\root\path -env C:\path\to\env1.json;C:\path\to\env2.json
<modifier name="nodev" dataAlias="DeveloperMode" dataValue="0" description="Disables the DeveloperMode flag for the module's lifecycle." />
<modifier name="quiet" aliases="q" dataAlias="Verbose" dataValue="0" description="Produces minimal output from the command." />
<modifier name="verbose" aliases="v" dataAlias="Verbose" dataValue="1" description="Produces verbose output from the command." />
<modifier name="bypass-py-deps" dataAlias="BypassPyDeps" dataValue="1" description="Skip installing python dependencies" />
<modifier name="bypass-py-deps" aliases="bpd" dataAlias="BypassPyDeps" dataValue="1" description="Skip installing python dependencies" />
<modifier name="bypass-deps" aliases="bd" dataAlias="BypassDeps" dataValue="1" description="Skip installing IPM dependencies" />
<modifier name="extra-pip-flags" dataAlias="ExtraPipFlags" value="true" description="Extra flags to pass to pip when installing python dependencies. Surround the flags (and values) with quotes if spaces are present. Default flags are &quot;--target &lt;target&gt; --python-version &lt;pyversion&gt; --only-binary=:all:&quot;." />
<modifier name="synchronous" value="false" deprecated="true" description="DEPRECATED. Dependencies are now always loaded synchronously with independent lifecycle phases doing their own multi-threading as needed." />
<modifier name="force" aliases="f" value="false" description="Allows the user to load a newer version of an existing module without running update steps." />
Expand Down Expand Up @@ -414,7 +415,8 @@ install -env /path/to/env1.json;/path/to/env2.json example-package
<modifier name="quiet" aliases="q" dataAlias="Verbose" dataValue="0" description="Produces minimal output from the command." />
<modifier name="verbose" aliases="v" dataAlias="Verbose" dataValue="1" description="Produces verbose output from the command." />
<modifier name="keywords" aliases="k" value="true" description="Searches for modules matching some set of keywords." />
<modifier name="bypass-py-deps" dataAlias="BypassPyDeps" dataValue="1" description="Skip installing python dependencies" />
<modifier name="bypass-py-deps" aliases="bpd" dataAlias="BypassPyDeps" dataValue="1" description="Skip installing python dependencies" />
<modifier name="bypass-deps" aliases="bd" dataAlias="BypassDeps" dataValue="1" description="Skip installing IPM dependencies" />
<modifier name="extra-pip-flags" dataAlias="ExtraPipFlags" value="true" description="Extra flags to pass to pip when installing python dependencies. Surround the flags (and values) with quotes if spaces are present. Default flags are &quot;--target &lt;target&gt; --python-version &lt;pyversion&gt; --only-binary=:all:&quot;."/>
<modifier name="synchronous" value="false" deprecated="true" description="DEPRECATED. Dependencies are now always loaded synchronously with independent lifecycle phases doing their own multi-threading as needed." />
<modifier name="force" aliases="f" value="false" description="Allows the user to install a newer version of an existing module without running update steps." />
Expand Down Expand Up @@ -452,7 +454,8 @@ reinstall -env /path/to/env1.json;/path/to/env2.json example-package
<modifier name="quiet" aliases="q" dataAlias="Verbose" dataValue="0" description="Produces minimal output from the command." />
<modifier name="verbose" aliases="v" dataAlias="Verbose" dataValue="1" description="Produces verbose output from the command." />
<modifier name="shallow" aliases="s" dataAlias="UpdateSnapshots" dataValue="0" description="Suppresses updating of dependencies with '+snapshot' versions." />
<modifier name="bypass-py-deps" dataAlias="BypassPyDeps" dataValue="1" description="Skip installing python dependencies" />
<modifier name="bypass-py-deps" aliases="bpd" dataAlias="BypassPyDeps" dataValue="1" description="Skip installing python dependencies" />
<modifier name="bypass-deps" aliases="bd" dataAlias="BypassDeps" dataValue="1" description="Skip installing IPM dependencies" />
<modifier name="extra-pip-flags" dataAlias="ExtraPipFlags" value="true" description="Extra flags to pass to pip when installing python dependencies. Surround the flags (and values) with quotes if spaces are present. Default flags are &quot;--target &lt;target&gt; --python-version &lt;pyversion&gt; --only-binary=:all:&quot;."/>

</command>
Expand Down
8 changes: 7 additions & 1 deletion src/cls/IPM/Utils/Module.cls
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,13 @@ ClassMethod LoadNewModule(
if $get(params("CreateLockFile"), 0) && '$data(params("LockFileModule")){
set params("LockFileModule") = tModule.Name
}
do ..LoadDependencies(tModule, .params)
if $get(params("BypassDeps")) {
if tVerbose {
write !, $$$FormattedLine($$$Yellow,"Skipping installation of IPM dependencies because -bypass-deps is set.")
}
} else {
do ..LoadDependencies(tModule, .params)
}

set tSC = $system.OBJ.Load(pDirectory_"module.xml",$select(tVerbose:"d",1:"-d"),,.tLoadedList)
$$$ThrowOnError(tSC)
Expand Down
66 changes: 66 additions & 0 deletions tests/unit_tests/Test/PM/Unit/CLI.cls
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,72 @@ Method TestListPython() As %Status
quit sc
}

/// Verifies the behavior of the -bypass-deps (and alias -bd) flag during the load and install process.
/// Ensures that the primary module is loaded but the dependency resolution graph is skipped.
Method TestByPassIPMDepsModifier()
{
set testRoot = ##class(%File).NormalizeDirectory($get(^UnitTestRoot))
set dependencyModules = $listbuild("objectscript-math","LocalizationLab","irisjwt")

set ptr = 0
while $listnext(dependencyModules,ptr,module) {
set exists = ##class(%IPM.Storage.Module).NameExists(module)
if exists{
do $$$AssertTrue(exists, module_" is already installed. So uninstalling for testing -bypass-deps.")
set status = ##class(%IPM.Main).Shell("uninstall "_module)
do $$$AssertStatusOK(status,"Uninstalled module: "_module)
}
}
set moduleStr="<?xml version=""1.0"" encoding=""UTF-8""?><Export generator=""Cache"" version=""25"">"_
"<Document name=""demo-module1.ZPM""><Module><Name>demo-module1</Name><Version>1.0.0</Version>"_
"<Description>description</Description><Dependencies><ModuleReference>"_
"<Name>objectscript-math</Name><Version>0.0.5</Version></ModuleReference><ModuleReference><Name>LocalizationLab</Name><Version>1.0.0</Version>"_
"</ModuleReference><ModuleReference><Name>irisjwt</Name><Version>1.0.0</Version>"_
"</ModuleReference></Dependencies><Packaging>module</Packaging><SourcesRoot>src</SourcesRoot></Module></Document></Export>"
set moduleDir = ##class(%File).NormalizeDirectory(##class(%File).GetDirectory(testRoot)_"/_data/bypass-deps/")

if '##class(%File).Exists(moduleDir) {
set status = ##class(%File).CreateDirectoryChain(moduleDir,.status)
do $$$AssertStatusOK(status,"Created module.xml file in directory: "_moduleDir)
set fileStream = ##class(%Stream.FileBinary).%New()
set fileStream.Filename = ##class(%File).NormalizeFilename("module.xml",moduleDir)
do fileStream.Write(moduleStr)
set status = fileStream.%Save()
do $$$AssertStatusOK(status,"module file created on directory "_moduleDir)
}
set status = ##class(%IPM.Main).Shell("load " _ moduleDir_" -bypass-deps")
do $$$AssertStatusOK(status,"Loaded SimpleApp demo-module1 with -bypass-deps successfully." _ moduleDir)

do $$$LogMessage("Verifying that dependencies were not installed...")
set ptr=0
while $listnext(dependencyModules,ptr,module) {
set found = 0
set exists = ##class(%IPM.Storage.Module).NameExists(module)
do $$$AssertTrue('exists, "Dependency module '"_module_"' not installed when loading with -bypass-deps.")
}

do $$$LogMessage("Now loading the module without -bypass-deps to verify dependencies get installed...")

// Now load again without -bypass-deps to verify dependencies get installed
set status = ##class(%IPM.Main).Shell("load " _ moduleDir)
do $$$AssertStatusOK(status,"Module demo-module1 is loaded without -bypass-deps")

set ptr=0
while $listnext(dependencyModules,ptr,module) {
set found = 0
set exists = ##class(%IPM.Storage.Module).NameExists(module)
do $$$AssertTrue(exists, "Dependency module '"_module_"' should be installed when loading without -bypass-deps.")
}

do $$$LogMessage("uninstalling the demo-module1 and its dependencies...")
set status = ##class(%IPM.Main).Shell("uninstall demo-module1 -r")
do $$$AssertStatusOK(status,"Uninstalled demo-module1 and its dependencies successfully.")

do $$$LogMessage("Deleting the created directory...")
set status = ##class(%File).RemoveDirectoryTree(moduleDir)
do $$$AssertStatusOK(status, "Directory deleted successfully")
}

Method TestUninstallWithoutModuleName()
{
do $$$LogMessage("Run Uninstall command without module name")
Expand Down