Skip to content

Commit bbcf32d

Browse files
committed
Merge branch 'profile_with_global' into everything
2 parents 7eaa247 + 69761fb commit bbcf32d

File tree

6 files changed

+169
-72
lines changed

6 files changed

+169
-72
lines changed

commands/instances.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func (s *arduinoCoreServerImpl) Init(req *rpc.InitRequest, stream rpc.ArduinoCor
243243
}
244244

245245
// Load Platforms
246-
if profile == nil {
246+
if profile == nil || profile.RequireSystemInstalledPlatform() {
247247
for _, err := range pmb.LoadHardware() {
248248
s := &cmderrors.PlatformLoadingError{Cause: err}
249249
responseError(s.GRPCStatus())

internal/arduino/cores/packageindex/index.go

Lines changed: 87 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -151,18 +151,8 @@ func (index Index) MergeIntoPackages(outPackages cores.Packages) {
151151
// which in turn contains a single indexPlatformRelease converted from the one
152152
// passed as argument
153153
func IndexFromPlatformRelease(pr *cores.PlatformRelease) Index {
154-
boards := []indexBoard{}
155-
for _, manifest := range pr.BoardsManifest {
156-
board := indexBoard{
157-
Name: manifest.Name,
158-
}
159-
for _, id := range manifest.ID {
160-
if id.USB != "" {
161-
board.ID = []indexBoardID{{USB: id.USB}}
162-
}
163-
}
164-
boards = append(boards, board)
165-
}
154+
// While enumerating the dependencies we also build a set of required packages.
155+
requiredPackages := map[string]bool{}
166156

167157
tools := []indexToolDependency{}
168158
for _, t := range pr.ToolDependencies {
@@ -171,6 +161,7 @@ func IndexFromPlatformRelease(pr *cores.PlatformRelease) Index {
171161
Name: t.ToolName,
172162
Version: t.ToolVersion,
173163
})
164+
requiredPackages[t.ToolPackager] = true
174165
}
175166

176167
discoveries := []indexDiscoveryDependency{}
@@ -179,6 +170,7 @@ func IndexFromPlatformRelease(pr *cores.PlatformRelease) Index {
179170
Packager: d.Packager,
180171
Name: d.Name,
181172
})
173+
requiredPackages[d.Packager] = true
182174
}
183175

184176
monitors := []indexMonitorDependency{}
@@ -187,58 +179,98 @@ func IndexFromPlatformRelease(pr *cores.PlatformRelease) Index {
187179
Packager: m.Packager,
188180
Name: m.Name,
189181
})
182+
requiredPackages[m.Packager] = true
190183
}
191184

192-
packageTools := []*indexToolRelease{}
193-
for name, tool := range pr.Platform.Package.Tools {
194-
for _, toolRelease := range tool.Releases {
195-
flavours := []indexToolReleaseFlavour{}
196-
for _, flavour := range toolRelease.Flavors {
197-
flavours = append(flavours, indexToolReleaseFlavour{
198-
OS: flavour.OS,
199-
URL: flavour.Resource.URL,
200-
ArchiveFileName: flavour.Resource.ArchiveFileName,
201-
Size: json.Number(fmt.Sprintf("%d", flavour.Resource.Size)),
202-
Checksum: flavour.Resource.Checksum,
185+
// Helper functions: those are needed to build an extract of the package_index.json
186+
// that is compatible with the one used by the CLI.
187+
// The installed.json is a simplified version of the cores.Packages
188+
// and therefore we need to extract the relevant information from the
189+
// cores.PlatformRelease and cores.Package structures.
190+
extractIndexPackage := func(pack *cores.Package) *indexPackage {
191+
packageTools := []*indexToolRelease{}
192+
for name, tool := range pack.Tools {
193+
for _, toolRelease := range tool.Releases {
194+
flavours := []indexToolReleaseFlavour{}
195+
for _, flavour := range toolRelease.Flavors {
196+
flavours = append(flavours, indexToolReleaseFlavour{
197+
OS: flavour.OS,
198+
URL: flavour.Resource.URL,
199+
ArchiveFileName: flavour.Resource.ArchiveFileName,
200+
Size: json.Number(fmt.Sprintf("%d", flavour.Resource.Size)),
201+
Checksum: flavour.Resource.Checksum,
202+
})
203+
}
204+
packageTools = append(packageTools, &indexToolRelease{
205+
Name: name,
206+
Version: toolRelease.Version,
207+
Systems: flavours,
203208
})
204209
}
205-
packageTools = append(packageTools, &indexToolRelease{
206-
Name: name,
207-
Version: toolRelease.Version,
208-
Systems: flavours,
209-
})
210+
}
211+
return &indexPackage{
212+
Name: pack.Name,
213+
Maintainer: pack.Maintainer,
214+
WebsiteURL: pack.WebsiteURL,
215+
URL: pack.URL,
216+
Email: pack.Email,
217+
Platforms: nil,
218+
Tools: packageTools,
219+
Help: indexHelp{Online: pack.Help.Online},
220+
}
221+
}
222+
extractIndexPlatformRelease := func(pr *cores.PlatformRelease) *indexPlatformRelease {
223+
boards := []indexBoard{}
224+
for _, manifest := range pr.BoardsManifest {
225+
board := indexBoard{
226+
Name: manifest.Name,
227+
}
228+
for _, id := range manifest.ID {
229+
if id.USB != "" {
230+
board.ID = []indexBoardID{{USB: id.USB}}
231+
}
232+
}
233+
boards = append(boards, board)
234+
}
235+
236+
return &indexPlatformRelease{
237+
Name: pr.Name,
238+
Architecture: pr.Platform.Architecture,
239+
Version: pr.Version,
240+
Deprecated: pr.Deprecated,
241+
Category: pr.Category,
242+
URL: pr.Resource.URL,
243+
ArchiveFileName: pr.Resource.ArchiveFileName,
244+
Checksum: pr.Resource.Checksum,
245+
Size: json.Number(fmt.Sprintf("%d", pr.Resource.Size)),
246+
Help: indexHelp{Online: pr.Help.Online},
247+
Boards: boards,
248+
ToolDependencies: nil,
249+
DiscoveryDependencies: nil,
250+
MonitorDependencies: nil,
251+
}
252+
}
253+
254+
mainPlatform := extractIndexPlatformRelease(pr)
255+
mainPlatform.ToolDependencies = tools
256+
mainPlatform.DiscoveryDependencies = discoveries
257+
mainPlatform.MonitorDependencies = monitors
258+
delete(requiredPackages, pr.Platform.Package.Name)
259+
260+
mainPackage := extractIndexPackage(pr.Platform.Package)
261+
mainPackage.Platforms = []*indexPlatformRelease{mainPlatform}
262+
263+
packages := []*indexPackage{mainPackage}
264+
for requiredPackageName := range requiredPackages {
265+
requiredPackage, ok := pr.Platform.Package.Packages.GetPackage(requiredPackageName)
266+
if ok {
267+
packages = append(packages, extractIndexPackage(requiredPackage))
210268
}
211269
}
212270

213271
return Index{
214272
IsTrusted: pr.IsTrusted,
215-
Packages: []*indexPackage{
216-
{
217-
Name: pr.Platform.Package.Name,
218-
Maintainer: pr.Platform.Package.Maintainer,
219-
WebsiteURL: pr.Platform.Package.WebsiteURL,
220-
URL: pr.Platform.Package.URL,
221-
Email: pr.Platform.Package.Email,
222-
Platforms: []*indexPlatformRelease{{
223-
Name: pr.Name,
224-
Architecture: pr.Platform.Architecture,
225-
Version: pr.Version,
226-
Deprecated: pr.Deprecated,
227-
Category: pr.Category,
228-
URL: pr.Resource.URL,
229-
ArchiveFileName: pr.Resource.ArchiveFileName,
230-
Checksum: pr.Resource.Checksum,
231-
Size: json.Number(fmt.Sprintf("%d", pr.Resource.Size)),
232-
Boards: boards,
233-
Help: indexHelp{Online: pr.Help.Online},
234-
ToolDependencies: tools,
235-
DiscoveryDependencies: discoveries,
236-
MonitorDependencies: monitors,
237-
}},
238-
Tools: packageTools,
239-
Help: indexHelp{Online: pr.Platform.Package.Help.Online},
240-
},
241-
},
273+
Packages: packages,
242274
}
243275
}
244276

internal/arduino/cores/status.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ type Package struct {
5050
Packages Packages `json:"-"`
5151
}
5252

53+
// GetPackage returns the specified Package if it exists
54+
// and a boolean indicating whether it was found or not.
55+
func (packages Packages) GetPackage(packager string) (*Package, bool) {
56+
targetPackage, ok := packages[packager]
57+
return targetPackage, ok
58+
}
59+
5360
// GetOrCreatePackage returns the specified Package or creates an empty one
5461
// filling all the cross-references
5562
func (packages Packages) GetOrCreatePackage(packager string) *Package {

internal/arduino/sketch/profiles.go

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ type Profile struct {
119119
Libraries ProfileRequiredLibraries `yaml:"libraries"`
120120
}
121121

122+
// UsesSystemPlatform checks if this profile requires a system installed platform.
123+
func (p *Profile) RequireSystemInstalledPlatform() bool {
124+
return p.Platforms[0].RequireSystemInstalledPlatform()
125+
}
126+
122127
// ToRpc converts this Profile to an rpc.SketchProfile
123128
func (p *Profile) ToRpc() *rpc.SketchProfile {
124129
var portConfig *rpc.MonitorPortConfiguration
@@ -187,6 +192,9 @@ type ProfileRequiredLibraries []*ProfileLibraryReference
187192

188193
// AsYaml outputs the required libraries as Yaml
189194
func (p *ProfileRequiredLibraries) AsYaml() string {
195+
if len(*p) == 0 {
196+
return ""
197+
}
190198
res := " libraries:\n"
191199
for _, lib := range *p {
192200
res += lib.AsYaml()
@@ -202,6 +210,12 @@ type ProfilePlatformReference struct {
202210
PlatformIndexURL *url.URL
203211
}
204212

213+
// RequireSystemInstalledPlatform returns true if the platform reference
214+
// does not specify a version, meaning it requires the system installed platform.
215+
func (p *ProfilePlatformReference) RequireSystemInstalledPlatform() bool {
216+
return p.Version == nil
217+
}
218+
205219
// InternalUniqueIdentifier returns the unique identifier for this object
206220
func (p *ProfilePlatformReference) InternalUniqueIdentifier() string {
207221
id := p.String()
@@ -220,20 +234,38 @@ func (p *ProfilePlatformReference) String() string {
220234

221235
// AsYaml outputs the platform reference as Yaml
222236
func (p *ProfilePlatformReference) AsYaml() string {
223-
res := fmt.Sprintf(" - platform: %s:%s (%s)\n", p.Packager, p.Architecture, p.Version)
237+
res := ""
238+
if p.Version != nil {
239+
res += fmt.Sprintf(" - platform: %s:%s (%s)\n", p.Packager, p.Architecture, p.Version)
240+
} else {
241+
res += fmt.Sprintf(" - platform: %s:%s\n", p.Packager, p.Architecture)
242+
}
224243
if p.PlatformIndexURL != nil {
225244
res += fmt.Sprintf(" platform_index_url: %s\n", p.PlatformIndexURL)
226245
}
227246
return res
228247
}
229248

230249
func parseNameAndVersion(in string) (string, string, bool) {
231-
re := regexp.MustCompile(`^([a-zA-Z0-9.\-_ :]+) \((.+)\)$`)
232-
split := re.FindAllStringSubmatch(in, -1)
233-
if len(split) != 1 || len(split[0]) != 3 {
234-
return "", "", false
250+
{
251+
// Try to parse the input string in the format "VENDOR:ARCH (VERSION)"
252+
re := regexp.MustCompile(`^([a-zA-Z0-9.\-_ :]+) \((.+)\)$`)
253+
split := re.FindAllStringSubmatch(in, -1)
254+
if len(split) == 1 && len(split[0]) == 3 {
255+
return split[0][1], split[0][2], true
256+
}
257+
}
258+
259+
{
260+
// Try to parse the input string in the format "VENDOR:ARCH"
261+
re := regexp.MustCompile(`^([a-zA-Z0-9.\-_ :]+)$`)
262+
split := re.FindAllStringSubmatch(in, -1)
263+
if len(split) == 1 && len(split[0]) == 2 {
264+
return split[0][1], "", true
265+
}
235266
}
236-
return split[0][1], split[0][2], true
267+
268+
return "", "", false
237269
}
238270

239271
// UnmarshalYAML decodes a ProfilePlatformReference from YAML source.
@@ -246,14 +278,23 @@ func (p *ProfilePlatformReference) UnmarshalYAML(unmarshal func(interface{}) err
246278
return errors.New(i18n.Tr("missing '%s' directive", "platform"))
247279
} else if platformID, platformVersion, ok := parseNameAndVersion(platformID); !ok {
248280
return errors.New(i18n.Tr("invalid '%s' directive", "platform"))
249-
} else if c, err := semver.Parse(platformVersion); err != nil {
250-
return fmt.Errorf("%s: %w", i18n.Tr("error parsing version constraints"), err)
251-
} else if split := strings.SplitN(platformID, ":", 2); len(split) != 2 {
252-
return fmt.Errorf("%s: %s", i18n.Tr("invalid platform identifier"), platformID)
253281
} else {
254-
p.Packager = split[0]
255-
p.Architecture = split[1]
256-
p.Version = c
282+
var version *semver.Version
283+
if platformVersion != "" {
284+
if v, err := semver.Parse(platformVersion); err != nil {
285+
return fmt.Errorf("%s: %w", i18n.Tr("error parsing version constraints"), err)
286+
} else {
287+
version = v
288+
}
289+
}
290+
291+
if split := strings.SplitN(platformID, ":", 2); len(split) != 2 {
292+
return fmt.Errorf("%s: %s", i18n.Tr("invalid platform identifier"), platformID)
293+
} else {
294+
p.Packager = split[0]
295+
p.Architecture = split[1]
296+
p.Version = version
297+
}
257298
}
258299

259300
if rawIndexURL, ok := data["platform_index_url"]; ok {

internal/arduino/sketch/profiles_test.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package sketch
1717

1818
import (
19-
"fmt"
2019
"testing"
2120

2221
"github.com/arduino/go-paths-helper"
@@ -28,7 +27,6 @@ func TestProjectFileLoading(t *testing.T) {
2827
sketchProj := paths.New("testdata", "SketchWithProfiles", "sketch.yml")
2928
proj, err := LoadProjectFile(sketchProj)
3029
require.NoError(t, err)
31-
fmt.Println(proj)
3230
golden, err := sketchProj.ReadFile()
3331
require.NoError(t, err)
3432
require.Equal(t, proj.AsYaml(), string(golden))
@@ -37,9 +35,16 @@ func TestProjectFileLoading(t *testing.T) {
3735
sketchProj := paths.New("testdata", "SketchWithDefaultFQBNAndPort", "sketch.yml")
3836
proj, err := LoadProjectFile(sketchProj)
3937
require.NoError(t, err)
40-
fmt.Println(proj)
4138
golden, err := sketchProj.ReadFile()
4239
require.NoError(t, err)
4340
require.Equal(t, proj.AsYaml(), string(golden))
4441
}
42+
{
43+
sketchProj := paths.New("testdata", "profiles", "profile_1.yml")
44+
proj, err := LoadProjectFile(sketchProj)
45+
require.NoError(t, err)
46+
golden, err := sketchProj.ReadFile()
47+
require.NoError(t, err)
48+
require.Equal(t, string(golden), proj.AsYaml())
49+
}
4550
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
profiles:
2+
giga:
3+
fqbn: arduino:mbed_giga:giga
4+
platforms:
5+
- platform: arduino:mbed_giga (4.3.1)
6+
7+
giga_any:
8+
fqbn: arduino:mbed_giga:giga
9+
platforms:
10+
- platform: arduino:mbed_giga
11+
12+
default_profile: giga_any

0 commit comments

Comments
 (0)