From d6196c1b9bb4cb3d2156c72b7822cc73123137e5 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 20 Feb 2023 10:19:32 +0100 Subject: [PATCH 1/4] Added `--install-in-builtin-dir` flag to `lib install` command (#2077) * In download query, report if a library is builtin * 'lib download' flag vars are now local * Added --install-in-builtin-dir flag in 'lib install' --- commands/lib/install.go | 3 ++ internal/cli/lib/install.go | 38 +++++++++++++++--------- internal/integrationtest/lib/lib_test.go | 14 +++++++++ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/commands/lib/install.go b/commands/lib/install.go index 5ace0cddfd0..e106981e60c 100644 --- a/commands/lib/install.go +++ b/commands/lib/install.go @@ -103,6 +103,9 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa if installTask.ReplacedLib != nil { downloadReason = "upgrade" } + if installLocation == libraries.IDEBuiltIn { + downloadReason += "-builtin" + } } if err := downloadLibrary(lm, libRelease, downloadCB, taskCB, downloadReason); err != nil { return err diff --git a/internal/cli/lib/install.go b/internal/cli/lib/install.go index bb6ff217fda..549f4d7c328 100644 --- a/internal/cli/lib/install.go +++ b/internal/cli/lib/install.go @@ -34,14 +34,12 @@ import ( semver "go.bug.st/relaxed-semver" ) -var ( - noDeps bool - noOverwrite bool - gitURL bool - zipPath bool -) - func initInstallCommand() *cobra.Command { + var noDeps bool + var noOverwrite bool + var gitURL bool + var zipPath bool + var useBuiltinLibrariesDir bool installCommand := &cobra.Command{ Use: fmt.Sprintf("install %s[@%s]...", tr("LIBRARY"), tr("VERSION_NUMBER")), Short: tr("Installs one or more specified libraries into the system."), @@ -53,7 +51,9 @@ func initInstallCommand() *cobra.Command { " " + os.Args[0] + " lib install --git-url https://github.com/arduino-libraries/WiFi101.git#0.16.0 # " + tr("for the specific version.") + "\n" + " " + os.Args[0] + " lib install --zip-path /path/to/WiFi101.zip /path/to/ArduinoBLE.zip\n", Args: cobra.MinimumNArgs(1), - Run: runInstallCommand, + Run: func(cmd *cobra.Command, args []string) { + runInstallCommand(args, noDeps, noOverwrite, gitURL, zipPath, useBuiltinLibrariesDir) + }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return arguments.GetInstallableLibs(), cobra.ShellCompDirectiveDefault }, @@ -62,10 +62,11 @@ func initInstallCommand() *cobra.Command { installCommand.Flags().BoolVar(&noOverwrite, "no-overwrite", false, tr("Do not overwrite already installed libraries.")) installCommand.Flags().BoolVar(&gitURL, "git-url", false, tr("Enter git url for libraries hosted on repositories")) installCommand.Flags().BoolVar(&zipPath, "zip-path", false, tr("Enter a path to zip file")) + installCommand.Flags().BoolVar(&useBuiltinLibrariesDir, "install-in-builtin-dir", false, tr("Install libraries in the IDE-Builtin directory")) return installCommand } -func runInstallCommand(cmd *cobra.Command, args []string) { +func runInstallCommand(args []string, noDeps bool, noOverwrite bool, gitURL bool, zipPath bool, useBuiltinLibrariesDir bool) { instance := instance.CreateAndInit() logrus.Info("Executing `arduino-cli lib install`") @@ -80,6 +81,10 @@ func runInstallCommand(cmd *cobra.Command, args []string) { feedback.Fatal(tr("--git-url and --zip-path are disabled by default, for more information see: %v", documentationURL), feedback.ErrGeneric) } feedback.Print(tr("--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")) + + if useBuiltinLibrariesDir { + feedback.Fatal(tr("--git-url or --zip-path can't be used with --install-in-builtin-dir"), feedback.ErrGeneric) + } } if zipPath { @@ -123,12 +128,17 @@ func runInstallCommand(cmd *cobra.Command, args []string) { } for _, libRef := range libRefs { + installLocation := rpc.LibraryInstallLocation_LIBRARY_INSTALL_LOCATION_USER + if useBuiltinLibrariesDir { + installLocation = rpc.LibraryInstallLocation_LIBRARY_INSTALL_LOCATION_BUILTIN + } libraryInstallRequest := &rpc.LibraryInstallRequest{ - Instance: instance, - Name: libRef.Name, - Version: libRef.Version, - NoDeps: noDeps, - NoOverwrite: noOverwrite, + Instance: instance, + Name: libRef.Name, + Version: libRef.Version, + NoDeps: noDeps, + NoOverwrite: noOverwrite, + InstallLocation: installLocation, } err := lib.LibraryInstall(context.Background(), libraryInstallRequest, feedback.ProgressBar(), feedback.TaskProgress()) if err != nil { diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go index 49352790a41..8cbae1af5de 100644 --- a/internal/integrationtest/lib/lib_test.go +++ b/internal/integrationtest/lib/lib_test.go @@ -1518,4 +1518,18 @@ func TestLibQueryParameters(t *testing.T) { require.NoError(t, err) require.Contains(t, string(stdout), "Starting download \x1b[36murl\x1b[0m=\"https://downloads.arduino.cc/libraries/github.com/arduino-libraries/WiFi101-0.16.1.zip?query=download\"\n") + + // Check query=install-builtin when a library dependency is installed in builtin-directory + cliEnv := cli.GetDefaultEnv() + cliEnv["ARDUINO_DIRECTORIES_BUILTIN_LIBRARIES"] = cli.DataDir().Join("libraries").String() + stdout, _, err = cli.RunWithCustomEnv(cliEnv, "lib", "install", "Firmata@2.5.3", "--install-in-builtin-dir", "-v", "--log-level", "debug") + require.NoError(t, err) + require.Contains(t, string(stdout), + "Starting download \x1b[36murl\x1b[0m=\"https://downloads.arduino.cc/libraries/github.com/firmata/Firmata-2.5.3.zip?query=install-builtin\"\n") + + // Check query=update-builtin when a library dependency is updated in builtin-directory + stdout, _, err = cli.RunWithCustomEnv(cliEnv, "lib", "install", "Firmata@2.5.9", "--install-in-builtin-dir", "-v", "--log-level", "debug") + require.NoError(t, err) + require.Contains(t, string(stdout), + "Starting download \x1b[36murl\x1b[0m=\"https://downloads.arduino.cc/libraries/github.com/firmata/Firmata-2.5.9.zip?query=upgrade-builtin\"\n") } From f9d139aa373e7aa91903b1051d57c208d06ee3c0 Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Tue, 14 Feb 2023 14:25:31 +0100 Subject: [PATCH 2/4] Add post install script support for tools --- .../cores/packagemanager/install_uninstall.go | 36 +++++++++++++------ commands/instances.go | 2 +- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/arduino/cores/packagemanager/install_uninstall.go b/arduino/cores/packagemanager/install_uninstall.go index 4ab87361111..87beee0a472 100644 --- a/arduino/cores/packagemanager/install_uninstall.go +++ b/arduino/cores/packagemanager/install_uninstall.go @@ -102,7 +102,7 @@ func (pme *Explorer) DownloadAndInstallPlatformAndTools( // Install tools first for _, tool := range toolsToInstall { - if err := pme.InstallTool(tool, taskCB); err != nil { + if err := pme.InstallTool(tool, taskCB, skipPostInstall); err != nil { return err } } @@ -171,7 +171,10 @@ func (pme *Explorer) DownloadAndInstallPlatformAndTools( if !skipPostInstall { log.Info("Running post_install script") taskCB(&rpc.TaskProgress{Message: tr("Configuring platform.")}) - if err := pme.RunPostInstallScript(platformRelease); err != nil { + if !platformRelease.IsInstalled() { + return errors.New(tr("platform not installed")) + } + if err := pme.RunPostInstallScript(platformRelease.InstallDir); err != nil { taskCB(&rpc.TaskProgress{Message: tr("WARNING cannot configure platform: %s", err)}) } } else { @@ -222,22 +225,19 @@ func (pme *Explorer) cacheInstalledJSON(platformRelease *cores.PlatformRelease) } // RunPostInstallScript runs the post_install.sh (or post_install.bat) script for the -// specified platformRelease. -func (pme *Explorer) RunPostInstallScript(platformRelease *cores.PlatformRelease) error { - if !platformRelease.IsInstalled() { - return errors.New(tr("platform not installed")) - } +// specified platformRelease or toolRelease. +func (pme *Explorer) RunPostInstallScript(installDir *paths.Path) error { postInstallFilename := "post_install.sh" if runtime.GOOS == "windows" { postInstallFilename = "post_install.bat" } - postInstall := platformRelease.InstallDir.Join(postInstallFilename) + postInstall := installDir.Join(postInstallFilename) if postInstall.Exist() && postInstall.IsNotDir() { cmd, err := executils.NewProcessFromPath(pme.GetEnvVarsForSpawnedProcess(), postInstall) if err != nil { return err } - cmd.SetDirFromPath(platformRelease.InstallDir) + cmd.SetDirFromPath(installDir) if err := cmd.Run(); err != nil { return err } @@ -299,7 +299,7 @@ func (pme *Explorer) UninstallPlatform(platformRelease *cores.PlatformRelease, t } // InstallTool installs a specific release of a tool. -func (pme *Explorer) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error { +func (pme *Explorer) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB, skipPostInstall bool) error { log := pme.log.WithField("Tool", toolRelease) if toolRelease.IsInstalled() { @@ -325,6 +325,22 @@ func (pme *Explorer) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc.Task log.WithError(err).Warn("Cannot install tool") return &arduino.FailedInstallError{Message: tr("Cannot install tool %s", toolRelease), Cause: err} } + if d, err := destDir.Abs(); err == nil { + toolRelease.InstallDir = d + } else { + return err + } + // Perform post install + if !skipPostInstall { + log.Info("Running tool post_install script") + taskCB(&rpc.TaskProgress{Message: tr("Configuring tool.")}) + if err := pme.RunPostInstallScript(toolRelease.InstallDir); err != nil { + taskCB(&rpc.TaskProgress{Message: tr("WARNING cannot configure tool: %s", err)}) + } + } else { + log.Info("Skipping tool configuration.") + taskCB(&rpc.TaskProgress{Message: tr("Skipping tool configuration.")}) + } log.Info("Tool installed") taskCB(&rpc.TaskProgress{Message: tr("%s installed", toolRelease), Completed: true}) diff --git a/commands/instances.go b/commands/instances.go index ddd7a58452e..4bd1cec9e8d 100644 --- a/commands/instances.go +++ b/commands/instances.go @@ -138,7 +138,7 @@ func installTool(pm *packagemanager.PackageManager, tool *cores.ToolRelease, dow return fmt.Errorf(tr("downloading %[1]s tool: %[2]s"), tool, err) } taskCB(&rpc.TaskProgress{Completed: true}) - if err := pme.InstallTool(tool, taskCB); err != nil { + if err := pme.InstallTool(tool, taskCB, true); err != nil { return fmt.Errorf(tr("installing %[1]s tool: %[2]s"), tool, err) } return nil From 748c4390565de93a8b9da58032c0877701928aed Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Tue, 14 Feb 2023 14:37:51 +0100 Subject: [PATCH 3/4] Add TestCoreInstallRunsToolPostInstallScript to core_test.go --- internal/integrationtest/core/core_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/integrationtest/core/core_test.go b/internal/integrationtest/core/core_test.go index 94e47b374f9..98117009724 100644 --- a/internal/integrationtest/core/core_test.go +++ b/internal/integrationtest/core/core_test.go @@ -992,3 +992,18 @@ func TestCoreInstallCreatesInstalledJson(t *testing.T) { sortedExpected := requirejson.Parse(t, expectedInstalledJson).Query("walk(if type == \"array\" then sort else . end)").String() require.JSONEq(t, sortedExpected, sortedInstalled) } + +func TestCoreInstallRunsToolPostInstallScript(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + url := "http://drazzy.com/package_drazzy.com_index.json" + + _, _, err := cli.Run("core", "update-index", "--additional-urls", url) + require.NoError(t, err) + + // Checks that the post_install script is correctly skipped on the CI + stdout, _, err := cli.Run("core", "install", "ATTinyCore:avr", "--verbose", "--additional-urls", url) + require.NoError(t, err) + require.Contains(t, string(stdout), "Skipping tool configuration.") +} From 81b6f64953d5643822d828f53b426d86de2a9b25 Mon Sep 17 00:00:00 2001 From: Matteo Pologruto Date: Mon, 20 Feb 2023 10:19:53 +0100 Subject: [PATCH 4/4] Document changes in UPGRADING.md --- docs/UPGRADING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index 0d867fe05db..5d14fcab452 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -2,6 +2,12 @@ Here you can find a list of migration guides to handle breaking changes between releases of the CLI. +## 0.31.0 + +### Added `post_install` script support for tools + +The `post_install` script now runs when a tool is correctly installed and the CLI is in "interactive" mode. This behavior can be [configured](https://arduino.github.io/arduino-cli/0.30/commands/arduino-cli_core_install/#options). + ## 0.30.0 ### Sketch name validation