Skip to content

Commit

Permalink
Merge pull request #668 from intersystems/v0.9.x
Browse files Browse the repository at this point in the history
Merge v0.9.x to main
  • Loading branch information
isc-tleavitt authored Dec 18, 2024
2 parents 1c760de + d11b82b commit 4726db4
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 10 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ 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.9.1] - 2024-12-18

### 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

### Fixed
- #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
Expand Down
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
# ObjectScript Package Manager Client - ZPM
# InterSystems Package Manager - IPM

Helps to install ObjectScript classes and routines, globals, Embedded Python modules, CSP and Frontend packages, and any files into InterSystems IRIS published on the official [ZPM Registry](https://pm.community.intersystems.com/packages/-/all) or private ZPM registry of your own.
Helps to install ObjectScript classes and routines, globals, Embedded Python modules, CSP and Frontend packages, and any files into InterSystems IRIS published on the official [Registry](https://pm.community.intersystems.com/packages/-/all) or private registry of your own.

## Documentation
* [The official documenation in the wiki](https://github.com/intersystems-community/zpm/wiki/)
* [Articles on the InterSystems Developer Community](https://community.intersystems.com/tags/objectscript-package-manager-zpm)
* [Videos on YouTube](https://www.youtube.com/playlist?list=PLKb2cBVphNQRcmxt4LtYDyLJEPfF4X4-4)

## Compatibility Note
With the release of IPM v0.9.0 on Dec 2024, IPM is no longer mapped across namespaces.
This is an intentional change so that users can have different IPM versions and configurations in different namespaces.
If you install IPM on an instance without the legacy 0.7.x version, IPM is only installed to the current namespace.

* To retain the old behavior where %IPM routines and classes mapped across all namespaces, run `zpm "enable -map -globally`. This is automatically performed when upgrading from a legacy version and can be undone by running `zpm "unmap -globally"`.
* You can optionally choose to map IPM repositories across namespaces with `zpm "enable -map -repos -namespaces NS1,NS2,NS3` or `zpm "enable -map -repos -globally`. Repositories are only mapped if %IPM classes and routines are also mapped from the same namespace.
* As a convenience command, `zpm "enable -community"` will make IPM behave essentially the same as legacy versions (v0.7.x) by setting up the the community registry and maping %IPM routines and classes, as well IPM repository settings to all namespaces.

## Installing ObjectScript Package Manager Client:

0. Use one-liner in terminal call or programmatically:
```
s r=##class(%Net.HttpRequest).%New(),r.Server="pm.community.intersystems.com",r.SSLConfiguration="ISC.FeatureTracker.SSL.Config" d r.Get("/packages/zpm/latest/installer"),$system.OBJ.LoadStream(r.HttpResponse.Data,"c")
s version="latest" s r=##class(%Net.HttpRequest).%New(),r.Server="pm.community.intersystems.com",r.SSLConfiguration="ISC.FeatureTracker.SSL.Config" d r.Get("/packages/zpm/"_version_"/installer"),$system.OBJ.LoadStream(r.HttpResponse.Data,"c")
```
**If you want the legacy behavior of mapping IPM classes, routines, and repository settings to all namespaces, run `zpm "enable -community"` after installing IPM. See `zpm "help enable"` for details.**
**In a CI script, for deterministic behavior, you should replace version="latest" with the IPM version you wish to use.**

OR:

Expand Down Expand Up @@ -65,4 +75,4 @@ Here is the [alternative supported folder structure.](https://openexchange.inter

## Support and Collaboration
ObjectScript Package Manager is a community supported project and thus open to collaboration via Pull Requests.
Issues and feature requests [are very welcome](https://github.com/intersystems-community/zpm/issues)
Issues and feature requests [are very welcome](https://github.com/intersystems-community/zpm/issues)
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 ?!
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 namespaces above and run: zpm ""enable -map -globally""."
Write !, "If you want to reset repository and map IPM globally along with repository settings, switch to one of the namespaces 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

0 comments on commit 4726db4

Please sign in to comment.