Skip to content

Commit

Permalink
[BREAKING] Support only compatible platform versions (#2285)
Browse files Browse the repository at this point in the history
  • Loading branch information
alessio-perugini authored Nov 9, 2023
1 parent f09ad56 commit b0e28d9
Show file tree
Hide file tree
Showing 26 changed files with 713 additions and 328 deletions.
46 changes: 46 additions & 0 deletions arduino/cores/cores.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type PlatformRelease struct {
PluggableDiscoveryAware bool `json:"-"` // true if the Platform supports pluggable discovery (no compatibility layer required)
Monitors map[string]*MonitorDependency `json:"-"`
MonitorsDevRecipes map[string]string `json:"-"`
Compatible bool `json:"-"` // true if at all ToolDependencies are available for the current OS/ARCH.
}

// BoardManifest contains information about a board. These metadata are usually
Expand Down Expand Up @@ -229,6 +230,21 @@ func (platform *Platform) GetLatestRelease() *PlatformRelease {
return platform.FindReleaseWithVersion(latestVersion)
}

// GetLatestCompatibleRelease returns the latest compatible release of this platform, or nil if no
// compatible releases are available.
func (platform *Platform) GetLatestCompatibleRelease() *PlatformRelease {
var maximum *PlatformRelease
for _, release := range platform.Releases {
if !release.IsCompatible() {
continue
}
if maximum == nil || release.Version.GreaterThan(maximum.Version) {
maximum = release
}
}
return maximum
}

// GetAllReleases returns all the releases of this platform, or an empty
// slice if no releases are available
func (platform *Platform) GetAllReleases() []*PlatformRelease {
Expand All @@ -249,6 +265,18 @@ func (platform *Platform) GetAllReleasesVersions() []*semver.Version {
return versions
}

// GetAllCompatibleReleasesVersions returns all the version numbers in this Platform Package that contains compatible tools.
func (platform *Platform) GetAllCompatibleReleasesVersions() []*semver.Version {
versions := []*semver.Version{}
for _, release := range platform.Releases {
if !release.IsCompatible() {
continue
}
versions = append(versions, release.Version)
}
return versions
}

// latestReleaseVersion obtains latest version number, or nil if no release available
func (platform *Platform) latestReleaseVersion() *semver.Version {
// TODO: Cache latest version using a field in Platform
Expand All @@ -266,6 +294,18 @@ func (platform *Platform) latestReleaseVersion() *semver.Version {
return max
}

// latestCompatibleReleaseVersion obtains latest version number, for platforms that contains compatible tools, or nil if no release available
func (platform *Platform) latestCompatibleReleaseVersion() *semver.Version {
versions := platform.GetAllCompatibleReleasesVersions()
var maxVer *semver.Version
for _, v := range versions {
if maxVer == nil || v.GreaterThan(maxVer) {
maxVer = v
}
}
return maxVer
}

// GetAllInstalled returns all installed PlatformRelease
func (platform *Platform) GetAllInstalled() []*PlatformRelease {
res := []*PlatformRelease{}
Expand Down Expand Up @@ -422,3 +462,9 @@ func (release *PlatformRelease) HasMetadata() bool {
installedJSONPath := release.InstallDir.Join("installed.json")
return installedJSONPath.Exist()
}

// IsCompatible returns true if all the tools dependencies of a PlatformRelease
// are available in the current OS/ARCH.
func (release *PlatformRelease) IsCompatible() bool {
return release.Compatible
}
4 changes: 2 additions & 2 deletions arduino/cores/packagemanager/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ func (pme *Explorer) FindPlatformReleaseDependencies(item *PlatformReference) (*
return nil, nil, fmt.Errorf(tr("required version %[1]s not found for platform %[2]s"), item.PlatformVersion, platform.String())
}
} else {
release = platform.GetLatestRelease()
release = platform.GetLatestCompatibleRelease()
if release == nil {
return nil, nil, fmt.Errorf(tr("platform %s has no available releases"), platform.String())
return nil, nil, fmt.Errorf(tr("platform is not available for your OS"))
}
}

Expand Down
2 changes: 1 addition & 1 deletion arduino/cores/packagemanager/install_uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (pme *Explorer) DownloadAndInstallPlatformUpgrades(
if installed == nil {
return nil, &arduino.PlatformNotFoundError{Platform: platformRef.String()}
}
latest := platform.GetLatestRelease()
latest := platform.GetLatestCompatibleRelease()
if !latest.Version.GreaterThan(installed.Version) {
return installed, &arduino.PlatformAlreadyAtTheLatestVersionError{Platform: platformRef.String()}
}
Expand Down
37 changes: 37 additions & 0 deletions arduino/cores/packagemanager/package_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,50 @@ func (pmb *Builder) Build() *PackageManager {
}
}

// calculate Compatible PlatformRelease
func (pmb *Builder) calculateCompatibleReleases() {
for _, op := range pmb.packages {
for _, p := range op.Platforms {
for _, pr := range p.Releases {
platformHasAllCompatibleTools := func() bool {
for _, td := range pr.ToolDependencies {
if td == nil {
return false
}

_, ok := pmb.packages[td.ToolPackager]
if !ok {
return false
}
tool := pmb.packages[td.ToolPackager].Tools[td.ToolName]
if tool == nil {
return false
}
tr := tool.Releases[td.ToolVersion.NormalizedString()]
if tr == nil {
return false
}

if tr.GetCompatibleFlavour() == nil {
return false
}
}
return true
}
pr.Compatible = platformHasAllCompatibleTools()
}
}
}
}

// NewBuilder creates a Builder with the same configuration
// of this PackageManager. A "commit" function callback is returned: calling
// this function will make the builder write the new configuration into this
// PackageManager.
func (pm *PackageManager) NewBuilder() (builder *Builder, commit func()) {
pmb := NewBuilder(pm.IndexDir, pm.PackagesDir, pm.DownloadDir, pm.tempDir, pm.userAgent)
return pmb, func() {
pmb.calculateCompatibleReleases()
pmb.BuildIntoExistingPackageManager(pm)
}
}
Expand Down
1 change: 1 addition & 0 deletions arduino/cores/packagemanager/package_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ func TestFindToolsRequiredFromPlatformRelease(t *testing.T) {
func TestFindPlatformReleaseDependencies(t *testing.T) {
pmb := NewBuilder(nil, nil, nil, nil, "test")
pmb.LoadPackageIndexFromFile(paths.New("testdata", "package_tooltest_index.json"))
pmb.calculateCompatibleReleases()
pm := pmb.Build()
pme, release := pm.NewExplorer()
defer release()
Expand Down
2 changes: 1 addition & 1 deletion commands/board/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchR
foundBoards := []*rpc.BoardListItem{}
for _, targetPackage := range pme.GetPackages() {
for _, platform := range targetPackage.Platforms {
latestPlatformRelease := platform.GetLatestRelease()
latestPlatformRelease := platform.GetLatestCompatibleRelease()
installedPlatformRelease := pme.GetInstalledPlatformRelease(platform)

if latestPlatformRelease == nil && installedPlatformRelease == nil {
Expand Down
1 change: 1 addition & 0 deletions commands/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,6 @@ func PlatformReleaseToRPC(platformRelease *cores.PlatformRelease) *rpc.PlatformR
MissingMetadata: missingMetadata,
Type: []string{platformRelease.Category},
Deprecated: platformRelease.Deprecated,
Compatible: platformRelease.IsCompatible(),
}
}
37 changes: 9 additions & 28 deletions commands/core/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse

// Discard platforms with no releases
latestRelease := platform.GetLatestRelease()
if latestRelease == nil {
continue
}
if latestRelease.Name == "" {
if latestRelease == nil || latestRelease.Name == "" {
continue
}

Expand Down Expand Up @@ -86,41 +83,25 @@ func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse
out := []*rpc.PlatformSummary{}
for _, platform := range res {
rpcPlatformSummary := &rpc.PlatformSummary{
Metadata: commands.PlatformToRPCPlatformMetadata(platform),
Releases: map[string]*rpc.PlatformRelease{},
}

rpcPlatformSummary.Metadata = commands.PlatformToRPCPlatformMetadata(platform)

installed := pme.GetInstalledPlatformRelease(platform)
latest := platform.GetLatestRelease()
if installed != nil {
if installed := pme.GetInstalledPlatformRelease(platform); installed != nil {
rpcPlatformSummary.InstalledVersion = installed.Version.String()
}
if latest != nil {
rpcPlatformSummary.LatestVersion = latest.Version.String()
if latestCompatible := platform.GetLatestCompatibleRelease(); latestCompatible != nil {
rpcPlatformSummary.LatestVersion = latestCompatible.Version.String()
}
if req.AllVersions {
for _, platformRelease := range platform.GetAllReleases() {
rpcPlatformRelease := commands.PlatformReleaseToRPC(platformRelease)
rpcPlatformSummary.Releases[rpcPlatformRelease.Version] = rpcPlatformRelease
}
} else {
if installed != nil {
rpcPlatformRelease := commands.PlatformReleaseToRPC(installed)
rpcPlatformSummary.Releases[installed.Version.String()] = rpcPlatformRelease
}
if latest != nil {
rpcPlatformRelease := commands.PlatformReleaseToRPC(latest)
rpcPlatformSummary.Releases[latest.Version.String()] = rpcPlatformRelease
}
for _, platformRelease := range platform.GetAllReleases() {
rpcPlatformRelease := commands.PlatformReleaseToRPC(platformRelease)
rpcPlatformSummary.Releases[rpcPlatformRelease.Version] = rpcPlatformRelease
}
out = append(out, rpcPlatformSummary)
}

// Sort result alphabetically and put deprecated platforms at the bottom
sort.Slice(out, func(i, j int) bool {
return strings.ToLower(out[i].GetReleases()[out[i].GetLatestVersion()].Name) <
strings.ToLower(out[j].GetReleases()[out[j].GetLatestVersion()].Name)
return strings.ToLower(out[i].GetMetadata().GetId()) < strings.ToLower(out[j].GetMetadata().GetId())
})
sort.SliceStable(out, func(i, j int) bool {
return !out[i].GetMetadata().Deprecated && out[j].GetMetadata().Deprecated
Expand Down
Loading

0 comments on commit b0e28d9

Please sign in to comment.