Unverified Commit c7163b77 authored by Cristian Maglie's avatar Cristian Maglie Committed by GitHub

[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: default avatarper1234 <accounts@perglass.com>

* Update arduino/cores/packagemanager/install_uninstall.go
Co-authored-by: default avatarper1234 <accounts@perglass.com>
Co-authored-by: default avatarper1234 <accounts@perglass.com>
parent d0b25569
......@@ -21,6 +21,7 @@ import (
"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/cores"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/pkg/errors"
"go.bug.st/downloader/v2"
semver "go.bug.st/relaxed-semver"
)
......@@ -118,13 +119,20 @@ func (pm *PackageManager) FindPlatformReleaseDependencies(item *PlatformReferenc
}
// DownloadToolRelease downloads a ToolRelease. If the tool is already downloaded a nil Downloader
// is returned.
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, label string, progressCB rpc.DownloadProgressCB) error {
// is returned. Uses the given downloader configuration for download, or the default config if nil.
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, progressCB rpc.DownloadProgressCB) error {
resource := tool.GetCompatibleFlavour()
if resource == nil {
return fmt.Errorf(tr("tool not available for your OS"))
return &arduino.FailedDownloadError{
Message: tr("Error downloading tool %s", tool),
Cause: errors.New(tr("no versions available for the current OS", tool))}
}
return resource.Download(pm.DownloadDir, config, label, progressCB)
if err := resource.Download(pm.DownloadDir, config, tool.String(), progressCB); err != nil {
return &arduino.FailedDownloadError{
Message: tr("Error downloading tool %s", tool),
Cause: err}
}
return nil
}
// DownloadPlatformRelease downloads a PlatformRelease. If the platform is already downloaded a
......
......@@ -55,7 +55,7 @@ func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathLi
// LoadHardwareFromDirectory read a plaform from the path passed as parameter
func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
var merr []error
pm.Log.Infof("Loading hardware from: %s", path)
pm.log.Infof("Loading hardware from: %s", path)
if err := path.ToAbs(); err != nil {
return append(merr, fmt.Errorf("%s: %w", tr("finding absolute path of %s", path), err))
}
......@@ -76,9 +76,9 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
// "Global" platform.txt used to overwrite all installed platforms.
// For more info: https://arduino.github.io/arduino-cli/latest/platform-specification/#global-platformtxt
if globalPlatformTxt := path.Join("platform.txt"); globalPlatformTxt.Exist() {
pm.Log.Infof("Loading custom platform properties: %s", globalPlatformTxt)
pm.log.Infof("Loading custom platform properties: %s", globalPlatformTxt)
if p, err := properties.LoadFromPath(globalPlatformTxt); err != nil {
pm.Log.WithError(err).Errorf("Error loading properties.")
pm.log.WithError(err).Errorf("Error loading properties.")
} else {
pm.CustomGlobalProperties.Merge(p)
}
......@@ -89,7 +89,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
// Skip tools, they're not packages and don't contain Platforms
if packager == "tools" {
pm.Log.Infof("Excluding directory: %s", packagerPath)
pm.log.Infof("Excluding directory: %s", packagerPath)
continue
}
......@@ -127,7 +127,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
// - PACKAGER/tools/TOOL-NAME/TOOL-VERSION/... (ex: arduino/tools/bossac/1.7.0/...)
toolsSubdirPath := packagerPath.Join("tools")
if toolsSubdirPath.IsDir() {
pm.Log.Infof("Checking existence of 'tools' path: %s", toolsSubdirPath)
pm.log.Infof("Checking existence of 'tools' path: %s", toolsSubdirPath)
merr = append(merr, pm.LoadToolsFromPackageDir(targetPackage, toolsSubdirPath)...)
}
// If the Package does not contain Platforms or Tools we remove it since does not contain anything valuable
......@@ -143,7 +143,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
// to the targetPackage object passed as parameter.
// A list of gRPC Status error is returned for each Platform failed to load.
func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir *paths.Path) []error {
pm.Log.Infof("Loading package %s from: %s", targetPackage.Name, packageDir)
pm.log.Infof("Loading package %s from: %s", targetPackage.Name, packageDir)
var merr []error
......@@ -220,11 +220,11 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, architectur
tmp := cores.NewPackages()
index.MergeIntoPackages(tmp)
if tmpPackage := tmp.GetOrCreatePackage(targetPackage.Name); tmpPackage == nil {
pm.Log.Warnf("Can't determine bundle platform version for %s", targetPackage.Name)
pm.log.Warnf("Can't determine bundle platform version for %s", targetPackage.Name)
} else if tmpPlatform := tmpPackage.GetOrCreatePlatform(architecture); tmpPlatform == nil {
pm.Log.Warnf("Can't determine bundle platform version for %s:%s", targetPackage.Name, architecture)
pm.log.Warnf("Can't determine bundle platform version for %s:%s", targetPackage.Name, architecture)
} else if tmpPlatformRelease := tmpPlatform.GetLatestRelease(); tmpPlatformRelease == nil {
pm.Log.Warnf("Can't determine bundle platform version for %s:%s, no valid release found", targetPackage.Name, architecture)
pm.log.Warnf("Can't determine bundle platform version for %s:%s, no valid release found", targetPackage.Name, architecture)
} else {
version = tmpPlatformRelease.Version
}
......@@ -239,12 +239,12 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, architectur
release := platform.GetOrCreateRelease(version)
release.IsIDEBundled = isIDEBundled
if isIDEBundled {
pm.Log.Infof("Package is built-in")
pm.log.Infof("Package is built-in")
}
if err := pm.loadPlatformRelease(release, platformPath); err != nil {
return fmt.Errorf("%s: %w", tr("loading platform release %s", release), err)
}
pm.Log.WithField("platform", release).Infof("Loaded platform")
pm.log.WithField("platform", release).Infof("Loaded platform")
} else {
// case: ARCHITECTURE/VERSION/boards.txt
......@@ -272,7 +272,7 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, architectur
if err := pm.loadPlatformRelease(release, versionDir); err != nil {
return fmt.Errorf("%s: %w", tr("loading platform release %s", release), err)
}
pm.Log.WithField("platform", release).Infof("Loaded platform")
pm.log.WithField("platform", release).Infof("Loaded platform")
}
}
......@@ -357,7 +357,7 @@ func (pm *PackageManager) loadPlatformRelease(platform *cores.PlatformRelease, p
if len(split) != 2 {
return fmt.Errorf(tr("invalid pluggable monitor reference: %s"), ref)
}
pm.Log.WithField("protocol", protocol).WithField("tool", ref).Info("Adding monitor tool")
pm.log.WithField("protocol", protocol).WithField("tool", ref).Info("Adding monitor tool")
platform.Monitors[protocol] = &cores.MonitorDependency{
Packager: split[0],
Name: split[1],
......@@ -367,7 +367,7 @@ func (pm *PackageManager) loadPlatformRelease(platform *cores.PlatformRelease, p
// Support for pluggable monitors in debugging/development environments
platform.MonitorsDevRecipes = map[string]string{}
for protocol, recipe := range platform.Properties.SubTree("pluggable_monitor.pattern").AsMap() {
pm.Log.WithField("protocol", protocol).WithField("recipe", recipe).Info("Adding monitor recipe")
pm.log.WithField("protocol", protocol).WithField("recipe", recipe).Info("Adding monitor recipe")
platform.MonitorsDevRecipes[protocol] = recipe
}
......@@ -592,7 +592,7 @@ func convertUploadToolsToPluggableDiscovery(props *properties.Map) {
// LoadToolsFromPackageDir loads a set of tools from the given toolsPath. The tools will be loaded
// in the given *Package.
func (pm *PackageManager) LoadToolsFromPackageDir(targetPackage *cores.Package, toolsPath *paths.Path) []error {
pm.Log.Infof("Loading tools from dir: %s", toolsPath)
pm.log.Infof("Loading tools from dir: %s", toolsPath)
var merr []error
......@@ -637,7 +637,7 @@ func (pm *PackageManager) loadToolReleaseFromDirectory(tool *cores.Tool, version
} else {
toolRelease := tool.GetOrCreateRelease(version)
toolRelease.InstallDir = absToolReleasePath
pm.Log.WithField("tool", toolRelease).Infof("Loaded tool")
pm.log.WithField("tool", toolRelease).Infof("Loaded tool")
return nil
}
}
......@@ -655,7 +655,7 @@ func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []
// LoadToolsFromBundleDirectory FIXMEDOC
func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) error {
pm.Log.Infof("Loading tools from bundle dir: %s", toolsPath)
pm.log.Infof("Loading tools from bundle dir: %s", toolsPath)
// We scan toolsPath content to find a "builtin_tools_versions.txt", if such file exists
// then the all the tools are available in the same directory, mixed together, and their
......@@ -689,7 +689,7 @@ func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) er
if builtinToolsVersionsTxtPath != "" {
// If builtin_tools_versions.txt is found create tools based on the info
// contained in that file
pm.Log.Infof("Found builtin_tools_versions.txt")
pm.log.Infof("Found builtin_tools_versions.txt")
toolPath, err := paths.New(builtinToolsVersionsTxtPath).Parent().Abs()
if err != nil {
return fmt.Errorf(tr("getting parent dir of %[1]s: %[2]s"), builtinToolsVersionsTxtPath, err)
......@@ -708,7 +708,7 @@ func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) er
version := semver.ParseRelaxed(toolVersion)
release := tool.GetOrCreateRelease(version)
release.InstallDir = toolPath
pm.Log.WithField("tool", release).Infof("Loaded tool")
pm.log.WithField("tool", release).Infof("Loaded tool")
}
}
} else {
......
......@@ -38,12 +38,12 @@ import (
// The manager also keeps track of the status of the Packages (their Platform Releases, actually)
// installed in the system.
type PackageManager struct {
Log logrus.FieldLogger
log logrus.FieldLogger
Packages cores.Packages
IndexDir *paths.Path
PackagesDir *paths.Path
DownloadDir *paths.Path
TempDir *paths.Path
tempDir *paths.Path
CustomGlobalProperties *properties.Map
profile *sketch.Profile
discoveryManager *discoverymanager.DiscoveryManager
......@@ -55,12 +55,12 @@ var tr = i18n.Tr
// NewPackageManager returns a new instance of the PackageManager
func NewPackageManager(indexDir, packagesDir, downloadDir, tempDir *paths.Path, userAgent string) *PackageManager {
return &PackageManager{
Log: logrus.StandardLogger(),
log: logrus.StandardLogger(),
Packages: cores.NewPackages(),
IndexDir: indexDir,
PackagesDir: packagesDir,
DownloadDir: downloadDir,
TempDir: tempDir,
tempDir: tempDir,
CustomGlobalProperties: properties.NewMap(),
discoveryManager: discoverymanager.New(),
userAgent: userAgent,
......@@ -386,7 +386,7 @@ func (pm *PackageManager) GetInstalledPlatformRelease(platform *cores.Platform)
}
debug := func(msg string, pl *cores.PlatformRelease) {
pm.Log.WithField("bundle", pl.IsIDEBundled).
pm.log.WithField("bundle", pl.IsIDEBundled).
WithField("version", pl.Version).
WithField("managed", pm.IsManagedPlatformRelease(pl)).
Debugf("%s: %s", msg, pl)
......@@ -465,7 +465,7 @@ func (pm *PackageManager) InstalledBoards() []*cores.Board {
// FindToolsRequiredFromPlatformRelease returns a list of ToolReleases needed by the specified PlatformRelease.
// If a ToolRelease is not found return an error
func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.PlatformRelease) ([]*cores.ToolRelease, error) {
pm.Log.Infof("Searching tools required for platform %s", platform)
pm.log.Infof("Searching tools required for platform %s", platform)
// maps "PACKAGER:TOOL" => ToolRelease
foundTools := map[string]*cores.ToolRelease{}
......@@ -483,7 +483,7 @@ func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.P
requiredTools := []*cores.ToolRelease{}
platform.ToolDependencies.Sort()
for _, toolDep := range platform.ToolDependencies {
pm.Log.WithField("tool", toolDep).Infof("Required tool")
pm.log.WithField("tool", toolDep).Infof("Required tool")
tool := pm.FindToolDependency(toolDep)
if tool == nil {
return nil, fmt.Errorf(tr("tool release not found: %s"), toolDep)
......@@ -494,7 +494,7 @@ func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.P
platform.DiscoveryDependencies.Sort()
for _, discoveryDep := range platform.DiscoveryDependencies {
pm.Log.WithField("discovery", discoveryDep).Infof("Required discovery")
pm.log.WithField("discovery", discoveryDep).Infof("Required discovery")
tool := pm.FindDiscoveryDependency(discoveryDep)
if tool == nil {
return nil, fmt.Errorf(tr("discovery release not found: %s"), discoveryDep)
......@@ -505,7 +505,7 @@ func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.P
platform.MonitorDependencies.Sort()
for _, monitorDep := range platform.MonitorDependencies {
pm.Log.WithField("monitor", monitorDep).Infof("Required monitor")
pm.log.WithField("monitor", monitorDep).Infof("Required monitor")
tool := pm.FindMonitorDependency(monitorDep)
if tool == nil {
return nil, fmt.Errorf(tr("monitor release not found: %s"), monitorDep)
......@@ -537,7 +537,7 @@ func (pm *PackageManager) GetTool(toolID string) *cores.Tool {
// FindToolsRequiredForBoard FIXMEDOC
func (pm *PackageManager) FindToolsRequiredForBoard(board *cores.Board) ([]*cores.ToolRelease, error) {
pm.Log.Infof("Searching tools required for board %s", board)
pm.log.Infof("Searching tools required for board %s", board)
// core := board.Properties["build.core"]
platform := board.PlatformRelease
......@@ -560,7 +560,7 @@ func (pm *PackageManager) FindToolsRequiredForBoard(board *cores.Board) ([]*core
requiredTools := []*cores.ToolRelease{}
platform.ToolDependencies.Sort()
for _, toolDep := range platform.ToolDependencies {
pm.Log.WithField("tool", toolDep).Infof("Required tool")
pm.log.WithField("tool", toolDep).Infof("Required tool")
tool := pm.FindToolDependency(toolDep)
if tool == nil {
return nil, fmt.Errorf(tr("tool release not found: %s"), toolDep)
......
......@@ -86,8 +86,8 @@ func (pm *PackageManager) loadProfilePlatform(platformRef *sketch.ProfilePlatfor
func (pm *PackageManager) installMissingProfilePlatform(platformRef *sketch.ProfilePlatformReference, destDir *paths.Path, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
// Instantiate a temporary package manager only for platform installation
_ = pm.TempDir.MkdirAll()
tmp, err := paths.MkTempDir(pm.TempDir.String(), "")
_ = pm.tempDir.MkdirAll()
tmp, err := paths.MkTempDir(pm.tempDir.String(), "")
if err != nil {
return fmt.Errorf("installing missing platform: could not create temp dir %s", err)
}
......
......@@ -21,7 +21,7 @@ import (
"github.com/arduino/arduino-cli/cli/feedback"
"github.com/arduino/arduino-cli/cli/instance"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/commands/outdated"
"github.com/arduino/arduino-cli/i18n"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/arduino/arduino-cli/table"
......@@ -50,7 +50,7 @@ func runOutdatedCommand(cmd *cobra.Command, args []string) {
inst := instance.CreateAndInit()
logrus.Info("Executing `arduino-cli outdated`")
outdatedResp, err := commands.Outdated(context.Background(), &rpc.OutdatedRequest{
outdatedResp, err := outdated.Outdated(context.Background(), &rpc.OutdatedRequest{
Instance: inst,
})
if err != nil {
......
......@@ -24,6 +24,7 @@ import (
"github.com/arduino/arduino-cli/cli/instance"
"github.com/arduino/arduino-cli/cli/output"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/commands/outdated"
"github.com/arduino/arduino-cli/i18n"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/arduino/arduino-cli/table"
......@@ -70,7 +71,7 @@ func runUpdateCommand(cmd *cobra.Command, args []string) {
feedback.Errorf(tr("Error initializing instance: %v"), err)
}
outdatedResp, err := commands.Outdated(context.Background(), &rpc.OutdatedRequest{
outdatedResp, err := outdated.Outdated(context.Background(), &rpc.OutdatedRequest{
Instance: inst,
})
if err != nil {
......
......@@ -23,7 +23,7 @@ import (
"github.com/arduino/arduino-cli/cli/feedback"
"github.com/arduino/arduino-cli/cli/instance"
"github.com/arduino/arduino-cli/cli/output"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/commands/upgrade"
"github.com/arduino/arduino-cli/i18n"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/sirupsen/logrus"
......@@ -54,7 +54,7 @@ func runUpgradeCommand(cmd *cobra.Command, args []string) {
inst := instance.CreateAndInit()
logrus.Info("Executing `arduino-cli upgrade`")
err := commands.Upgrade(context.Background(), &rpc.UpgradeRequest{
err := upgrade.Upgrade(context.Background(), &rpc.UpgradeRequest{
Instance: inst,
SkipPostInstall: postInstallFlags.DetectSkipPostInstallValue(),
}, output.NewDownloadProgressBarCB(), output.TaskProgress())
......
......@@ -17,12 +17,9 @@ package core
import (
"context"
"errors"
"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/httpclient"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/i18n"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
......@@ -52,39 +49,15 @@ func PlatformDownload(ctx context.Context, req *rpc.PlatformDownloadRequest, dow
return nil, &arduino.PlatformNotFoundError{Platform: ref.String(), Cause: err}
}
if err := downloadPlatform(pm, platform, downloadCB); err != nil {
if err := pm.DownloadPlatformRelease(platform, nil, downloadCB); err != nil {
return nil, err
}
for _, tool := range tools {
if err := downloadTool(pm, tool, downloadCB); err != nil {
if err := pm.DownloadToolRelease(tool, nil, downloadCB); err != nil {
return nil, err
}
}
return &rpc.PlatformDownloadResponse{}, nil
}
func downloadPlatform(pm *packagemanager.PackageManager, platformRelease *cores.PlatformRelease, downloadCB rpc.DownloadProgressCB) error {
// Download platform
config, err := httpclient.GetDownloaderConfig()
if err != nil {
return &arduino.FailedDownloadError{Message: tr("Error downloading platform %s", platformRelease), Cause: err}
}
return pm.DownloadPlatformRelease(platformRelease, config, downloadCB)
}
func downloadTool(pm *packagemanager.PackageManager, tool *cores.ToolRelease, downloadCB rpc.DownloadProgressCB) error {
// Check if tool has a flavor available for the current OS
if tool.GetCompatibleFlavour() == nil {
return &arduino.FailedDownloadError{
Message: tr("Error downloading tool %s", tool),
Cause: errors.New(tr("no versions available for the current OS", tool))}
}
if err := commands.DownloadToolRelease(pm, tool, downloadCB); err != nil {
return &arduino.FailedDownloadError{Message: tr("Error downloading tool %s", tool), Cause: err}
}
return nil
}
......@@ -20,7 +20,6 @@ import (
"fmt"
"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/commands"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
......@@ -64,7 +63,7 @@ func PlatformInstall(ctx context.Context, req *rpc.PlatformInstallRequest,
}
}
if err := installPlatform(pm, platformRelease, tools, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
if err := pm.DownloadAndInstallPlatformAndTools(platformRelease, tools, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
return nil, err
}
......@@ -74,115 +73,3 @@ func PlatformInstall(ctx context.Context, req *rpc.PlatformInstallRequest,
return &rpc.PlatformInstallResponse{}, nil
}
func installPlatform(pm *packagemanager.PackageManager,
platformRelease *cores.PlatformRelease, requiredTools []*cores.ToolRelease,
downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB,
skipPostInstall bool) error {
log := pm.Log.WithField("platform", platformRelease)
// Prerequisite checks before install
toolsToInstall := []*cores.ToolRelease{}
for _, tool := range requiredTools {
if tool.IsInstalled() {
log.WithField("tool", tool).Warn("Tool already installed")
taskCB(&rpc.TaskProgress{Name: tr("Tool %s already installed", tool), Completed: true})
} else {
toolsToInstall = append(toolsToInstall, tool)
}
}
// Package download
taskCB(&rpc.TaskProgress{Name: tr("Downloading packages")})
for _, tool := range toolsToInstall {
if err := downloadTool(pm, tool, downloadCB); err != nil {
return err
}
}
if err := downloadPlatform(pm, platformRelease, downloadCB); err != nil {
return err
}
taskCB(&rpc.TaskProgress{Completed: true})
// Install tools first
for _, tool := range toolsToInstall {
if err := commands.InstallToolRelease(pm, tool, taskCB); err != nil {
return err
}
}
installed := pm.GetInstalledPlatformRelease(platformRelease.Platform)
installedTools := []*cores.ToolRelease{}
if installed == nil {
// No version of this platform is installed
log.Info("Installing platform")
taskCB(&rpc.TaskProgress{Name: tr("Installing platform %s", platformRelease)})
} else {
// A platform with a different version is already installed
log.Info("Replacing platform " + installed.String())
taskCB(&rpc.TaskProgress{Name: tr("Replacing platform %[1]s with %[2]s", installed, platformRelease)})
platformRef := &packagemanager.PlatformReference{
Package: platformRelease.Platform.Package.Name,
PlatformArchitecture: platformRelease.Platform.Architecture,
PlatformVersion: installed.Version,
}
// Get a list of tools used by the currently installed platform version.
// This must be done so tools used by the currently installed version are
// removed if not used also by the newly installed version.
var err error
_, installedTools, err = pm.FindPlatformReleaseDependencies(platformRef)
if err != nil {
return &arduino.NotFoundError{Message: tr("Can't find dependencies for platform %s", platformRef), Cause: err}
}
}
// Install
if err := pm.InstallPlatform(platformRelease); err != nil {
log.WithError(err).Error("Cannot install platform")
return &arduino.FailedInstallError{Message: tr("Cannot install platform"), Cause: err}
}
// If upgrading remove previous release
if installed != nil {
uninstallErr := pm.UninstallPlatform(installed)
// In case of error try to rollback
if uninstallErr != nil {
log.WithError(uninstallErr).Error("Error upgrading platform.")
taskCB(&rpc.TaskProgress{Message: tr("Error upgrading platform: %s", uninstallErr)})
// Rollback
if err := pm.UninstallPlatform(platformRelease); err != nil {
log.WithError(err).Error("Error rolling-back changes.")
taskCB(&rpc.TaskProgress{Message: tr("Error rolling-back changes: %s", err)})
}
return &arduino.FailedInstallError{Message: tr("Cannot upgrade platform"), Cause: uninstallErr}
}
// Uninstall unused tools
for _, tool := range installedTools {
if !pm.IsToolRequired(tool) {
uninstallToolRelease(pm, tool, taskCB)
}
}
}
// Perform post install
if !skipPostInstall {
log.Info("Running post_install script")
taskCB(&rpc.TaskProgress{Message: tr("Configuring platform.")})
if err := pm.RunPostInstallScript(platformRelease); err != nil {
taskCB(&rpc.TaskProgress{Message: tr("WARNING cannot configure platform: %s", err)})
}
} else {
log.Info("Skipping platform configuration.")
taskCB(&rpc.TaskProgress{Message: tr("Skipping platform configuration.")})
}
log.Info("Platform installed")
taskCB(&rpc.TaskProgress{Message: tr("Platform %s installed", platformRelease), Completed: true})
return nil
}
......@@ -19,7 +19,6 @@ import (
"context"
"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/commands"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
......@@ -53,13 +52,14 @@ func PlatformUninstall(ctx context.Context, req *rpc.PlatformUninstallRequest, t
return nil, &arduino.NotFoundError{Message: tr("Can't find dependencies for platform %s", ref), Cause: err}
}
if err := uninstallPlatformRelease(pm, platform, taskCB); err != nil {
if err := pm.UninstallPlatform(platform, taskCB); err != nil {
return nil, err
}
for _, tool := range tools {
if !pm.IsToolRequired(tool) {
uninstallToolRelease(pm, tool, taskCB)
taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s, tool is no more required", tool)})
pm.UninstallTool(tool, taskCB)
}
}
......@@ -69,35 +69,3 @@ func PlatformUninstall(ctx context.Context, req *rpc.PlatformUninstallRequest, t
return &rpc.PlatformUninstallResponse{}, nil
}
func uninstallPlatformRelease(pm *packagemanager.PackageManager, platformRelease *cores.PlatformRelease, taskCB rpc.TaskProgressCB) error {
log := pm.Log.WithField("platform", platformRelease)
log.Info("Uninstalling platform")
taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s", platformRelease)})
if err := pm.UninstallPlatform(platformRelease); err != nil {
log.WithError(err).Error("Error uninstalling")
return &arduino.FailedUninstallError{Message: tr("Error uninstalling platform %s", platformRelease), Cause: err}
}
log.Info("Platform uninstalled")
taskCB(&rpc.TaskProgress{Message: tr("Platform %s uninstalled", platformRelease), Completed: true})
return nil
}
func uninstallToolRelease(pm *packagemanager.PackageManager, toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
log := pm.Log.WithField("Tool", toolRelease)
log.Info("Uninstalling tool")
taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s, tool is no more required", toolRelease)})
if err := pm.UninstallTool(toolRelease); err != nil {
log.WithError(err).Error("Error uninstalling")
return &arduino.FailedUninstallError{Message: tr("Error uninstalling tool %s", toolRelease), Cause: err}
}
log.Info("Tool uninstalled")
taskCB(&rpc.TaskProgress{Message: tr("Tool %s uninstalled", toolRelease), Completed: true})
return nil
}
......@@ -38,7 +38,7 @@ func PlatformUpgrade(ctx context.Context, req *rpc.PlatformUpgradeRequest,
Package: req.PlatformPackage,
PlatformArchitecture: req.Architecture,
}
if err := upgradePlatform(pm, ref, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
if err := pm.DownloadAndInstallPlatformUpgrades(ref, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
return nil, err
}
......@@ -48,35 +48,3 @@ func PlatformUpgrade(ctx context.Context, req *rpc.PlatformUpgradeRequest,
return &rpc.PlatformUpgradeResponse{}, nil
}
func upgradePlatform(pm *packagemanager.PackageManager, platformRef *packagemanager.PlatformReference,
downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB, skipPostInstall bool) error {
if platformRef.PlatformVersion != nil {
return &arduino.InvalidArgumentError{Message: tr("Upgrade doesn't accept parameters with version")}
}
// Search the latest version for all specified platforms
platform := pm.FindPlatform(platformRef)
if platform == nil {
return &arduino.PlatformNotFoundError{Platform: platformRef.String()}
}
installed := pm.GetInstalledPlatformRelease(platform)
if installed == nil {
return &arduino.PlatformNotFoundError{Platform: platformRef.String()}
}
latest := platform.GetLatestRelease()
if !latest.Version.GreaterThan(installed.Version) {
return &arduino.PlatformAlreadyAtTheLatestVersionError{}
}
platformRef.PlatformVersion = latest.Version
platformRelease, tools, err := pm.FindPlatformReleaseDependencies(platformRef)
if err != nil {
return &arduino.PlatformNotFoundError{Platform: platformRef.String()}
}
if err := installPlatform(pm, platformRelease, tools, downloadCB, taskCB, skipPostInstall); err != nil {
return err
}
return nil
}
......@@ -29,7 +29,9 @@ import (
"github.com/arduino/arduino-cli/commands/core"
"github.com/arduino/arduino-cli/commands/lib"
"github.com/arduino/arduino-cli/commands/monitor"
"github.com/arduino/arduino-cli/commands/outdated"
"github.com/arduino/arduino-cli/commands/sketch"
"github.com/arduino/arduino-cli/commands/upgrade"
"github.com/arduino/arduino-cli/commands/upload"
"github.com/arduino/arduino-cli/i18n"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
......@@ -202,13 +204,13 @@ func (s *ArduinoCoreServerImpl) UpdateCoreLibrariesIndex(req *rpc.UpdateCoreLibr
// Outdated FIXMEDOC
func (s *ArduinoCoreServerImpl) Outdated(ctx context.Context, req *rpc.OutdatedRequest) (*rpc.OutdatedResponse, error) {
resp, err := commands.Outdated(ctx, req)
resp, err := outdated.Outdated(ctx, req)
return resp, convertErrorToRPCStatus(err)
}
// Upgrade FIXMEDOC
func (s *ArduinoCoreServerImpl) Upgrade(req *rpc.UpgradeRequest, stream rpc.ArduinoCoreService_UpgradeServer) error {
err := commands.Upgrade(stream.Context(), req,
err := upgrade.Upgrade(stream.Context(), req,
func(p *rpc.DownloadProgress) {
stream.Send(&rpc.UpgradeResponse{
Progress: p,
......
This diff is collapsed.
// This file is part of arduino-cli.
//
// Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package outdated
import (
"context"
"github.com/arduino/arduino-cli/commands/core"
"github.com/arduino/arduino-cli/commands/lib"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
)
// Outdated returns a list struct containing both Core and Libraries that can be updated
func Outdated(ctx context.Context, req *rpc.OutdatedRequest) (*rpc.OutdatedResponse, error) {
libraryListResponse, err := lib.LibraryList(ctx, &rpc.LibraryListRequest{
Instance: req.GetInstance(),
Updatable: true,
})
if err != nil {
return nil, err
}
getPlatformsResp, err := core.GetPlatforms(&rpc.PlatformListRequest{
Instance: req.GetInstance(),
UpdatableOnly: true,
})
if err != nil {
return nil, err
}
return &rpc.OutdatedResponse{
OutdatedLibraries: libraryListResponse.GetInstalledLibraries(),
OutdatedPlatforms: getPlatformsResp,
}, nil
}
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
// Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
......@@ -13,44 +13,47 @@
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package commands
package upgrade
import (
"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/httpclient"
"context"
"strings"
"github.com/arduino/arduino-cli/commands/core"
"github.com/arduino/arduino-cli/commands/lib"
"github.com/arduino/arduino-cli/commands/outdated"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
)
// DownloadToolRelease downloads a ToolRelease
func DownloadToolRelease(pm *packagemanager.PackageManager, toolRelease *cores.ToolRelease, downloadCB rpc.DownloadProgressCB) error {
config, err := httpclient.GetDownloaderConfig()
// Upgrade downloads and installs outdated Cores and Libraries
func Upgrade(ctx context.Context, req *rpc.UpgradeRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
outdatedResp, err := outdated.Outdated(ctx, &rpc.OutdatedRequest{Instance: req.GetInstance()})
if err != nil {
return err
}
return pm.DownloadToolRelease(toolRelease, config, toolRelease.String(), downloadCB)
}
// InstallToolRelease installs a ToolRelease
func InstallToolRelease(pm *packagemanager.PackageManager, toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
log := pm.Log.WithField("Tool", toolRelease)
if toolRelease.IsInstalled() {
log.Warn("Tool already installed")
taskCB(&rpc.TaskProgress{Name: tr("Tool %s already installed", toolRelease), Completed: true})
return nil
for _, libToUpgrade := range outdatedResp.GetOutdatedLibraries() {
err := lib.LibraryInstall(ctx, &rpc.LibraryInstallRequest{
Instance: req.GetInstance(),
Name: libToUpgrade.GetLibrary().GetName(),
}, downloadCB, taskCB)
if err != nil {
return err
}
}
log.Info("Installing tool")
taskCB(&rpc.TaskProgress{Name: tr("Installing %s", toolRelease)})
err := pm.InstallTool(toolRelease)
if err != nil {
log.WithError(err).Warn("Cannot install tool")
return &arduino.FailedInstallError{Message: tr("Cannot install tool %s", toolRelease), Cause: err}
for _, platformToUpgrade := range outdatedResp.GetOutdatedPlatforms() {
split := strings.Split(platformToUpgrade.GetId(), ":")
_, err := core.PlatformUpgrade(ctx, &rpc.PlatformUpgradeRequest{
Instance: req.GetInstance(),
PlatformPackage: split[0],
Architecture: split[1],
SkipPostInstall: req.GetSkipPostInstall(),
}, downloadCB, taskCB)
if err != nil {
return err
}
}
log.Info("Tool installed")
taskCB(&rpc.TaskProgress{Message: tr("%s installed", toolRelease), Completed: true})
return nil
}
......@@ -2,6 +2,56 @@
Here you can find a list of migration guides to handle breaking changes between releases of the CLI.
## 0.26.0
### `github.com/arduino/arduino-cli/commands.DownloadToolRelease`, and `InstallToolRelease` functions have been removed
This functionality was duplicated and already available via `PackageManager` methods.
### `github.com/arduino/arduino-cli/commands.Outdated` and `Upgrade` functions have been moved
- `github.com/arduino/arduino-cli/commands.Outdated` is now `github.com/arduino/arduino-cli/commands/outdated.Outdated`
- `github.com/arduino/arduino-cli/commands.Upgrade` is now `github.com/arduino/arduino-cli/commands/upgrade.Upgrade`
Old code must change the imports accordingly.
### `github.com/arduino-cli/arduino/cores/packagemanager.PackageManager` methods and fields change
- The `PackageManager.Log` and `TempDir` fields are now private.
- The `PackageManager.DownloadToolRelease` method has no more the `label` parameter:
```go
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, label string, progressCB rpc.DownloadProgressCB) error {
```
has been changed to:
```go
func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, progressCB rpc.DownloadProgressCB) error {
```
Old code should remove the `label` parameter.
- The `PackageManager.UninstallPlatform`, `PackageManager.InstallTool`, and `PackageManager.UninstallTool` methods now
requires a `github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1.TaskProgressCB`
```go
func (pm *PackageManager) UninstallPlatform(platformRelease *cores.PlatformRelease) error {
func (pm *PackageManager) InstallTool(toolRelease *cores.ToolRelease) error {
func (pm *PackageManager) UninstallTool(toolRelease *cores.ToolRelease) error {
```
have been changed to:
```go
func (pm *PackageManager) UninstallPlatform(platformRelease *cores.PlatformRelease, taskCB rpc.TaskProgressCB) error {
func (pm *PackageManager) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
func (pm *PackageManager) UninstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
```
If you're not interested in getting the task events you can pass an empty callback function.
## 0.25.0
### go-lang function `github.com/arduino/arduino-cli/arduino/utils.FeedStreamTo` has been changed
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment