Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c7163b7

Browse files
cmaglieper1234
andauthoredAug 8, 2022
[skip-changelog] [breaking] Downloaders/Installers refactor (#1809)
* Made PackageManager.TempDir private * Merged InstallToolRelease function into the proper packagemanager method * Moved uninstallToolRelease into the proper packagamanger method * Moved uninstallPlatformRelease into the proper packagamanger method * Moved downloadToolRelease into the proper packagamanger method * Merged downloadTool with the proper packagamanger method * Merged downloadPlatform with the proper packagamanger method * Moved installPlatform into a packagamanger method * Moved upgradePlatform into a packagamanger method * Made PackageManager.Log field private * Removed the massive code duplication in the 'upgrade' command * Removed the massive code duplication in the 'outdated' command * Updated docs * Update arduino/cores/packagemanager/install_uninstall.go Co-authored-by: per1234 <[email protected]> * Update arduino/cores/packagemanager/install_uninstall.go Co-authored-by: per1234 <[email protected]> Co-authored-by: per1234 <[email protected]>
1 parent d0b2556 commit c7163b7

File tree

18 files changed

+432
-625
lines changed

18 files changed

+432
-625
lines changed
 

‎arduino/cores/packagemanager/download.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/arduino/arduino-cli/arduino"
2222
"github.com/arduino/arduino-cli/arduino/cores"
2323
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
24+
"github.com/pkg/errors"
2425
"go.bug.st/downloader/v2"
2526
semver "go.bug.st/relaxed-semver"
2627
)
@@ -118,13 +119,20 @@ func (pm *PackageManager) FindPlatformReleaseDependencies(item *PlatformReferenc
118119
}
119120

120121
// DownloadToolRelease downloads a ToolRelease. If the tool is already downloaded a nil Downloader
121-
// is returned.
122-
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, label string, progressCB rpc.DownloadProgressCB) error {
122+
// is returned. Uses the given downloader configuration for download, or the default config if nil.
123+
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, progressCB rpc.DownloadProgressCB) error {
123124
resource := tool.GetCompatibleFlavour()
124125
if resource == nil {
125-
return fmt.Errorf(tr("tool not available for your OS"))
126+
return &arduino.FailedDownloadError{
127+
Message: tr("Error downloading tool %s", tool),
128+
Cause: errors.New(tr("no versions available for the current OS", tool))}
126129
}
127-
return resource.Download(pm.DownloadDir, config, label, progressCB)
130+
if err := resource.Download(pm.DownloadDir, config, tool.String(), progressCB); err != nil {
131+
return &arduino.FailedDownloadError{
132+
Message: tr("Error downloading tool %s", tool),
133+
Cause: err}
134+
}
135+
return nil
128136
}
129137

130138
// DownloadPlatformRelease downloads a PlatformRelease. If the platform is already downloaded a

‎arduino/cores/packagemanager/install_uninstall.go

Lines changed: 212 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,170 @@ import (
2020
"fmt"
2121
"runtime"
2222

23+
"github.com/arduino/arduino-cli/arduino"
2324
"github.com/arduino/arduino-cli/arduino/cores"
2425
"github.com/arduino/arduino-cli/arduino/cores/packageindex"
2526
"github.com/arduino/arduino-cli/executils"
27+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
2628
"github.com/arduino/go-paths-helper"
2729
"github.com/pkg/errors"
2830
)
2931

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+
30187
// InstallPlatform installs a specific release of a platform.
31188
func (pm *PackageManager) InstallPlatform(platformRelease *cores.PlatformRelease) error {
32189
destDir := pm.PackagesDir.Join(
@@ -39,7 +196,7 @@ func (pm *PackageManager) InstallPlatform(platformRelease *cores.PlatformRelease
39196

40197
// InstallPlatformInDirectory installs a specific release of a platform in a specific directory.
41198
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 {
43200
return errors.Errorf(tr("installing platform %[1]s: %[2]s"), platformRelease, err)
44201
}
45202
if d, err := destDir.Abs(); err == nil {
@@ -109,25 +266,51 @@ func (pm *PackageManager) IsManagedPlatformRelease(platformRelease *cores.Platfo
109266
}
110267

111268
// 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+
113275
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()}
115279
}
116280

117281
// Safety measure
118282
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()}
120286
}
121287

122288
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()}
124292
}
293+
125294
platformRelease.InstallDir = nil
295+
296+
log.Info("Platform uninstalled")
297+
taskCB(&rpc.TaskProgress{Message: tr("Platform %s uninstalled", platformRelease), Completed: true})
126298
return nil
127299
}
128300

129301
// 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+
131314
toolResource := toolRelease.GetCompatibleFlavour()
132315
if toolResource == nil {
133316
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 {
137320
"tools",
138321
toolRelease.Tool.Name,
139322
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
141332
}
142333

143334
// IsManagedToolRelease returns true if the ToolRelease is managed by the PackageManager
@@ -161,20 +352,31 @@ func (pm *PackageManager) IsManagedToolRelease(toolRelease *cores.ToolRelease) b
161352
}
162353

163354
// 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+
165359
if toolRelease.InstallDir == nil {
166360
return fmt.Errorf(tr("tool not installed"))
167361
}
168362

169363
// Safety measure
170364
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
172368
}
173369

174370
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
176374
}
375+
177376
toolRelease.InstallDir = nil
377+
378+
log.Info("Tool uninstalled")
379+
taskCB(&rpc.TaskProgress{Message: tr("Tool %s uninstalled", toolRelease), Completed: true})
178380
return nil
179381
}
180382

0 commit comments

Comments
 (0)
Please sign in to comment.