@@ -20,13 +20,170 @@ import (
20
20
"fmt"
21
21
"runtime"
22
22
23
+ "github.com/arduino/arduino-cli/arduino"
23
24
"github.com/arduino/arduino-cli/arduino/cores"
24
25
"github.com/arduino/arduino-cli/arduino/cores/packageindex"
25
26
"github.com/arduino/arduino-cli/executils"
27
+ rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
26
28
"github.com/arduino/go-paths-helper"
27
29
"github.com/pkg/errors"
28
30
)
29
31
32
+ // DownloadAndInstallPlatformUpgrades runs a full installation process to upgrade the given platform.
33
+ // This method takes care of downloading missing archives, upgrading platforms and tools, and
34
+ // removing the previously installed platform/tools that are no longer needed after the upgrade.
35
+ func (pm * PackageManager ) DownloadAndInstallPlatformUpgrades (
36
+ platformRef * PlatformReference ,
37
+ downloadCB rpc.DownloadProgressCB ,
38
+ taskCB rpc.TaskProgressCB ,
39
+ skipPostInstall bool ,
40
+ ) error {
41
+ if platformRef .PlatformVersion != nil {
42
+ return & arduino.InvalidArgumentError {Message : tr ("Upgrade doesn't accept parameters with version" )}
43
+ }
44
+
45
+ // Search the latest version for all specified platforms
46
+ platform := pm .FindPlatform (platformRef )
47
+ if platform == nil {
48
+ return & arduino.PlatformNotFoundError {Platform : platformRef .String ()}
49
+ }
50
+ installed := pm .GetInstalledPlatformRelease (platform )
51
+ if installed == nil {
52
+ return & arduino.PlatformNotFoundError {Platform : platformRef .String ()}
53
+ }
54
+ latest := platform .GetLatestRelease ()
55
+ if ! latest .Version .GreaterThan (installed .Version ) {
56
+ return & arduino.PlatformAlreadyAtTheLatestVersionError {}
57
+ }
58
+ platformRef .PlatformVersion = latest .Version
59
+
60
+ platformRelease , tools , err := pm .FindPlatformReleaseDependencies (platformRef )
61
+ if err != nil {
62
+ return & arduino.PlatformNotFoundError {Platform : platformRef .String ()}
63
+ }
64
+ if err := pm .DownloadAndInstallPlatformAndTools (platformRelease , tools , downloadCB , taskCB , skipPostInstall ); err != nil {
65
+ return err
66
+ }
67
+
68
+ return nil
69
+ }
70
+
71
+ // DownloadAndInstallPlatformAndTools runs a full installation process for the given platform and tools.
72
+ // This method takes care of downloading missing archives, installing/upgrading platforms and tools, and
73
+ // removing the previously installed platform/tools that are no longer needed after the upgrade.
74
+ func (pm * PackageManager ) DownloadAndInstallPlatformAndTools (
75
+ platformRelease * cores.PlatformRelease , requiredTools []* cores.ToolRelease ,
76
+ downloadCB rpc.DownloadProgressCB , taskCB rpc.TaskProgressCB ,
77
+ skipPostInstall bool ) error {
78
+ log := pm .log .WithField ("platform" , platformRelease )
79
+
80
+ // Prerequisite checks before install
81
+ toolsToInstall := []* cores.ToolRelease {}
82
+ for _ , tool := range requiredTools {
83
+ if tool .IsInstalled () {
84
+ log .WithField ("tool" , tool ).Warn ("Tool already installed" )
85
+ taskCB (& rpc.TaskProgress {Name : tr ("Tool %s already installed" , tool ), Completed : true })
86
+ } else {
87
+ toolsToInstall = append (toolsToInstall , tool )
88
+ }
89
+ }
90
+
91
+ // Package download
92
+ taskCB (& rpc.TaskProgress {Name : tr ("Downloading packages" )})
93
+ for _ , tool := range toolsToInstall {
94
+ if err := pm .DownloadToolRelease (tool , nil , downloadCB ); err != nil {
95
+ return err
96
+ }
97
+ }
98
+ if err := pm .DownloadPlatformRelease (platformRelease , nil , downloadCB ); err != nil {
99
+ return err
100
+ }
101
+ taskCB (& rpc.TaskProgress {Completed : true })
102
+
103
+ // Install tools first
104
+ for _ , tool := range toolsToInstall {
105
+ if err := pm .InstallTool (tool , taskCB ); err != nil {
106
+ return err
107
+ }
108
+ }
109
+
110
+ installed := pm .GetInstalledPlatformRelease (platformRelease .Platform )
111
+ installedTools := []* cores.ToolRelease {}
112
+ if installed == nil {
113
+ // No version of this platform is installed
114
+ log .Info ("Installing platform" )
115
+ taskCB (& rpc.TaskProgress {Name : tr ("Installing platform %s" , platformRelease )})
116
+ } else {
117
+ // A platform with a different version is already installed
118
+ log .Info ("Replacing platform " + installed .String ())
119
+ taskCB (& rpc.TaskProgress {Name : tr ("Replacing platform %[1]s with %[2]s" , installed , platformRelease )})
120
+ platformRef := & PlatformReference {
121
+ Package : platformRelease .Platform .Package .Name ,
122
+ PlatformArchitecture : platformRelease .Platform .Architecture ,
123
+ PlatformVersion : installed .Version ,
124
+ }
125
+
126
+ // Get a list of tools used by the currently installed platform version.
127
+ // This must be done so tools used by the currently installed version are
128
+ // removed if not used also by the newly installed version.
129
+ var err error
130
+ _ , installedTools , err = pm .FindPlatformReleaseDependencies (platformRef )
131
+ if err != nil {
132
+ return & arduino.NotFoundError {Message : tr ("Can't find dependencies for platform %s" , platformRef ), Cause : err }
133
+ }
134
+ }
135
+
136
+ // Install
137
+ if err := pm .InstallPlatform (platformRelease ); err != nil {
138
+ log .WithError (err ).Error ("Cannot install platform" )
139
+ return & arduino.FailedInstallError {Message : tr ("Cannot install platform" ), Cause : err }
140
+ }
141
+
142
+ // If upgrading remove previous release
143
+ if installed != nil {
144
+ uninstallErr := pm .UninstallPlatform (installed , taskCB )
145
+
146
+ // In case of error try to rollback
147
+ if uninstallErr != nil {
148
+ log .WithError (uninstallErr ).Error ("Error upgrading platform." )
149
+ taskCB (& rpc.TaskProgress {Message : tr ("Error upgrading platform: %s" , uninstallErr )})
150
+
151
+ // Rollback
152
+ if err := pm .UninstallPlatform (platformRelease , taskCB ); err != nil {
153
+ log .WithError (err ).Error ("Error rolling-back changes." )
154
+ taskCB (& rpc.TaskProgress {Message : tr ("Error rolling-back changes: %s" , err )})
155
+ }
156
+
157
+ return & arduino.FailedInstallError {Message : tr ("Cannot upgrade platform" ), Cause : uninstallErr }
158
+ }
159
+
160
+ // Uninstall unused tools
161
+ for _ , tool := range installedTools {
162
+ taskCB (& rpc.TaskProgress {Name : tr ("Uninstalling %s, tool is no more required" , tool )})
163
+ if ! pm .IsToolRequired (tool ) {
164
+ pm .UninstallTool (tool , taskCB )
165
+ }
166
+ }
167
+
168
+ }
169
+
170
+ // Perform post install
171
+ if ! skipPostInstall {
172
+ log .Info ("Running post_install script" )
173
+ taskCB (& rpc.TaskProgress {Message : tr ("Configuring platform." )})
174
+ if err := pm .RunPostInstallScript (platformRelease ); err != nil {
175
+ taskCB (& rpc.TaskProgress {Message : tr ("WARNING cannot configure platform: %s" , err )})
176
+ }
177
+ } else {
178
+ log .Info ("Skipping platform configuration." )
179
+ taskCB (& rpc.TaskProgress {Message : tr ("Skipping platform configuration." )})
180
+ }
181
+
182
+ log .Info ("Platform installed" )
183
+ taskCB (& rpc.TaskProgress {Message : tr ("Platform %s installed" , platformRelease ), Completed : true })
184
+ return nil
185
+ }
186
+
30
187
// InstallPlatform installs a specific release of a platform.
31
188
func (pm * PackageManager ) InstallPlatform (platformRelease * cores.PlatformRelease ) error {
32
189
destDir := pm .PackagesDir .Join (
@@ -39,7 +196,7 @@ func (pm *PackageManager) InstallPlatform(platformRelease *cores.PlatformRelease
39
196
40
197
// InstallPlatformInDirectory installs a specific release of a platform in a specific directory.
41
198
func (pm * PackageManager ) InstallPlatformInDirectory (platformRelease * cores.PlatformRelease , destDir * paths.Path ) error {
42
- if err := platformRelease .Resource .Install (pm .DownloadDir , pm .TempDir , destDir ); err != nil {
199
+ if err := platformRelease .Resource .Install (pm .DownloadDir , pm .tempDir , destDir ); err != nil {
43
200
return errors .Errorf (tr ("installing platform %[1]s: %[2]s" ), platformRelease , err )
44
201
}
45
202
if d , err := destDir .Abs (); err == nil {
@@ -109,25 +266,51 @@ func (pm *PackageManager) IsManagedPlatformRelease(platformRelease *cores.Platfo
109
266
}
110
267
111
268
// UninstallPlatform remove a PlatformRelease.
112
- func (pm * PackageManager ) UninstallPlatform (platformRelease * cores.PlatformRelease ) error {
269
+ func (pm * PackageManager ) UninstallPlatform (platformRelease * cores.PlatformRelease , taskCB rpc.TaskProgressCB ) error {
270
+ log := pm .log .WithField ("platform" , platformRelease )
271
+
272
+ log .Info ("Uninstalling platform" )
273
+ taskCB (& rpc.TaskProgress {Name : tr ("Uninstalling %s" , platformRelease )})
274
+
113
275
if platformRelease .InstallDir == nil {
114
- return fmt .Errorf (tr ("platform not installed" ))
276
+ err := fmt .Errorf (tr ("platform not installed" ))
277
+ log .WithError (err ).Error ("Error uninstalling" )
278
+ return & arduino.FailedUninstallError {Message : err .Error ()}
115
279
}
116
280
117
281
// Safety measure
118
282
if ! pm .IsManagedPlatformRelease (platformRelease ) {
119
- return fmt .Errorf (tr ("%s is not managed by package manager" ), platformRelease )
283
+ err := fmt .Errorf (tr ("%s is not managed by package manager" ), platformRelease )
284
+ log .WithError (err ).Error ("Error uninstalling" )
285
+ return & arduino.FailedUninstallError {Message : err .Error ()}
120
286
}
121
287
122
288
if err := platformRelease .InstallDir .RemoveAll (); err != nil {
123
- return fmt .Errorf (tr ("removing platform files: %s" ), err )
289
+ err = fmt .Errorf (tr ("removing platform files: %s" ), err )
290
+ log .WithError (err ).Error ("Error uninstalling" )
291
+ return & arduino.FailedUninstallError {Message : err .Error ()}
124
292
}
293
+
125
294
platformRelease .InstallDir = nil
295
+
296
+ log .Info ("Platform uninstalled" )
297
+ taskCB (& rpc.TaskProgress {Message : tr ("Platform %s uninstalled" , platformRelease ), Completed : true })
126
298
return nil
127
299
}
128
300
129
301
// InstallTool installs a specific release of a tool.
130
- func (pm * PackageManager ) InstallTool (toolRelease * cores.ToolRelease ) error {
302
+ func (pm * PackageManager ) InstallTool (toolRelease * cores.ToolRelease , taskCB rpc.TaskProgressCB ) error {
303
+ log := pm .log .WithField ("Tool" , toolRelease )
304
+
305
+ if toolRelease .IsInstalled () {
306
+ log .Warn ("Tool already installed" )
307
+ taskCB (& rpc.TaskProgress {Name : tr ("Tool %s already installed" , toolRelease ), Completed : true })
308
+ return nil
309
+ }
310
+
311
+ log .Info ("Installing tool" )
312
+ taskCB (& rpc.TaskProgress {Name : tr ("Installing %s" , toolRelease )})
313
+
131
314
toolResource := toolRelease .GetCompatibleFlavour ()
132
315
if toolResource == nil {
133
316
return fmt .Errorf (tr ("no compatible version of %s tools found for the current os" ), toolRelease .Tool .Name )
@@ -137,7 +320,15 @@ func (pm *PackageManager) InstallTool(toolRelease *cores.ToolRelease) error {
137
320
"tools" ,
138
321
toolRelease .Tool .Name ,
139
322
toolRelease .Version .String ())
140
- return toolResource .Install (pm .DownloadDir , pm .TempDir , destDir )
323
+ err := toolResource .Install (pm .DownloadDir , pm .tempDir , destDir )
324
+ if err != nil {
325
+ log .WithError (err ).Warn ("Cannot install tool" )
326
+ return & arduino.FailedInstallError {Message : tr ("Cannot install tool %s" , toolRelease ), Cause : err }
327
+ }
328
+ log .Info ("Tool installed" )
329
+ taskCB (& rpc.TaskProgress {Message : tr ("%s installed" , toolRelease ), Completed : true })
330
+
331
+ return nil
141
332
}
142
333
143
334
// IsManagedToolRelease returns true if the ToolRelease is managed by the PackageManager
@@ -161,20 +352,31 @@ func (pm *PackageManager) IsManagedToolRelease(toolRelease *cores.ToolRelease) b
161
352
}
162
353
163
354
// UninstallTool remove a ToolRelease.
164
- func (pm * PackageManager ) UninstallTool (toolRelease * cores.ToolRelease ) error {
355
+ func (pm * PackageManager ) UninstallTool (toolRelease * cores.ToolRelease , taskCB rpc.TaskProgressCB ) error {
356
+ log := pm .log .WithField ("Tool" , toolRelease )
357
+ log .Info ("Uninstalling tool" )
358
+
165
359
if toolRelease .InstallDir == nil {
166
360
return fmt .Errorf (tr ("tool not installed" ))
167
361
}
168
362
169
363
// Safety measure
170
364
if ! pm .IsManagedToolRelease (toolRelease ) {
171
- return fmt .Errorf (tr ("tool %s is not managed by package manager" ), toolRelease )
365
+ err := & arduino.FailedUninstallError {Message : tr ("tool %s is not managed by package manager" , toolRelease )}
366
+ log .WithError (err ).Error ("Error uninstalling" )
367
+ return err
172
368
}
173
369
174
370
if err := toolRelease .InstallDir .RemoveAll (); err != nil {
175
- return fmt .Errorf (tr ("removing tool files: %s" ), err )
371
+ err = & arduino.FailedUninstallError {Message : err .Error ()}
372
+ log .WithError (err ).Error ("Error uninstalling" )
373
+ return err
176
374
}
375
+
177
376
toolRelease .InstallDir = nil
377
+
378
+ log .Info ("Tool uninstalled" )
379
+ taskCB (& rpc.TaskProgress {Message : tr ("Tool %s uninstalled" , toolRelease ), Completed : true })
178
380
return nil
179
381
}
180
382
0 commit comments