Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow mapping and unmapping repos & improve zpm error output #663

Merged
merged 15 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ jobs:
CONTAINER=$(docker run -d --rm -v $(pwd):/home/irisowner/zpm/ containers.intersystems.com/intersystems/${{ needs.prepare.outputs.main }} --check-caps false)
sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh
docker exec -i $CONTAINER iris session iris -UUSER << EOF
set sc=##class(%SYSTEM.OBJ).Load("/home/irisowner/zpm/Installer.cls","ck")
set sc=##class(%SYSTEM.OBJ).Load("/home/irisowner/zpm/preload/cls/IPM/Installer.cls","ck")
set sc=##class(IPM.Installer).setup("/home/irisowner/zpm/",3)
zpm "repo -r -name registry -url ""https://pm.community.intersystems.com/"" -username ${{ secrets.REGISTRY_USERNAME }} -password ${{ secrets.REGISTRY_PASSWORD }}":1
zpm "publish zpm -v":1
Expand Down
19 changes: 12 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@ 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).

## [Unreleased - 0.9.0+snapshot]
## [0.9.1] - 2024-12-17

### Added
- #663 Added support for mapping of repository settings along with, or in addition to, IPM package and routines
- #663 Added functionality to always unmap repository settings when IPM package and routines are unmapped
- #663 Added support for unmapping of repository settings alone
- #663 Added support for `enable -community`, which resets repository settings to default and maps IPM along with repo settings globally

### Changed
isc-shuliu marked this conversation as resolved.
Show resolved Hide resolved
- #663 Improved error output and instructions in the language extension when "zpm" is run from a namespace without IPM

## [0.9.0] - 2024-12-16

### Added
- #364 Added ability to restrict the installation to IRIS or IRIS for Health platform to the SystemRequirements attribute
Expand Down Expand Up @@ -64,11 +75,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- #606: Don't put garbage folders in tar archive
- #652: Don't create extra needless mappings (could cause deadlock with parallel installation of dependencies)

### Security
-

### Removed
-

### Deprecated
- #593 CSPApplication is deprecated in favor of WebApplication. User will be warned when installing a package containing CSPApplication.
93 changes: 87 additions & 6 deletions src/cls/IPM/Main.cls
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,10 @@ generate /my/path -export 00000,PacketName2,IgnorePacket2^00000,PacketName3,Igno
<modifier name="local-only" description="If specified, only local artifacts will be used for installation. By default, this modifier is not set and will not limit to local artifacts." />
<modifier name="allow-upgrade" description="If specified, will also check for IPM version in specified namespaces and upgrade if version is lower than the target version. By default, this modifier is not ste and will not allow upgrade." />
<modifier name="map" aliases="m" description="If specified, will map IPM code from the current namespace-default code database rather than installing a separate copy." />
<modifier name="repos" aliases="r" description="If specified, will map repository settings across namespaces. Must be used together with -map." />
<modifier name="quiet" aliases="q" description="Quiet mode. By default, this modifier is not set and will display the contents onto the terminal/caller command line." />
<modifier name="preview" aliases="p" description="Preview what will be changed without actually making the changes." />
<modifier name="community" description="If specified, will reset repository to the community repository and map IPM to all namespaces along with the repository settings. This is functionaly equivalent to &quot;repo -delete-all&quot;, &quot;repo -reset-defaults&quot;, and &quot;enable -map -repos -globally&quot;. With this modifier, all other modifiers will be ignored."/>
<!-- Examples -->
<example description="Make IPM available in all namespaces (including %SYS) by mapping the version in the current namespace default routine database. Namespace-specific installation will override this.">
enable -map -globally
Expand All @@ -672,15 +674,21 @@ generate /my/path -export 00000,PacketName2,IgnorePacket2^00000,PacketName3,Igno
<example description="Install or upgrade IPM to latest IPM version in namespaces: NS1, NS2, NS3.">
enable -v latest -allow-upgrade NS1,NS2,NS3
</example>
<example description="Reset repository to the community repository and map IPM to all namespaces along with the repository settings.">
enable -community
</example>
</command>

<command name="unmap">
<summary>Unmap %IPM package and routines in specified namespaces.</summary>
<description>
Unmap %IPM package and routines in specified namespaces. Will Skip non-mapped namespaces.
If repository settings are mapped, will also unmap repository settings.
</description>
<modifier name="namespaces" aliases="ns" value="true" description="Comma-separated namespaces in which IPM mapping needs to be deleted."/>
<modifier name="globally" aliases="g" description="Will unmap IPM in all explicit namespaces that currently do not have IPM installed."/>
<modifier name="quiet" aliases="q" description="Quiet mode. By default, this modifier is not set and will display the contents onto the terminal/caller command line." />
<modifier name="repos-only" description="If specified, will only unmap repository settings across namespaces. This doesn't affect mapping of IPM packages and routines." />
<example description="Unmap IPM from namespaces NS1, NS2, NS3.">
unmap -ns NS1,NS2,NS3
</example>
Expand Down Expand Up @@ -2803,9 +2811,12 @@ ZPM(pArgs...)
Set found = 0
While rs.%Next() {
Set $Namespace = $Zstrip(rs.%Get("Nsp"), "<>WC")
If $System.CLS.IsMthd("%IPM.Main", "Shell") {
// Some I4H containers come with %IPM.Main but the "version" command doesn't work ?!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would probably be those with IPM mapped from HSLIB/HSCUSTOM, on older versions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for example, containers.intersystems.com/intersystems/irishealth-community:2024.1 has this problem in HSLIB.

If $System.CLS.IsMthd("%IPM.Main", "Shell") && ($Namespace '= "HSLIB") && ($Namespace '= "HSSYS") {
Write !, "Change namepace to one of the following to run the ""zpm"" command"
Do ##class(%IPM.Main).Shell("version")
Write !, "If you want to map IPM globally, switch to one of the namesapaces above and run: zpm ""enable -map -globally""."
isc-shuliu marked this conversation as resolved.
Show resolved Hide resolved
Write !, "If you want to reset repository and map IPM globally along with repository settings, switch to one of the namesapaces above and run: zpm ""enable -community""."
Set found = 1
Quit
}
Expand Down Expand Up @@ -2840,6 +2851,19 @@ ClassMethod EnableIPM(ByRef pCommandInfo)
Write !,($namespace)_"> "_$$$FormattedLine($$$Green,$$$IPMModuleName_" ")_modDef.VersionString
}

If $$$HasModifier(pCommandInfo,"community") {
For cmd = "repo -delete-all", "repo -reset-defaults", "enable -map -repos -globally" {
Write !!, "RUNNING command: """, cmd, """"
Do ..ShellInternal(cmd, .exc)
If exc '= $$$NULLOREF {
Write !, $$$FormattedLine($$$Red, $$$FormatText("Error running command ""%1"" - %2", cmd, exc.DisplayString()))
} Else {
Write !, $$$FormattedLine($$$Green, $$$FormatText("Command ""%1"" finished successfull", cmd))
}
}
Return
}

Set quiet = $$$HasModifier(pCommandInfo,"quiet")
Set preview = $$$HasModifier(pCommandInfo,"preview")
Set map = $$$HasModifier(pCommandInfo,"map")
Expand All @@ -2848,6 +2872,7 @@ ClassMethod EnableIPM(ByRef pCommandInfo)
Set version = $$$GetModifier(pCommandInfo, "version")
Set namespaces = $$$GetModifier(pCommandInfo, "namespaces")
Set allowUpgrade = $$$HasModifier(pCommandInfo,"allow-upgrade")
Set mapRepos = $$$HasModifier(pCommandInfo,"repos")
Set useLocal = 1 // var to store the final decision of whether to use local manifest or get from server
Set targetVersion = "" // var to store the final version of IPM to be installed
Kill targetNamespaces // multi-dim array to store the final namespaces that need to install IPM
Expand All @@ -2866,6 +2891,9 @@ ClassMethod EnableIPM(ByRef pCommandInfo)
If map && 'globally && (namespaces = "") {
$$$ThrowOnError($$$ERROR($$$GeneralError,"If mapping from the current namespace's routine database with -map, must specify either -globally or a list of namespaces with -ns"))
}
If ('map) && (mapRepos) {
$$$ThrowOnError($$$ERROR($$$GeneralError,"Cannot specify -repos without -map"))
}

If map {
If globally {
Expand All @@ -2884,13 +2912,15 @@ ClassMethod EnableIPM(ByRef pCommandInfo)
} Else {
Set namespaces = $ListFromString(namespaces)
}

// First try to map IPM itself
Set pointer = 0
While $ListNext(namespaces,pointer,namespace) {
Set namespace = $Zstrip(namespace, "<>WC")
Set $Namespace = namespace
If ..IPMInstalled() {
If 'quiet || preview {
Write !,"Skipping "_namespace_" - IPM already installed."
Write !,"Skipping IPM mapping of "_namespace_" - IPM already installed."
}
Continue
}
Expand All @@ -2908,6 +2938,42 @@ ClassMethod EnableIPM(ByRef pCommandInfo)
}
$$$ThrowOnError(##class(%IPM.Utils.Build).MapRoutineEquivalently("%IPM.*",initNamespace,,namespace))
}

// Then try to map repositories if -repos is specified
If mapRepos {
Do ..GetMapInfo(.isMappedFrom)
Set pointer = 0
While $ListNext(namespaces,pointer,namespace) {
Set namespace = $ZStrip(namespace, "<>WC")
// If IPM is not mapped from source namespace, skip repo mapping
If $Get(isMappedFrom(namespace)) '= initNamespace {
If 'quiet || preview {
Write !,"Skipping repository mapping of "_namespace_" - IPM not mapped from source namespace."
}
Continue
}
// If repository are already present, also skip repo mapping avoid override
Set $Namespace = namespace
If $Data(^IPM.Repo.DefinitionD) \ 2 {
If 'quiet || preview {
Write !,"Skipping repository mapping of "_namespace_" - IPM repositories found."
}
Continue
}
Set $Namespace = initNamespace
If preview {
Write !,"Would add IPM repository mappings to "_namespace
Continue
}
If 'quiet {
Write !,"Mapping IPM repository in "_namespace_" equivalently to "_initNamespace
}
For suffix = "D", "S", "I" {
$$$ThrowOnError(##class(%IPM.Utils.Build).MapGlobalEquivalently("IPM.Repo.Definition"_suffix, initNamespace, namespace))
}
}
}

Set $Namespace = initNamespace
If preview {
Write !,"Preview mode; no configuration changes were made."
Expand Down Expand Up @@ -3141,6 +3207,7 @@ ClassMethod UnmapIPM(ByRef pCommandInfo)
Set globally = $$$HasModifier(pCommandInfo,"globally")
Set namespaces = $ListFromString($$$GetModifier(pCommandInfo,"namespaces"), ",")
Set verbose = '$$$HasModifier(pCommandInfo,"quiet")
set reposOnly = $$$HasModifier(pCommandInfo,"repos-only")
// Sanity check
If (globally && (namespaces '= "")) {
$$$ThrowOnError($$$ERROR($$$GeneralError,"Cannot specify namespaces and global unmap flag at the same time."))
Expand All @@ -3161,7 +3228,11 @@ ClassMethod UnmapIPM(ByRef pCommandInfo)
}
}
If verbose {
Write !,"Will attempt to unmap %IPM package and routines from: "_ $ListToString(namespaces, ", ")
If reposOnly {
Write !,"Will attempt to unmap IPM repository settings from: "_ $ListToString(namespaces, ", ")
} Else {
Write !,"Will attempt to unmap IPM package, routines, and repository settings from: "_ $ListToString(namespaces, ", ")
}
}

// Gather namespaces where %IPM is mapped into
Expand All @@ -3176,11 +3247,21 @@ ClassMethod UnmapIPM(ByRef pCommandInfo)
}
Continue
}

If verbose {
Write !,"Unmapping %IPM package and routines from "_ns_" (mapped from "_src_")"
Write !,"Unmapping repository settings from "_ns_" (mapped from "_src_")"
}
For suffix = "D", "S", "I" {
$$$ThrowOnError(##class(%IPM.Utils.Module).RemoveGlobalMapping(ns, "IPM.Repo.Definition"_suffix))
}

If 'reposOnly {
If verbose {
Write !,"Unmapping IPM package and routines from "_ns_" (mapped from "_src_")"
}
$$$ThrowOnError(##class(%IPM.Utils.Module).RemovePackageMapping(ns, "%IPM"))
$$$ThrowOnError(##class(%IPM.Utils.Module).RemoveRoutineMapping(ns, "%IPM.*"))
}
$$$ThrowOnError(##class(%IPM.Utils.Module).RemovePackageMapping(ns, "%IPM"))
$$$ThrowOnError(##class(%IPM.Utils.Module).RemoveRoutineMapping(ns, "%IPM.*"))
}
}

Expand Down
Loading