diff --git a/cmd/commands/add.go b/cmd/commands/add.go index 030e167..71b8e45 100644 --- a/cmd/commands/add.go +++ b/cmd/commands/add.go @@ -62,7 +62,11 @@ Add a pack using the following "" specification or using packs provided by been released yet. This will install it as a local pack and keep a reference in ".Local/local_repository.pidx". -The file can be a local file or a file hosted somewhere else on the Internet. + To select a specific version use: Vendor::Pack@x.y.z + To select the newest version of a major version use: Vendor::Pack@^x.y.z + To select any newer version use: Vendor::Pack@>=x.y.z + + The file can be a local file or a file hosted somewhere else on the Internet. If it's hosted somewhere, cpackget will first download it then extract all pack files into "CMSIS_PACK_ROOT////" If "-f" is used, cpackget will call "cpackget pack add" on each URL specified in the file.`, Args: cobra.MinimumNArgs(0), diff --git a/cmd/commands/list.go b/cmd/commands/list.go index a773e5d..83699b1 100644 --- a/cmd/commands/list.go +++ b/cmd/commands/list.go @@ -10,6 +10,9 @@ import ( ) var listCmdFlags struct { + // listUpdates tells whether listing all packs for which updates exist + listUpdates bool + // listPublic tells whether listing all packs in the public index listPublic bool @@ -21,13 +24,13 @@ var listCmdFlags struct { } var ListCmd = &cobra.Command{ - Use: "list [--cached|--public]", + Use: "list [--cached|--public|--updates]", Short: "List installed packs", - Long: "List all installed packs and optionally cached pack files", + Long: "List all installed packs and optionally cached packs or those for which updates are available", Args: cobra.MaximumNArgs(0), PersistentPreRunE: configureInstaller, RunE: func(cmd *cobra.Command, args []string) error { - return installer.ListInstalledPacks(listCmdFlags.listCached, listCmdFlags.listPublic, false, listCmdFlags.listFilter) + return installer.ListInstalledPacks(listCmdFlags.listCached, listCmdFlags.listPublic, listCmdFlags.listUpdates, false, listCmdFlags.listFilter) }, } @@ -38,13 +41,14 @@ var listRequiredCmd = &cobra.Command{ Args: cobra.MaximumNArgs(0), PersistentPreRunE: configureInstaller, RunE: func(cmd *cobra.Command, args []string) error { - return installer.ListInstalledPacks(listCmdFlags.listCached, listCmdFlags.listPublic, true, listCmdFlags.listFilter) + return installer.ListInstalledPacks(listCmdFlags.listCached, listCmdFlags.listPublic, listCmdFlags.listUpdates, true, listCmdFlags.listFilter) }, } func init() { ListCmd.Flags().BoolVarP(&listCmdFlags.listCached, "cached", "c", false, "list only cached packs") ListCmd.Flags().BoolVarP(&listCmdFlags.listPublic, "public", "p", false, "list packs in the public index") + ListCmd.Flags().BoolVarP(&listCmdFlags.listUpdates, "updates", "u", false, "list packs which have newer versions") ListCmd.Flags().StringVarP(&listCmdFlags.listFilter, "filter", "f", "", "filter results (case sensitive, accepts several expressions)") ListCmd.AddCommand(listRequiredCmd) diff --git a/cmd/installer/pack.go b/cmd/installer/pack.go index 8c7d865..997f45b 100644 --- a/cmd/installer/pack.go +++ b/cmd/installer/pack.go @@ -45,7 +45,7 @@ type PackType struct { toBeRemoved bool // exactVersion tells whether this pack identifier is specifying an exact version - // or is requesting a newer one, e.g. >=x.y.z + // or is requesting a newer one, e.g. @>=x.y.z versionModifier int // targetVersion is the most recent version of a pack in case exactVersion==true @@ -485,7 +485,7 @@ func (p *PackType) extractEula(packPath string) error { return os.WriteFile(eulaFileName, eulaContents, utils.FileModeRO) } -// resolveVersionModifier takes into account eventual versionModifiers (@, @^ and >=) to determine +// resolveVersionModifier takes into account eventual versionModifiers (@, @^ and @>=) to determine // which version of a pack should be targeted for installation func (p *PackType) resolveVersionModifier(pdscXML *xml.PdscXML) { log.Debugf("Resolving version modifier for \"%s\" using PDSC \"%s\"", p.path, pdscXML.FileName) @@ -509,7 +509,7 @@ func (p *PackType) resolveVersionModifier(pdscXML *xml.PdscXML) { log.Errorf("Tried to install at least version %s, highest available version is %s", p.Version, pdscXML.LatestVersion()) } else { p.targetVersion = pdscXML.LatestVersion() - log.Debugf("- resolved(>=) as %s", p.targetVersion) + log.Debugf("- resolved(@>=) as %s", p.targetVersion) } return } @@ -638,7 +638,7 @@ func (p *PackType) PdscFileNameWithVersion() string { } // GetVersion makes sure to get the latest version for the pack -// after parsing possible version modifiers (@^, >=) +// after parsing possible version modifiers (@^, @>=) func (p *PackType) GetVersion() string { if p.versionModifier != utils.ExactVersion { return p.targetVersion diff --git a/cmd/installer/root.go b/cmd/installer/root.go index c9cf32f..44c82a4 100644 --- a/cmd/installer/root.go +++ b/cmd/installer/root.go @@ -520,7 +520,7 @@ func UpdatePublicIndex(indexPath string, overwrite bool, sparse bool, downloadPd } // ListInstalledPacks generates a list of all packs present in the pack root folder -func ListInstalledPacks(listCached, listPublic, listRequirements bool, listFilter string) error { +func ListInstalledPacks(listCached, listPublic, listUpdates, listRequirements bool, listFilter string) error { log.Debugf("Listing packs") if listPublic { if listFilter != "" { @@ -599,13 +599,21 @@ func ListInstalledPacks(listCached, listPublic, listRequirements bool, listFilte } } } else { - if listRequirements { - log.Info("Listing installed packs with dependencies") - } else { + if listUpdates { if listFilter != "" { - log.Infof("Listing installed packs, filtering by \"%s\"", listFilter) + log.Infof("Listing installed updateable packs, filtering by \"%s\"", listFilter) } else { - log.Infof("Listing installed packs") + log.Infof("Listing installed updateable packs") + } + } else { + if listRequirements { + log.Info("Listing installed packs with dependencies") + } else { + if listFilter != "" { + log.Infof("Listing installed packs, filtering by \"%s\"", listFilter) + } else { + log.Infof("Listing installed packs") + } } } diff --git a/cmd/installer/root_pack_list_test.go b/cmd/installer/root_pack_list_test.go index 84e6546..46b223a 100644 --- a/cmd/installer/root_pack_list_test.go +++ b/cmd/installer/root_pack_list_test.go @@ -23,6 +23,7 @@ var ( ListCached = true ListFilter = "" ListPublic = true + ListUpdates = true ListRequirements = true ) @@ -35,7 +36,7 @@ func ExampleListInstalledPacks() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(!ListCached, !ListPublic, !ListRequirements, ListFilter) + _ = installer.ListInstalledPacks(!ListCached, !ListPublic, !ListUpdates, !ListRequirements, ListFilter) // Output: // I: Listing installed packs // I: (no packs installed) @@ -49,7 +50,7 @@ func ExampleListInstalledPacks_emptyCache() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(ListCached, !ListPublic, !ListRequirements, ListFilter) + _ = installer.ListInstalledPacks(ListCached, !ListPublic, !ListUpdates, !ListRequirements, ListFilter) // Output: // I: Listing cached packs // I: (no packs cached) @@ -63,7 +64,7 @@ func ExampleListInstalledPacks_emptyPublicIndex() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListRequirements, ListFilter) + _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListUpdates, !ListRequirements, ListFilter) // Output: // I: Listing packs from the public index // I: (no packs in public index) @@ -102,7 +103,7 @@ func ExampleListInstalledPacks_list() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListRequirements, ListFilter) + _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListUpdates, !ListRequirements, ListFilter) // Output: // I: Listing packs from the public index // I: TheVendor::PublicLocalPack@1.2.3 (cached) @@ -139,7 +140,7 @@ func ExampleListInstalledPacks_listCached() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(ListCached, !ListPublic, !ListRequirements, ListFilter) + _ = installer.ListInstalledPacks(ListCached, !ListPublic, !ListUpdates, !ListRequirements, ListFilter) // Output: // I: Listing cached packs // I: TheVendor::PublicLocalPack@1.2.3 @@ -186,7 +187,7 @@ func TestListInstalledPacks(t *testing.T) { var buf bytes.Buffer log.SetOutput(&buf) defer log.SetOutput(io.Discard) - assert.Nil(installer.ListInstalledPacks(!ListCached, !ListPublic, !ListRequirements, ListFilter)) + assert.Nil(installer.ListInstalledPacks(!ListCached, !ListPublic, !ListUpdates, !ListRequirements, ListFilter)) stdout := buf.String() assert.Contains(stdout, "I: Listing installed packs") assert.Contains(stdout, fmt.Sprintf("I: TheVendor::PackName@1.2.3 (installed via %s)", expectedPdscAbsPath)) @@ -216,7 +217,7 @@ func TestListInstalledPacks(t *testing.T) { var buf bytes.Buffer log.SetOutput(&buf) defer log.SetOutput(io.Discard) - assert.Nil(installer.ListInstalledPacks(!ListCached, !ListPublic, !ListRequirements, ListFilter)) + assert.Nil(installer.ListInstalledPacks(!ListCached, !ListPublic, !ListUpdates, !ListRequirements, ListFilter)) stdout := buf.String() assert.Contains(stdout, "I: Listing installed packs") assert.Contains(stdout, fmt.Sprintf("I: TheVendor::PackName@1.2.3 (installed via %s)", expectedPdscAbsPath)) @@ -226,7 +227,7 @@ func TestListInstalledPacks(t *testing.T) { assert.Nil(pdscXML.Read()) pdscXML.ReleasesTag.Releases[0].Version = "1.2.4" assert.Nil(utils.WriteXML(pdscPath, pdscXML)) - assert.Nil(installer.ListInstalledPacks(!ListCached, !ListPublic, !ListRequirements, ListFilter)) + assert.Nil(installer.ListInstalledPacks(!ListCached, !ListPublic, !ListUpdates, !ListRequirements, ListFilter)) stdout = buf.String() assert.Contains(stdout, "I: Listing installed packs") assert.Contains(stdout, fmt.Sprintf("I: TheVendor::PackName@1.2.4 (installed via %s)", expectedPdscAbsPath)) @@ -264,7 +265,7 @@ func ExampleListInstalledPacks_listMalformedInstalledPacks() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(!ListCached, !ListPublic, !ListRequirements, ListFilter) + _ = installer.ListInstalledPacks(!ListCached, !ListPublic, !ListUpdates, !ListRequirements, ListFilter) // Output: // I: Listing installed packs // E: _TheVendor::_PublicLocalPack@1.2.3.4 - error: pack version incorrect format @@ -300,7 +301,7 @@ func ExampleListInstalledPacks_filter() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListRequirements, "1.2.4") + _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListUpdates, !ListRequirements, "1.2.4") // Output: // I: Listing packs from the public index, filtering by "1.2.4" // I: TheVendor::PublicLocalPack@1.2.4 (installed) @@ -337,7 +338,7 @@ func ExampleListInstalledPacks_filterErrorPackages() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(!ListCached, !ListPublic, !ListRequirements, "TheVendor") + _ = installer.ListInstalledPacks(!ListCached, !ListPublic, !ListUpdates, !ListRequirements, "TheVendor") // Output: // I: Listing installed packs, filtering by "TheVendor" // E: _TheVendor::_PublicLocalPack@1.2.3.4 - error: pack version incorrect format @@ -372,7 +373,7 @@ func ExampleListInstalledPacks_filterInvalidChars() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListRequirements, "@ :") + _ = installer.ListInstalledPacks(ListCached, ListPublic, !ListUpdates, !ListRequirements, "@ :") // Output: // I: Listing packs from the public index, filtering by "@ :" } @@ -406,7 +407,7 @@ func ExampleListInstalledPacks_filteradditionalMessages() { log.SetOutput(os.Stdout) defer log.SetOutput(io.Discard) - _ = installer.ListInstalledPacks(ListCached, !ListPublic, !ListRequirements, "(installed)") + _ = installer.ListInstalledPacks(ListCached, !ListPublic, !ListUpdates, !ListRequirements, "(installed)") // Output: // I: Listing cached packs, filtering by "(installed)" } diff --git a/cmd/utils/packs.go b/cmd/utils/packs.go index 735ff94..15fe0bd 100644 --- a/cmd/utils/packs.go +++ b/cmd/utils/packs.go @@ -46,9 +46,10 @@ var packFileNameRegex = regexp.MustCompile(packFileNamePattern) // - Vendor::Pack // - Vendor::Pack@x.y.z // - Vendor::Pack@^x.y.z +// - Vendor::Pack@>=x.y.z // - Vendor::Pack>=x.y.z var dottedPackIDPattern = fmt.Sprintf(`^(?P%s)\.(?P%s)(?:\.(?P%s))?$`, namePattern, namePattern, versionPattern) -var legacyPackIDPattern = fmt.Sprintf(`^(?P%s)::(?P%s)(?:(@|@\^|>=)(?P%s|latest))?$`, namePattern, namePattern, versionPattern) +var legacyPackIDPattern = fmt.Sprintf(`^(?P%s)::(?P%s)(?:(@|@\^|@>=|>=)(?P%s|latest))?$`, namePattern, namePattern, versionPattern) var packIDPattern = fmt.Sprintf(`(?:%s|%s)`, dottedPackIDPattern, legacyPackIDPattern) // packIDRegex pre-compiles packIdPattern @@ -126,7 +127,7 @@ const ( // Examples: Vendor::PackName, Vendor.PackName AnyVersion = 2 - // Example: Vendor::PackName>=x.y.z + // Example: Vendor::PackName@>=x.y.z GreaterVersion = 3 // Example: Vendor::PackName@^x.y.z (the greatest version of the pack keeping the same major number) @@ -137,9 +138,10 @@ const ( ) var versionModMap = map[string]int{ - "@": ExactVersion, - "@^": GreatestCompatibleVersion, - ">=": GreaterVersion, + "@": ExactVersion, + "@^": GreatestCompatibleVersion, + "@>=": GreaterVersion, + ">=": GreaterVersion, } // PackInfo defines a basic pack information set @@ -241,7 +243,7 @@ func ExtractPackInfo(packPath string) (PackInfo, error) { info.VersionModifier = ExactVersion } } else if len(matches) == 5 { - // 5 matches: [Vendor::Pack(@|@^|>=)x.y.z, Vendor, Pack, (@|@^|>=), x.y.z] (legacy version) + // 5 matches: [Vendor::Pack(@|@^|@>=|>=)x.y.z, Vendor, Pack, (@|@^|@>=|>=), x.y.z] (legacy version) versionModifier := matches[3] version := matches[4]