Skip to content

Commit 1d604b8

Browse files
committed
Removed state-altering methods from PackageManager
They have been moved into a Builder object that has the ability to build a new PackageManager. This allows to clearly separate subrotuines that actually change the status of the PackageManager from subroutines that just need to query it.
1 parent 0a26c4a commit 1d604b8

File tree

10 files changed

+191
-137
lines changed

10 files changed

+191
-137
lines changed

Diff for: arduino/cores/packagemanager/loader.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333
)
3434

3535
// LoadHardware read all plaforms from the configured paths
36-
func (pm *PackageManager) LoadHardware() []error {
36+
func (pm *Builder) LoadHardware() []error {
3737
hardwareDirs := configuration.HardwareDirectories(configuration.Settings)
3838
merr := pm.LoadHardwareFromDirectories(hardwareDirs)
3939

@@ -44,7 +44,7 @@ func (pm *PackageManager) LoadHardware() []error {
4444
}
4545

4646
// LoadHardwareFromDirectories load plaforms from a set of directories
47-
func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []error {
47+
func (pm *Builder) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []error {
4848
var merr []error
4949
for _, path := range hardwarePaths {
5050
merr = append(merr, pm.LoadHardwareFromDirectory(path)...)
@@ -53,7 +53,7 @@ func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathLi
5353
}
5454

5555
// LoadHardwareFromDirectory read a plaform from the path passed as parameter
56-
func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
56+
func (pm *Builder) LoadHardwareFromDirectory(path *paths.Path) []error {
5757
var merr []error
5858
pm.log.Infof("Loading hardware from: %s", path)
5959
if err := path.ToAbs(); err != nil {
@@ -142,7 +142,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
142142
// loadPlatforms load plaftorms from the specified directory assuming that they belongs
143143
// to the targetPackage object passed as parameter.
144144
// A list of gRPC Status error is returned for each Platform failed to load.
145-
func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir *paths.Path) []error {
145+
func (pm *Builder) loadPlatforms(targetPackage *cores.Package, packageDir *paths.Path) []error {
146146
pm.log.Infof("Loading package %s from: %s", targetPackage.Name, packageDir)
147147

148148
var merr []error
@@ -174,7 +174,7 @@ func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir
174174
// loadPlatform loads a single platform and all its installed releases given a platformPath.
175175
// platformPath must be a directory.
176176
// Returns a gRPC Status error in case of failures.
177-
func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, architecture string, platformPath *paths.Path) error {
177+
func (pm *Builder) loadPlatform(targetPackage *cores.Package, architecture string, platformPath *paths.Path) error {
178178
// This is not a platform
179179
if platformPath.IsNotDir() {
180180
return errors.New(tr("path is not a platform directory: %s", platformPath))
@@ -279,7 +279,7 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, architectur
279279
return nil
280280
}
281281

282-
func (pm *PackageManager) loadPlatformRelease(platform *cores.PlatformRelease, path *paths.Path) error {
282+
func (pm *Builder) loadPlatformRelease(platform *cores.PlatformRelease, path *paths.Path) error {
283283
platform.InstallDir = path
284284

285285
// Some useful paths
@@ -440,14 +440,14 @@ func convertLegacyNetworkPatternToPluggableDiscovery(props *properties.Map, newT
440440
return res
441441
}
442442

443-
func (pm *PackageManager) loadProgrammer(programmerProperties *properties.Map) *cores.Programmer {
443+
func (pm *Builder) loadProgrammer(programmerProperties *properties.Map) *cores.Programmer {
444444
return &cores.Programmer{
445445
Name: programmerProperties.Get("name"),
446446
Properties: programmerProperties,
447447
}
448448
}
449449

450-
func (pm *PackageManager) loadBoards(platform *cores.PlatformRelease) error {
450+
func (pm *Builder) loadBoards(platform *cores.PlatformRelease) error {
451451
if platform.InstallDir == nil {
452452
return fmt.Errorf(tr("platform not installed"))
453453
}
@@ -591,7 +591,7 @@ func convertUploadToolsToPluggableDiscovery(props *properties.Map) {
591591

592592
// LoadToolsFromPackageDir loads a set of tools from the given toolsPath. The tools will be loaded
593593
// in the given *Package.
594-
func (pm *PackageManager) LoadToolsFromPackageDir(targetPackage *cores.Package, toolsPath *paths.Path) []error {
594+
func (pm *Builder) LoadToolsFromPackageDir(targetPackage *cores.Package, toolsPath *paths.Path) []error {
595595
pm.log.Infof("Loading tools from dir: %s", toolsPath)
596596

597597
var merr []error
@@ -612,7 +612,7 @@ func (pm *PackageManager) LoadToolsFromPackageDir(targetPackage *cores.Package,
612612
return merr
613613
}
614614

615-
func (pm *PackageManager) loadToolReleasesFromTool(tool *cores.Tool, toolPath *paths.Path) error {
615+
func (pm *Builder) loadToolReleasesFromTool(tool *cores.Tool, toolPath *paths.Path) error {
616616
toolVersions, err := toolPath.ReadDir()
617617
if err != nil {
618618
return err
@@ -629,7 +629,7 @@ func (pm *PackageManager) loadToolReleasesFromTool(tool *cores.Tool, toolPath *p
629629
return nil
630630
}
631631

632-
func (pm *PackageManager) loadToolReleaseFromDirectory(tool *cores.Tool, version *semver.RelaxedVersion, toolReleasePath *paths.Path) error {
632+
func (pm *Builder) loadToolReleaseFromDirectory(tool *cores.Tool, version *semver.RelaxedVersion, toolReleasePath *paths.Path) error {
633633
if absToolReleasePath, err := toolReleasePath.Abs(); err != nil {
634634
return errors.New(tr("error opening %s", absToolReleasePath))
635635
} else if !absToolReleasePath.IsDir() {
@@ -643,7 +643,7 @@ func (pm *PackageManager) loadToolReleaseFromDirectory(tool *cores.Tool, version
643643
}
644644

645645
// LoadToolsFromBundleDirectories FIXMEDOC
646-
func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []error {
646+
func (pm *Builder) LoadToolsFromBundleDirectories(dirs paths.PathList) []error {
647647
var merr []error
648648
for _, dir := range dirs {
649649
if err := pm.LoadToolsFromBundleDirectory(dir); err != nil {
@@ -654,7 +654,7 @@ func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []
654654
}
655655

656656
// LoadToolsFromBundleDirectory FIXMEDOC
657-
func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) error {
657+
func (pm *Builder) LoadToolsFromBundleDirectory(toolsPath *paths.Path) error {
658658
pm.log.Infof("Loading tools from bundle dir: %s", toolsPath)
659659

660660
// We scan toolsPath content to find a "builtin_tools_versions.txt", if such file exists

Diff for: arduino/cores/packagemanager/loader_test.go

+19-19
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ func TestLoadDiscoveries(t *testing.T) {
111111
fakePath := paths.New("fake-path")
112112

113113
createTestPackageManager := func() *PackageManager {
114-
packageManager := NewPackageManager(fakePath, fakePath, fakePath, fakePath, "test")
115-
pack := packageManager.Packages.GetOrCreatePackage("arduino")
114+
pmb := NewBuilder(fakePath, fakePath, fakePath, fakePath, "test")
115+
pack := pmb.Packages.GetOrCreatePackage("arduino")
116116
// ble-discovery tool
117117
tool := pack.GetOrCreateTool("ble-discovery")
118118
toolRelease := tool.GetOrCreateRelease(semver.ParseRelaxed("1.0.0"))
@@ -131,71 +131,71 @@ func TestLoadDiscoveries(t *testing.T) {
131131
release := platform.GetOrCreateRelease(semver.MustParse("1.0.0"))
132132
release.InstallDir = fakePath
133133

134-
return packageManager
134+
return pmb.Build()
135135
}
136136

137-
packageManager := createTestPackageManager()
138-
release := packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
137+
pm := createTestPackageManager()
138+
release := pm.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
139139
release.Properties = properties.NewFromHashmap(map[string]string{
140140
"pluggable_discovery.required": "arduino:ble-discovery",
141141
})
142142

143-
err := packageManager.LoadDiscoveries()
143+
err := pm.LoadDiscoveries()
144144
require.Len(t, err, 2)
145145
require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
146146
require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
147-
discoveries := packageManager.DiscoveryManager().IDs()
147+
discoveries := pm.DiscoveryManager().IDs()
148148
require.Len(t, discoveries, 1)
149149
require.Contains(t, discoveries, "arduino:ble-discovery")
150150

151-
packageManager = createTestPackageManager()
152-
release = packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
151+
pm = createTestPackageManager()
152+
release = pm.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
153153
release.Properties = properties.NewFromHashmap(map[string]string{
154154
"pluggable_discovery.required.0": "arduino:ble-discovery",
155155
"pluggable_discovery.required.1": "arduino:serial-discovery",
156156
})
157157

158-
err = packageManager.LoadDiscoveries()
158+
err = pm.LoadDiscoveries()
159159
require.Len(t, err, 2)
160160
require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
161161
require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
162-
discoveries = packageManager.DiscoveryManager().IDs()
162+
discoveries = pm.DiscoveryManager().IDs()
163163
require.Len(t, discoveries, 2)
164164
require.Contains(t, discoveries, "arduino:ble-discovery")
165165
require.Contains(t, discoveries, "arduino:serial-discovery")
166166

167-
packageManager = createTestPackageManager()
168-
release = packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
167+
pm = createTestPackageManager()
168+
release = pm.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
169169
release.Properties = properties.NewFromHashmap(map[string]string{
170170
"pluggable_discovery.required.0": "arduino:ble-discovery",
171171
"pluggable_discovery.required.1": "arduino:serial-discovery",
172172
"pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2",
173173
})
174174

175-
err = packageManager.LoadDiscoveries()
175+
err = pm.LoadDiscoveries()
176176
require.Len(t, err, 2)
177177
require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
178178
require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
179-
discoveries = packageManager.DiscoveryManager().IDs()
179+
discoveries = pm.DiscoveryManager().IDs()
180180
require.Len(t, discoveries, 3)
181181
require.Contains(t, discoveries, "arduino:ble-discovery")
182182
require.Contains(t, discoveries, "arduino:serial-discovery")
183183
require.Contains(t, discoveries, "teensy")
184184

185-
packageManager = createTestPackageManager()
186-
release = packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
185+
pm = createTestPackageManager()
186+
release = pm.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
187187
release.Properties = properties.NewFromHashmap(map[string]string{
188188
"pluggable_discovery.required": "arduino:some-discovery",
189189
"pluggable_discovery.required.0": "arduino:ble-discovery",
190190
"pluggable_discovery.required.1": "arduino:serial-discovery",
191191
"pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2",
192192
})
193193

194-
err = packageManager.LoadDiscoveries()
194+
err = pm.LoadDiscoveries()
195195
require.Len(t, err, 2)
196196
require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
197197
require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
198-
discoveries = packageManager.DiscoveryManager().IDs()
198+
discoveries = pm.DiscoveryManager().IDs()
199199
require.Len(t, discoveries, 3)
200200
require.Contains(t, discoveries, "arduino:ble-discovery")
201201
require.Contains(t, discoveries, "arduino:serial-discovery")

Diff for: arduino/cores/packagemanager/package_manager.go

+59-24
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,62 @@ type PackageManager struct {
5050
userAgent string
5151
}
5252

53+
// Builder is used to create a new PackageManager. The builder
54+
// has methods to load patforms and tools to actually build the PackageManager.
55+
// Once the PackageManager is built, it cannot be changed anymore.
56+
type Builder struct {
57+
*PackageManager
58+
}
59+
5360
var tr = i18n.Tr
5461

55-
// NewPackageManager returns a new instance of the PackageManager
56-
func NewPackageManager(indexDir, packagesDir, downloadDir, tempDir *paths.Path, userAgent string) *PackageManager {
57-
return &PackageManager{
58-
log: logrus.StandardLogger(),
59-
Packages: cores.NewPackages(),
60-
IndexDir: indexDir,
61-
PackagesDir: packagesDir,
62-
DownloadDir: downloadDir,
63-
tempDir: tempDir,
64-
CustomGlobalProperties: properties.NewMap(),
65-
discoveryManager: discoverymanager.New(),
66-
userAgent: userAgent,
62+
// NewBuilder returns a new Builder
63+
func NewBuilder(indexDir, packagesDir, downloadDir, tempDir *paths.Path, userAgent string) *Builder {
64+
return &Builder{
65+
PackageManager: &PackageManager{
66+
log: logrus.StandardLogger(),
67+
Packages: cores.NewPackages(),
68+
IndexDir: indexDir,
69+
PackagesDir: packagesDir,
70+
DownloadDir: downloadDir,
71+
tempDir: tempDir,
72+
CustomGlobalProperties: properties.NewMap(),
73+
discoveryManager: discoverymanager.New(),
74+
userAgent: userAgent,
75+
},
76+
}
77+
}
78+
79+
// BuildIntoExistingPackageManager will overwrite the give PackageManager instead
80+
// of building a new one.
81+
func (pmb *Builder) BuildIntoExistingPackageManager(old *PackageManager) {
82+
old.log = pmb.log
83+
old.Packages = pmb.Packages
84+
old.IndexDir = pmb.IndexDir
85+
old.PackagesDir = pmb.PackagesDir
86+
old.DownloadDir = pmb.DownloadDir
87+
old.tempDir = pmb.tempDir
88+
old.CustomGlobalProperties = pmb.CustomGlobalProperties
89+
old.profile = pmb.profile
90+
old.discoveryManager = pmb.discoveryManager
91+
old.userAgent = pmb.userAgent
92+
}
93+
94+
// Build builds a new PackageManager.
95+
func (pmb *Builder) Build() *PackageManager {
96+
res := &PackageManager{}
97+
pmb.BuildIntoExistingPackageManager(res)
98+
return res
99+
}
100+
101+
// NewBuilder creates a Builder with the same configuration
102+
// of this PackageManager. A "commit" function callback is returned: calling
103+
// this function will make the builder write the new configuration into this
104+
// PackageManager.
105+
func (pm *PackageManager) NewBuilder() (*Builder, func()) {
106+
pmb := NewBuilder(pm.IndexDir, pm.PackagesDir, pm.DownloadDir, pm.tempDir, pm.userAgent)
107+
return pmb, func() {
108+
pmb.BuildIntoExistingPackageManager(pm)
67109
}
68110
}
69111

@@ -83,13 +125,6 @@ func (pm *PackageManager) GetEnvVarsForSpawnedProcess() []string {
83125
}
84126
}
85127

86-
// Clear resets the PackageManager to its initial state
87-
func (pm *PackageManager) Clear() {
88-
pm.Packages = cores.NewPackages()
89-
pm.CustomGlobalProperties = properties.NewMap()
90-
pm.discoveryManager.Clear()
91-
}
92-
93128
// DiscoveryManager returns the DiscoveryManager in use by this PackageManager
94129
func (pm *PackageManager) DiscoveryManager() *discoverymanager.DiscoveryManager {
95130
return pm.discoveryManager
@@ -243,12 +278,12 @@ func (pm *PackageManager) ResolveFQBN(fqbn *cores.FQBN) (
243278
}
244279

245280
// LoadPackageIndex loads a package index by looking up the local cached file from the specified URL
246-
func (pm *PackageManager) LoadPackageIndex(URL *url.URL) error {
281+
func (pmb *Builder) LoadPackageIndex(URL *url.URL) error {
247282
indexFileName := path.Base(URL.Path)
248283
if strings.HasSuffix(indexFileName, ".tar.bz2") {
249284
indexFileName = strings.TrimSuffix(indexFileName, ".tar.bz2") + ".json"
250285
}
251-
indexPath := pm.IndexDir.Join(indexFileName)
286+
indexPath := pmb.IndexDir.Join(indexFileName)
252287
index, err := packageindex.LoadIndex(indexPath)
253288
if err != nil {
254289
return fmt.Errorf(tr("loading json index file %[1]s: %[2]s"), indexPath, err)
@@ -258,18 +293,18 @@ func (pm *PackageManager) LoadPackageIndex(URL *url.URL) error {
258293
p.URL = URL.String()
259294
}
260295

261-
index.MergeIntoPackages(pm.Packages)
296+
index.MergeIntoPackages(pmb.Packages)
262297
return nil
263298
}
264299

265300
// LoadPackageIndexFromFile load a package index from the specified file
266-
func (pm *PackageManager) LoadPackageIndexFromFile(indexPath *paths.Path) (*packageindex.Index, error) {
301+
func (pmb *Builder) LoadPackageIndexFromFile(indexPath *paths.Path) (*packageindex.Index, error) {
267302
index, err := packageindex.LoadIndex(indexPath)
268303
if err != nil {
269304
return nil, fmt.Errorf(tr("loading json index file %[1]s: %[2]s"), indexPath, err)
270305
}
271306

272-
index.MergeIntoPackages(pm.Packages)
307+
index.MergeIntoPackages(pmb.Packages)
273308
return index, nil
274309
}
275310

0 commit comments

Comments
 (0)