Skip to content

Commit 249193a

Browse files
committed
Updated documentation
1 parent 46eeee2 commit 249193a

File tree

2 files changed

+250
-3
lines changed

2 files changed

+250
-3
lines changed

arduino/cores/packagemanager/package_manager.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,8 @@ func (pm *PackageManager) NewBuilder() (builder *Builder, commit func()) {
117117

118118
// NewExplorer creates an Explorer for this PackageManager.
119119
// The Explorer will keep a read-lock on the underlying PackageManager,
120-
// and a "release" callback function to release the lock is returned.
121-
// The "release" function must be called when the Explorer is no more
122-
// to correctly dispose it.
120+
// the user must call the "release" callback function to release the lock
121+
// when the Explorer is no more needed.
123122
func (pm *PackageManager) NewExplorer() (explorer *Explorer, release func()) {
124123
pm.packagesLock.RLock()
125124
return &Explorer{

docs/UPGRADING.md

+248
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,254 @@
22

33
Here you can find a list of migration guides to handle breaking changes between releases of the CLI.
44

5+
## 0.27.0
6+
7+
### Breaking changes in golang API `github.com/arduino/arduino-cli/arduino/cores/packagemanager.PackageManager`
8+
9+
The `PackageManager` API has been heavily refactored to correctly handle multitasking and concurrency. Many fields in the PackageManager object are now private. All the `PackageManager` methods have been moved into other objects. In particular:
10+
- the methods that query the `PackageManager` without changing its internal state, have been moved into the new `Explorer` object
11+
- the methods that change the `PackageManager` internal state, have been moved into the new `Builder` object.
12+
13+
The `Builder` object must be used to create a new `PackageManager`. Previously the function `NewPackageManager` was used to get a clean `PackageManager` object and then use the `LoadHardware*` methods to build it. Now the function `NewBuilder` must be used to create a `Builder`, run the `LoadHardware*` methods to load platforms, and finally call the `Builder.Build()` method to obtain the final `PackageManager`.
14+
15+
Previously we did:
16+
17+
```go
18+
pm := packagemanager.NewPackageManager(...)
19+
err = pm.LoadHardware()
20+
err = pm.LoadHardwareFromDirectories(...)
21+
err = pm.LoadHardwareFromDirectory(...)
22+
err = pm.LoadToolsFromPackageDir(...)
23+
err = pm.LoadToolsFromBundleDirectories(...)
24+
err = pm.LoadToolsFromBundleDirectory(...)
25+
pack = pm.GetOrCreatePackage("packagername")
26+
// ...use `pack` to tweak or load more hardware...
27+
err = pm.LoadPackageIndex(...)
28+
err = pm.LoadPackageIndexFromFile(...)
29+
err = pm.LoadHardwareForProfile(...)
30+
31+
// ...use `pm` to implement business logic...
32+
```
33+
34+
Now we must do:
35+
36+
```go
37+
var pm *packagemanager.PackageManager
38+
39+
{
40+
pmb := packagemanager.Newbuilder(...)
41+
err = pmb.LoadHardware()
42+
err = pmb.LoadHardwareFromDirectories(...)
43+
err = pmb.LoadHardwareFromDirectory(...)
44+
err = pmb.LoadToolsFromPackageDir(...)
45+
err = pmb.LoadToolsFromBundleDirectories(...)
46+
err = pmb.LoadToolsFromBundleDirectory(...)
47+
pack = pmb.GetOrCreatePackage("packagername")
48+
// ...use `pack` to tweak or load more hardware...
49+
err = pmb.LoadPackageIndex(...)
50+
err = pmb.LoadPackageIndexFromFile(...)
51+
err = pmb.LoadHardwareForProfile(...)
52+
pm = pmb.Build()
53+
}
54+
55+
// ...use `pm` to implement business logic...
56+
```
57+
58+
It's not mandatory but highly recommended, to drop the `Builder` object once it has built the `PackageManager` (that's why in the example the `pmb` builder is created in a limited scope between braces).
59+
60+
To query the `PackagerManager` now it is required to obtain an `Explorer` object through the `PackageManager.NewExplorer()` method.
61+
62+
Previously we did:
63+
64+
```go
65+
func DoStuff(pm *packagemanager.PackageManager, ...) {
66+
// ...implement business logic through PackageManager methods...
67+
... := pm.Packages
68+
... := pm.CustomGlobalProperties
69+
... := pm.FindPlatform(...)
70+
... := pm.FindPlatformRelease(...)
71+
... := pm.FindPlatformReleaseDependencies(...)
72+
... := pm.DownloadToolRelease(...)
73+
... := pm.DownloadPlatformRelease(...)
74+
... := pm.IdentifyBoard(...)
75+
... := pm.DownloadAndInstallPlatformUpgrades(...)
76+
... := pm.DownloadAndInstallPlatformAndTools(...)
77+
... := pm.InstallPlatform(...)
78+
... := pm.InstallPlatformInDirectory(...)
79+
... := pm.RunPostInstallScript(...)
80+
... := pm.IsManagedPlatformRelease(...)
81+
... := pm.UninstallPlatform(...)
82+
... := pm.InstallTool(...)
83+
... := pm.IsManagedToolRelease(...)
84+
... := pm.UninstallTool(...)
85+
... := pm.IsToolRequired(...)
86+
... := pm.LoadDiscoveries(...)
87+
... := pm.GetProfile(...)
88+
... := pm.GetEnvVarsForSpawnedProcess(...)
89+
... := pm.DiscoveryManager(...)
90+
... := pm.FindPlatformReleaseProvidingBoardsWithVidPid(...)
91+
... := pm.FindBoardsWithVidPid(...)
92+
... := pm.FindBoardsWithID(...)
93+
... := pm.FindBoardWithFQBN(...)
94+
... := pm.ResolveFQBN(...)
95+
... := pm.Package(...)
96+
... := pm.GetInstalledPlatformRelease(...)
97+
... := pm.GetAllInstalledToolsReleases(...)
98+
... := pm.InstalledPlatformReleases(...)
99+
... := pm.InstalledBoards(...)
100+
... := pm.FindToolsRequiredFromPlatformRelease(...)
101+
... := pm.GetTool(...)
102+
... := pm.FindToolsRequiredForBoard(...)
103+
... := pm.FindToolDependency(...)
104+
... := pm.FindDiscoveryDependency(...)
105+
... := pm.FindMonitorDependency(...)
106+
}
107+
```
108+
109+
Now we must obtain the `Explorer` object to access the same methods, moreover, we must call the `release` callback function once we complete the task:
110+
111+
```go
112+
func DoStuff(pm *packagemanager.PackageManager, ...) {
113+
pme, release := pm.NewExplorer()
114+
defer release()
115+
116+
... := pme.GetPackages()
117+
... := pme.GetCustomGlobalProperties()
118+
... := pme.FindPlatform(...)
119+
... := pme.FindPlatformRelease(...)
120+
... := pme.FindPlatformReleaseDependencies(...)
121+
... := pme.DownloadToolRelease(...)
122+
... := pme.DownloadPlatformRelease(...)
123+
... := pme.IdentifyBoard(...)
124+
... := pme.DownloadAndInstallPlatformUpgrades(...)
125+
... := pme.DownloadAndInstallPlatformAndTools(...)
126+
... := pme.InstallPlatform(...)
127+
... := pme.InstallPlatformInDirectory(...)
128+
... := pme.RunPostInstallScript(...)
129+
... := pme.IsManagedPlatformRelease(...)
130+
... := pme.UninstallPlatform(...)
131+
... := pme.InstallTool(...)
132+
... := pme.IsManagedToolRelease(...)
133+
... := pme.UninstallTool(...)
134+
... := pme.IsToolRequired(...)
135+
... := pme.LoadDiscoveries(...)
136+
... := pme.GetProfile(...)
137+
... := pme.GetEnvVarsForSpawnedProcess(...)
138+
... := pme.DiscoveryManager(...)
139+
... := pme.FindPlatformReleaseProvidingBoardsWithVidPid(...)
140+
... := pme.FindBoardsWithVidPid(...)
141+
... := pme.FindBoardsWithID(...)
142+
... := pme.FindBoardWithFQBN(...)
143+
... := pme.ResolveFQBN(...)
144+
... := pme.Package(...)
145+
... := pme.GetInstalledPlatformRelease(...)
146+
... := pme.GetAllInstalledToolsReleases(...)
147+
... := pme.InstalledPlatformReleases(...)
148+
... := pme.InstalledBoards(...)
149+
... := pme.FindToolsRequiredFromPlatformRelease(...)
150+
... := pme.GetTool(...)
151+
... := pme.FindToolsRequiredForBoard(...)
152+
... := pme.FindToolDependency(...)
153+
... := pme.FindDiscoveryDependency(...)
154+
... := pme.FindMonitorDependency(...)
155+
}
156+
```
157+
158+
The `Explorer` object keeps a read-lock on the underlying `PackageManager` that must be released once the task is done by calling the `release` callback function. This ensures that no other task will change the status of the `PackageManager` while the current task is in progress.
159+
160+
The `PackageManager.Clean()` method has been removed and replaced by the methods:
161+
* `PackageManager.NewBuilder() (*Builder, commit func())`
162+
* `Builder.BuildIntoExistingPackageManager(target *PackageManager)`
163+
164+
Previously, to update a `PackageManager` instance we did:
165+
166+
```go
167+
func Reload(pm *packagemanager.PackageManager) {
168+
pm.Clear()
169+
... = pm.LoadHardware(...)
170+
// ...other pm.Load* calls...
171+
}
172+
```
173+
174+
now we have two options:
175+
176+
```go
177+
func Reload(pm *packagemanager.PackageManager) {
178+
// Create a new builder and build a package manager
179+
pmb := packagemanager.NewBuilder(.../* config params */)
180+
... = pmb.LoadHardware(...)
181+
// ...other pmb.Load* calls...
182+
183+
// apply the changes to the original pm
184+
pmb.BuildIntoExistingPackageManager(pm)
185+
}
186+
```
187+
188+
in this case, we create a new `Builder` with the given config params and once the package manager is built we apply the changes atomically with `BuildIntoExistingPackageManager`. This procedure may be even more simplified with:
189+
190+
```go
191+
func Reload(pm *packagemanager.PackageManager) {
192+
// Create a new builder using the same config params
193+
// as the original package manager
194+
pmb, commit := pm.NewBuilder()
195+
196+
// build the new package manager
197+
... = pmb.LoadHardware(...)
198+
// ...other pmb.Load* calls...
199+
200+
// apply the changes to the original pm
201+
commit()
202+
}
203+
```
204+
205+
In this case, we don't even need to bother to provide the configuration parameters because they are taken from the previous `PackageManager` instance.
206+
207+
### Some gRPC-mapped methods now accepts the gRPC request instead of the instance ID as parameter
208+
209+
The following methods in subpackages of `github.com/arduino/arduino-cli/commands/*`:
210+
211+
```go
212+
func Watch(instanceID int32) (<-chan *rpc.BoardListWatchResponse, func(), error) { ... }
213+
func LibraryUpgradeAll(instanceID int32, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
214+
func LibraryUpgrade(instanceID int32, libraryNames []string, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
215+
```
216+
217+
have been changed to:
218+
219+
```go
220+
func Watch(req *rpc.BoardListWatchRequest) (<-chan *rpc.BoardListWatchResponse, func(), error) { ... ]
221+
func LibraryUpgradeAll(req *rpc.LibraryUpgradeAllRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
222+
func LibraryUpgrade(ctx context.Context, req *rpc.LibraryUpgradeRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
223+
```
224+
225+
The following methods in package `github.com/arduino/arduino-cli/commands`
226+
227+
```go
228+
func GetInstance(id int32) *CoreInstance { ... }
229+
func GetPackageManager(id int32) *packagemanager.PackageManager { ... }
230+
func GetLibraryManager(instanceID int32) *librariesmanager.LibrariesManager { ... }
231+
```
232+
233+
have been changed to:
234+
235+
```go
236+
func GetPackageManager(instance rpc.InstanceCommand) *packagemanager.PackageManager { ... } // Deprecated
237+
func GetPackageManagerExplorer(req rpc.InstanceCommand) (explorer *packagemanager.Explorer, release func()) { ... ]
238+
func GetLibraryManager(req rpc.InstanceCommand) *librariesmanager.LibrariesManager { ... }
239+
```
240+
241+
Old code using the `instanceID` inside the gRPC request, for example:
242+
243+
```go
244+
eventsChan, closeWatcher, err := board.Watch(req.Instance.Id)
245+
```
246+
247+
must be change to pass directly the gRPC request:
248+
249+
```go
250+
eventsChan, closeWatcher, err := board.Watch(msg)
251+
```
252+
5253
## 0.26.0
6254
7255
### `github.com/arduino/arduino-cli/commands.DownloadToolRelease`, and `InstallToolRelease` functions have been removed

0 commit comments

Comments
 (0)