diff --git a/cli/cli.go b/cli/cli.go index a29faa25a08..c69f9398cd5 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -35,8 +35,11 @@ import ( "github.com/arduino/arduino-cli/cli/generatedocs" "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/lib" + "github.com/arduino/arduino-cli/cli/outdated" "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/cli/sketch" + "github.com/arduino/arduino-cli/cli/update" + "github.com/arduino/arduino-cli/cli/upgrade" "github.com/arduino/arduino-cli/cli/upload" "github.com/arduino/arduino-cli/cli/version" "github.com/arduino/arduino-cli/i18n" @@ -85,7 +88,10 @@ func createCliCommandTree(cmd *cobra.Command) { cmd.AddCommand(daemon.NewCommand()) cmd.AddCommand(generatedocs.NewCommand()) cmd.AddCommand(lib.NewCommand()) + cmd.AddCommand(outdated.NewCommand()) cmd.AddCommand(sketch.NewCommand()) + cmd.AddCommand(update.NewCommand()) + cmd.AddCommand(upgrade.NewCommand()) cmd.AddCommand(upload.NewCommand()) cmd.AddCommand(debug.NewCommand()) cmd.AddCommand(burnbootloader.NewCommand()) diff --git a/cli/outdated/outdated.go b/cli/outdated/outdated.go new file mode 100644 index 00000000000..dc8b68a2ec7 --- /dev/null +++ b/cli/outdated/outdated.go @@ -0,0 +1,98 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 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" + "os" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/commands/core" + "github.com/arduino/arduino-cli/commands/lib" + rpc "github.com/arduino/arduino-cli/rpc/commands" + "github.com/arduino/arduino-cli/table" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +// NewCommand creates a new `outdated` command +func NewCommand() *cobra.Command { + outdatedCommand := &cobra.Command{ + Use: "outdated", + Short: "Lists cores and libraries that can be upgraded", + Long: "This commands shows a list of installed cores and/or libraries\n" + + "that can be upgraded. If nothing needs to be updated the output is empty.", + Example: " " + os.Args[0] + " outdated\n", + Args: cobra.NoArgs, + Run: runOutdatedCommand, + } + + return outdatedCommand +} + +func runOutdatedCommand(cmd *cobra.Command, args []string) { + inst, err := instance.CreateInstance() + if err != nil { + feedback.Errorf("Error upgrading: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + logrus.Info("Executing `arduino outdated`") + + // Gets outdated cores + targets, err := core.GetPlatforms(inst.Id, true) + if err != nil { + feedback.Errorf("Error retrieving core list: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + // Gets outdated libraries + res, err := lib.LibraryList(context.Background(), &rpc.LibraryListReq{ + Instance: inst, + All: false, + Updatable: true, + }) + if err != nil { + feedback.Errorf("Error retrieving library list: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + // Prints outdated cores + tab := table.New() + tab.SetHeader("Core name", "Installed version", "New version") + if len(targets) > 0 { + for _, t := range targets { + plat := t.Platform + tab.AddRow(plat.Name, t.Version, plat.GetLatestRelease().Version) + } + feedback.Print(tab.Render()) + } + + // Prints outdated libraries + tab = table.New() + tab.SetHeader("Library name", "Installed version", "New version") + libs := res.GetInstalledLibrary() + if len(libs) > 0 { + for _, l := range libs { + tab.AddRow(l.Library.Name, l.Library.Version, l.Release.Version) + } + feedback.Print(tab.Render()) + } + + logrus.Info("Done") +} diff --git a/cli/update/update.go b/cli/update/update.go new file mode 100644 index 00000000000..42b6280ba93 --- /dev/null +++ b/cli/update/update.go @@ -0,0 +1,118 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 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 update + +import ( + "context" + "os" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/core" + "github.com/arduino/arduino-cli/commands/lib" + rpc "github.com/arduino/arduino-cli/rpc/commands" + "github.com/arduino/arduino-cli/table" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +// NewCommand creates a new `update` command +func NewCommand() *cobra.Command { + updateCommand := &cobra.Command{ + Use: "update", + Short: "Updates the index of cores and libraries", + Long: "Updates the index of cores and libraries to the latest versions.", + Example: " " + os.Args[0] + " update", + Args: cobra.NoArgs, + Run: runUpdateCommand, + } + updateCommand.Flags().BoolVar(&updateFlags.showOutdated, "outdated", false, "Show outdated cores and libraries after index update") + return updateCommand +} + +var updateFlags struct { + showOutdated bool +} + +func runUpdateCommand(cmd *cobra.Command, args []string) { + instance := instance.CreateInstanceIgnorePlatformIndexErrors() + + logrus.Info("Executing `arduino update`") + + _, err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexReq{ + Instance: instance, + }, output.ProgressBar()) + if err != nil { + feedback.Errorf("Error updating core index: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + err = commands.UpdateLibrariesIndex(context.Background(), &rpc.UpdateLibrariesIndexReq{ + Instance: instance, + }, output.ProgressBar()) + if err != nil { + feedback.Errorf("Error updating library index: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + if updateFlags.showOutdated { + // Gets outdated cores + targets, err := core.GetPlatforms(instance.Id, true) + if err != nil { + feedback.Errorf("Error retrieving core list: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + // Gets outdated libraries + res, err := lib.LibraryList(context.Background(), &rpc.LibraryListReq{ + Instance: instance, + All: false, + Updatable: true, + }) + if err != nil { + feedback.Errorf("Error retrieving library list: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + // Prints outdated cores + tab := table.New() + tab.SetHeader("Core name", "Installed version", "New version") + if len(targets) > 0 { + for _, t := range targets { + plat := t.Platform + tab.AddRow(plat.Name, t.Version, plat.GetLatestRelease().Version) + } + feedback.Print(tab.Render()) + } + + // Prints outdated libraries + tab = table.New() + tab.SetHeader("Library name", "Installed version", "New version") + libs := res.GetInstalledLibrary() + if len(libs) > 0 { + for _, l := range libs { + tab.AddRow(l.Library.Name, l.Library.Version, l.Release.Version) + } + feedback.Print(tab.Render()) + } + + } + + logrus.Info("Done") +} diff --git a/cli/upgrade/upgrade.go b/cli/upgrade/upgrade.go new file mode 100644 index 00000000000..2a191326131 --- /dev/null +++ b/cli/upgrade/upgrade.go @@ -0,0 +1,99 @@ +// This file is part of arduino-cli. +// +// Copyright 2020 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 upgrade + +import ( + "context" + "os" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/core" + "github.com/arduino/arduino-cli/commands/lib" + rpc "github.com/arduino/arduino-cli/rpc/commands" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +// NewCommand creates a new `upgrade` command +func NewCommand() *cobra.Command { + upgradeCommand := &cobra.Command{ + Use: "upgrade", + Short: "Upgrades installed cores and libraries.", + Long: "Upgrades installed cores and libraries to latest version.", + Example: " " + os.Args[0] + " upgrade", + Args: cobra.NoArgs, + Run: runUpgradeCommand, + } + + return upgradeCommand +} + +func runUpgradeCommand(cmd *cobra.Command, args []string) { + inst, err := instance.CreateInstance() + if err != nil { + feedback.Errorf("Error upgrading: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + logrus.Info("Executing `arduino upgrade`") + + // Gets list of libraries to upgrade, cores' libraries are ignored since they're upgraded + // when the core is + res, err := lib.LibraryList(context.Background(), &rpc.LibraryListReq{ + Instance: inst, + All: false, + Updatable: true, + }) + if err != nil { + feedback.Errorf("Error retrieving library list: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + libraries := []string{} + for _, l := range res.InstalledLibrary { + libraries = append(libraries, l.Library.Name) + } + + // Upgrades libraries + err = lib.LibraryUpgrade(inst.Id, libraries, output.ProgressBar(), output.TaskProgress()) + if err != nil { + feedback.Errorf("Error upgrading libraries: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + targets, err := core.GetPlatforms(inst.Id, true) + if err != nil { + feedback.Errorf("Error retrieving core list: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + + for _, t := range targets { + r := &rpc.PlatformUpgradeReq{ + Instance: inst, + PlatformPackage: t.Platform.Package.Name, + Architecture: t.Platform.Architecture, + } + _, err := core.PlatformUpgrade(context.Background(), r, output.ProgressBar(), output.TaskProgress()) + if err != nil { + feedback.Errorf("Error during upgrade: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + } + + logrus.Info("Done") +} diff --git a/mkdocs.yml b/mkdocs.yml index 92113595dac..c5434f69349 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -96,8 +96,11 @@ nav: - lib uninstall: commands/arduino-cli_lib_uninstall.md - lib update-index: commands/arduino-cli_lib_update-index.md - lib upgrade: commands/arduino-cli_lib_upgrade.md + - outdated: commands/arduino-cli_outdated.md - sketch: commands/arduino-cli_sketch.md - sketch new: commands/arduino-cli_sketch_new.md + - update: commands/arduino-cli_update.md + - upgrade: commands/arduino-cli_upgrade.md - upload: commands/arduino-cli_upload.md - version: commands/arduino-cli_version.md - gRPC reference: diff --git a/test/test_outdated.py b/test/test_outdated.py new file mode 100644 index 00000000000..99b83ee9271 --- /dev/null +++ b/test/test_outdated.py @@ -0,0 +1,35 @@ +# This file is part of arduino-cli. +# +# Copyright 2020 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. + + +def test_outdated(run_command): + # Updates index for cores and libraries + assert run_command("core update-index") + assert run_command("lib update-index") + + # Installs an outdated core and library + assert run_command("core install arduino:avr@1.6.3") + assert run_command("lib install USBHost@1.0.0") + + # Installs latest version of a core and a library + assert run_command("core install arduino:samd") + assert run_command("lib install ArduinoJson") + + # Verifies only outdated cores and libraries are returned + result = run_command("outdated") + assert result.ok + lines = [l.strip() for l in result.stdout.splitlines()] + assert lines[1].startswith("Arduino AVR Boards") + assert lines[4].startswith("USBHost") diff --git a/test/test_update.py b/test/test_update.py new file mode 100644 index 00000000000..84b547e3784 --- /dev/null +++ b/test/test_update.py @@ -0,0 +1,49 @@ +# This file is part of arduino-cli. +# +# Copyright 2020 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. + + +def test_update(run_command): + res = run_command("update") + assert res.ok + lines = [l.strip() for l in res.stdout.splitlines()] + + assert "Updating index: package_index.json downloaded" in lines + assert "Updating index: package_index.json.sig downloaded" in lines + assert "Updating index: library_index.json downloaded" in lines + + +def test_update_showing_outdated(run_command): + # Updates index for cores and libraries + assert run_command("core update-index") + assert run_command("lib update-index") + + # Installs an outdated core and library + assert run_command("core install arduino:avr@1.6.3") + assert run_command("lib install USBHost@1.0.0") + + # Installs latest version of a core and a library + assert run_command("core install arduino:samd") + assert run_command("lib install ArduinoJson") + + # Verifies outdated cores and libraries are printed after updating indexes + result = run_command("update --outdated") + assert result.ok + lines = [l.strip() for l in result.stdout.splitlines()] + + assert "Updating index: package_index.json downloaded" in lines + assert "Updating index: package_index.json.sig downloaded" in lines + assert "Updating index: library_index.json downloaded" in lines + assert lines[-5].startswith("Arduino AVR Boards") + assert lines[-2].startswith("USBHost") diff --git a/test/test_upgrade.py b/test/test_upgrade.py new file mode 100644 index 00000000000..f90a5356520 --- /dev/null +++ b/test/test_upgrade.py @@ -0,0 +1,43 @@ +# This file is part of arduino-cli. +# +# Copyright 2020 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. + + +def test_upgrade(run_command): + # Updates index for cores and libraries + assert run_command("core update-index") + assert run_command("lib update-index") + + # Installs an outdated core and library + assert run_command("core install arduino:avr@1.6.3") + assert run_command("lib install USBHost@1.0.0") + + # Installs latest version of a core and a library + assert run_command("core install arduino:samd") + assert run_command("lib install ArduinoJson") + + # Verifies outdated core and libraries are shown + result = run_command("outdated") + assert result.ok + lines = result.stdout.splitlines() + assert lines[1].startswith("Arduino AVR Boards") + assert lines[4].startswith("USBHost") + + result = run_command("upgrade") + assert result.ok + + # Verifies cores and libraries have been updated + result = run_command("outdated") + assert result.ok + assert result.stdout == ""