From 9cac9264914c5ce7fd739964ad6eccac5c2d7a27 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 9 Nov 2022 17:50:47 +0100 Subject: [PATCH 01/13] Remove useless logging The errors are already reported upstream via returned `err` value --- arduino/libraries/librariesmanager/install.go | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index 5baa17e3d94..8af8840d4ed 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -29,7 +29,6 @@ import ( "github.com/arduino/arduino-cli/arduino/utils" paths "github.com/arduino/go-paths-helper" "github.com/codeclysm/extract/v3" - "github.com/sirupsen/logrus" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" ) @@ -175,19 +174,9 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath strin if !overwrite { return fmt.Errorf(tr("library %s already installed"), libraryName) } - logrus. - WithField("library name", libraryName). - WithField("install path", installPath). - Trace("Deleting library") installPath.RemoveAll() } - logrus. - WithField("library name", libraryName). - WithField("install path", installPath). - WithField("zip file", archivePath). - Trace("Installing library") - // Copy extracted library in the destination directory if err := extractionPath.CopyDirTo(installPath); err != nil { return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err) @@ -205,9 +194,6 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { libraryName, ref, err := parseGitURL(gitURL) if err != nil { - logrus. - WithError(err). - Warn("Parsing git URL") return err } @@ -217,22 +203,12 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { if !overwrite { return fmt.Errorf(tr("library %s already installed"), libraryName) } - logrus. - WithField("library name", libraryName). - WithField("install path", installPath). - Trace("Deleting library") installPath.RemoveAll() } if installPath.Exist() { return fmt.Errorf(tr("could not create directory %s: a file with the same name exists!", installPath)) } - logrus. - WithField("library name", libraryName). - WithField("install path", installPath). - WithField("git url", gitURL). - Trace("Installing library") - depth := 1 if ref != "" { depth = 0 @@ -243,27 +219,15 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { Progress: os.Stdout, }) if err != nil { - logrus. - WithError(err). - Warn("Cloning git repository") return err } if ref != "" { if h, err := repo.ResolveRevision(ref); err != nil { - logrus. - WithError(err). - Warnf("Resolving revision %s", ref) return err } else if w, err := repo.Worktree(); err != nil { - logrus. - WithError(err). - Warn("Finding worktree") return err } else if err := w.Checkout(&git.CheckoutOptions{Hash: plumbing.NewHash(h.String())}); err != nil { - logrus. - WithError(err). - Warnf("Checking out %s", h) return err } } From 1485b91d927a14fe8d54984df167957672375d30 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 9 Nov 2022 18:04:09 +0100 Subject: [PATCH 02/13] librariesmanager.InstallPrerequisiteCheck signature change It now accepts library name and version as single arguments since we are going to use this function also for libraries not present in the index. --- arduino/libraries/librariesmanager/install.go | 8 ++++---- commands/lib/install.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index 8af8840d4ed..693161b7368 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -29,6 +29,7 @@ import ( "github.com/arduino/arduino-cli/arduino/utils" paths "github.com/arduino/go-paths-helper" "github.com/codeclysm/extract/v3" + semver "go.bug.st/relaxed-semver" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" ) @@ -48,7 +49,7 @@ var ( // InstallPrerequisiteCheck performs prequisite checks to install a library. It returns the // install path, where the library should be installed and the possible library that is already // installed on the same folder and it's going to be replaced by the new one. -func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesindex.Release, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) { +func (lm *LibrariesManager) InstallPrerequisiteCheck(name string, version *semver.Version, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) { installDir := lm.getLibrariesDir(installLocation) if installDir == nil { if installLocation == libraries.User { @@ -57,10 +58,9 @@ func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesinde return nil, nil, fmt.Errorf(tr("Builtin libraries directory not set")) } - name := indexLibrary.Library.Name libs := lm.FindByReference(&librariesindex.Reference{Name: name}, installLocation) for _, lib := range libs { - if lib.Version != nil && lib.Version.Equal(indexLibrary.Version) { + if lib.Version != nil && lib.Version.Equal(version) { return lib.InstallDir, nil, ErrAlreadyInstalled } } @@ -82,7 +82,7 @@ func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesinde replaced = libs[0] } - libPath := installDir.Join(utils.SanitizeName(indexLibrary.Library.Name)) + libPath := installDir.Join(utils.SanitizeName(name)) if replaced != nil && replaced.InstallDir.EquivalentTo(libPath) { return libPath, replaced, nil } else if libPath.IsDir() { diff --git a/commands/lib/install.go b/commands/lib/install.go index 0a82c9d074d..1e24e6b191d 100644 --- a/commands/lib/install.go +++ b/commands/lib/install.go @@ -82,7 +82,7 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa // Check if any of the libraries to install is already installed and remove it from the list j := 0 for i, libRelease := range libReleasesToInstall { - _, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease, installLocation) + _, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease.Library.Name, libRelease.Version, installLocation) if errors.Is(err, librariesmanager.ErrAlreadyInstalled) { taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true}) } else if err != nil { @@ -127,7 +127,7 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *librariesindex.Release, installLocation libraries.LibraryLocation, taskCB rpc.TaskProgressCB) error { taskCB(&rpc.TaskProgress{Name: tr("Installing %s", libRelease)}) logrus.WithField("library", libRelease).Info("Installing library") - libPath, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease, installLocation) + libPath, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease.Library.Name, libRelease.Version, installLocation) if errors.Is(err, librariesmanager.ErrAlreadyInstalled) { taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true}) return err From a67171cd18dd08890e8e399f935c424a9020b862 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 9 Nov 2022 18:26:22 +0100 Subject: [PATCH 03/13] Added integration test --- internal/integrationtest/lib/lib_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go index 435d26acf03..43eb8e81dfb 100644 --- a/internal/integrationtest/lib/lib_test.go +++ b/internal/integrationtest/lib/lib_test.go @@ -145,6 +145,27 @@ func TestDuplicateLibInstallDetection(t *testing.T) { require.Contains(t, string(stdErr), "The library ArduinoOTA has multiple installations") } +func TestDuplicateLibInstallFromGitDetection(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + cliEnv := cli.GetDefaultEnv() + cliEnv["ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL"] = "true" + + // Make a double install in the sketchbook/user directory + _, _, err := cli.Run("lib", "install", "Arduino SigFox for MKRFox1200") + require.NoError(t, err) + + _, _, err = cli.RunWithCustomEnv(cliEnv, "lib", "install", "--git-url", "https://github.com/arduino-libraries/SigFox#1.0.3") + require.NoError(t, err) + + jsonOut, _, err := cli.Run("lib", "list", "--format", "json") + require.NoError(t, err) + // Count how many libraries with the name "Arduino SigFox for MKRFox1200" are installed + requirejson.Parse(t, jsonOut). + Query(`[.[].library.name | select(. == "Arduino SigFox for MKRFox1200")]`). + LengthMustEqualTo(1, "Found multiple installations of Arduino SigFox for MKRFox1200'") +} + func TestLibDepsOutput(t *testing.T) { env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) defer env.CleanUp() From c9fc668de2c558f0e05e986c3c6532c555cf5902 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 9 Nov 2022 18:22:20 +0100 Subject: [PATCH 04/13] Fixed `lib install --git-url` pre-install checks Now it performs all the needed checks to avoid multiple installations. --- arduino/libraries/librariesmanager/install.go | 69 ++++++++++++++----- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index 693161b7368..635b3fb4980 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -17,6 +17,7 @@ package librariesmanager import ( "context" + "errors" "fmt" "net/url" "os" @@ -192,28 +193,24 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { return fmt.Errorf(tr("User directory not set")) } - libraryName, ref, err := parseGitURL(gitURL) + gitLibraryName, ref, err := parseGitURL(gitURL) if err != nil { return err } - // Deletes libraries folder if already installed - installPath := installDir.Join(libraryName) - if installPath.IsDir() { - if !overwrite { - return fmt.Errorf(tr("library %s already installed"), libraryName) - } - installPath.RemoveAll() - } - if installPath.Exist() { - return fmt.Errorf(tr("could not create directory %s: a file with the same name exists!", installPath)) + // Clone library in a temporary directory + tmp, err := paths.MkTempDir("", "") + if err != nil { + return err } + defer tmp.RemoveAll() + tmpInstallPath := tmp.Join(gitLibraryName) depth := 1 if ref != "" { depth = 0 } - repo, err := git.PlainClone(installPath.String(), false, &git.CloneOptions{ + repo, err := git.PlainClone(tmpInstallPath.String(), false, &git.CloneOptions{ URL: gitURL, Depth: depth, Progress: os.Stdout, @@ -232,14 +229,52 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { } } - if err := validateLibrary(installPath); err != nil { - // Clean up installation directory since this is not a valid library - installPath.RemoveAll() + // We don't want the installed library to be a git repository thus we delete this folder + tmpInstallPath.Join(".git").RemoveAll() + + // Check if the library is valid and load metatada + if err := validateLibrary(tmpInstallPath); err != nil { + return err + } + library, err := libraries.Load(tmpInstallPath, libraries.User) + if err != nil { return err } - // We don't want the installed library to be a git repository thus we delete this folder - installPath.Join(".git").RemoveAll() + // Check if the library is already installed and determine install path + var installPath *paths.Path + libInstalled, libReplaced, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) + if errors.Is(err, ErrAlreadyInstalled) { + if !overwrite { + return fmt.Errorf(tr("library %s already installed"), library.Name) + } + installPath = libInstalled + } else if err != nil { + return err + } else if libReplaced != nil { + if !overwrite { + return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, libReplaced)) + } + installPath = libReplaced.InstallDir + } else { + installPath = installDir.Join(library.Name) + if !overwrite && installPath.IsDir() { + return fmt.Errorf(tr("library %s already installed", library.Name)) + } + } + + // Deletes libraries folder if already installed + if installPath.IsDir() { + installPath.RemoveAll() + } + if installPath.Exist() { + return fmt.Errorf(tr("could not create directory %s: a file with the same name exists!", installPath)) + } + + // Copy extracted library in the destination directory + if err := tmpInstallPath.CopyDirTo(installPath); err != nil { + return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err) + } return nil } From f70dac1f5c5368e332aeb7077fd7135498793ee5 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 10 Nov 2022 10:45:52 +0100 Subject: [PATCH 05/13] Added test for double install with -.zip-path flag --- internal/integrationtest/lib/lib_test.go | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go index 43eb8e81dfb..388b95abd79 100644 --- a/internal/integrationtest/lib/lib_test.go +++ b/internal/integrationtest/lib/lib_test.go @@ -17,10 +17,13 @@ package lib_test import ( "encoding/json" + "io" + "net/http" "strings" "testing" "github.com/arduino/arduino-cli/internal/integrationtest" + "github.com/arduino/go-paths-helper" "github.com/stretchr/testify/require" "go.bug.st/testifyjson/requirejson" ) @@ -164,6 +167,42 @@ func TestDuplicateLibInstallFromGitDetection(t *testing.T) { requirejson.Parse(t, jsonOut). Query(`[.[].library.name | select(. == "Arduino SigFox for MKRFox1200")]`). LengthMustEqualTo(1, "Found multiple installations of Arduino SigFox for MKRFox1200'") + + // Try to make a double install by upgrade + _, _, err = cli.Run("lib", "upgrade") + require.NoError(t, err) + + // Check if double install happened + jsonOut, _, err = cli.Run("lib", "list", "--format", "json") + require.NoError(t, err) + requirejson.Parse(t, jsonOut). + Query(`[.[].library.name | select(. == "Arduino SigFox for MKRFox1200")]`). + LengthMustEqualTo(1, "Found multiple installations of Arduino SigFox for MKRFox1200'") + + // Try to make a double install by zip-installing + tmp, err := paths.MkTempDir("", "") + require.NoError(t, err) + defer tmp.RemoveAll() + tmpZip := tmp.Join("SigFox.zip") + defer tmpZip.Remove() + + f, err := tmpZip.Create() + require.NoError(t, err) + resp, err := http.Get("https://github.com/arduino-libraries/SigFox/archive/refs/tags/1.0.3.zip") + require.NoError(t, err) + _, err = io.Copy(f, resp.Body) + require.NoError(t, err) + require.NoError(t, f.Close()) + + _, _, err = cli.RunWithCustomEnv(cliEnv, "lib", "install", "--zip-path", tmpZip.String()) + require.NoError(t, err) + + // Check if double install happened + jsonOut, _, err = cli.Run("lib", "list", "--format", "json") + require.NoError(t, err) + requirejson.Parse(t, jsonOut). + Query(`[.[].library.name | select(. == "Arduino SigFox for MKRFox1200")]`). + LengthMustEqualTo(1, "Found multiple installations of Arduino SigFox for MKRFox1200'") } func TestLibDepsOutput(t *testing.T) { From eccd0b5df9884529f763ef9634bae9bcd4e5e31e Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 10 Nov 2022 10:59:42 +0100 Subject: [PATCH 06/13] Fixed `lib install --zip-path` pre-install checks Now it performs all the needed checks to avoid multiple installations --- arduino/libraries/librariesmanager/install.go | 77 +++++++++++-------- commands/lib/install.go | 3 +- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index 635b3fb4980..ecee7f3d351 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -113,20 +113,20 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error { } // InstallZipLib installs a Zip library on the specified path. -func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath string, overwrite bool) error { - libsDir := lm.getLibrariesDir(libraries.User) - if libsDir == nil { +func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *paths.Path, overwrite bool) error { + installDir := lm.getLibrariesDir(libraries.User) + if installDir == nil { return fmt.Errorf(tr("User directory not set")) } - tmpDir, err := paths.MkTempDir(paths.TempDir().String(), "arduino-cli-lib-") + // Clone library in a temporary directory + tmpDir, err := paths.MkTempDir("", "") if err != nil { return err } - // Deletes temp dir used to extract archive when finished defer tmpDir.RemoveAll() - file, err := os.Open(archivePath) + file, err := archivePath.Open() if err != nil { return err } @@ -138,48 +138,63 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath strin return fmt.Errorf(tr("extracting archive: %w"), err) } - paths, err := tmpDir.ReadDir() + libRootFiles, err := tmpDir.ReadDir() if err != nil { return err } - - // Ignores metadata from Mac OS X - paths.FilterOutPrefix("__MACOSX") - - if len(paths) > 1 { + libRootFiles.FilterOutPrefix("__MACOSX") // Ignores metadata from Mac OS X + if len(libRootFiles) > 1 { return fmt.Errorf(tr("archive is not valid: multiple files found in zip file top level")) } + if len(libRootFiles) == 0 { + return fmt.Errorf(tr("archive is not valid: no files found in zip file top level")) + } + tmpInstallPath := libRootFiles[0] - extractionPath := paths[0] - libraryName := extractionPath.Base() - - if err := validateLibrary(extractionPath); err != nil { + // Check if the library is valid and load metatada + if err := validateLibrary(tmpInstallPath); err != nil { return err } - - installPath := libsDir.Join(libraryName) - - if err := libsDir.MkdirAll(); err != nil { + library, err := libraries.Load(tmpInstallPath, libraries.User) + if err != nil { return err } - defer func() { - // Clean up install dir if installation failed - files, err := installPath.ReadDir() - if err == nil && len(files) == 0 { - installPath.RemoveAll() - } - }() - // Delete library folder if already installed - if installPath.IsDir() { + // Check if the library is already installed and determine install path + var installPath *paths.Path + libInstalled, libReplaced, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) + if errors.Is(err, ErrAlreadyInstalled) { if !overwrite { - return fmt.Errorf(tr("library %s already installed"), libraryName) + return fmt.Errorf(tr("library %s already installed"), library.Name) } + installPath = libInstalled + } else if err != nil { + return err + } else if libReplaced != nil { + if !overwrite { + return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, libReplaced)) + } + installPath = libReplaced.InstallDir + } else { + installPath = installDir.Join(library.Name) + if !overwrite && installPath.IsDir() { + return fmt.Errorf(tr("library %s already installed", library.Name)) + } + } + + // Deletes libraries folder if already installed + if installPath.IsDir() { installPath.RemoveAll() } + if installPath.Exist() { + return fmt.Errorf(tr("could not create directory %s: a file with the same name exists!", installPath)) + } // Copy extracted library in the destination directory - if err := extractionPath.CopyDirTo(installPath); err != nil { + if err := installDir.MkdirAll(); err != nil { + return err + } + if err := tmpInstallPath.CopyDirTo(installPath); err != nil { return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err) } diff --git a/commands/lib/install.go b/commands/lib/install.go index 1e24e6b191d..7628ab1e7fd 100644 --- a/commands/lib/install.go +++ b/commands/lib/install.go @@ -26,6 +26,7 @@ import ( "github.com/arduino/arduino-cli/arduino/libraries/librariesmanager" "github.com/arduino/arduino-cli/commands" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" + "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" ) @@ -156,7 +157,7 @@ func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *libraries // ZipLibraryInstall FIXMEDOC func ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallRequest, taskCB rpc.TaskProgressCB) error { lm := commands.GetLibraryManager(req) - if err := lm.InstallZipLib(ctx, req.Path, req.Overwrite); err != nil { + if err := lm.InstallZipLib(ctx, paths.New(req.Path), req.Overwrite); err != nil { return &arduino.FailedLibraryInstallError{Cause: err} } taskCB(&rpc.TaskProgress{Message: tr("Library installed"), Completed: true}) From 5f544cb6da6381e5425ef4c04e2629f1165c2cc4 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 10 Nov 2022 17:11:47 +0100 Subject: [PATCH 07/13] Simplified loop in LibraryInstall function --- commands/lib/install.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/commands/lib/install.go b/commands/lib/install.go index 7628ab1e7fd..4a14bba0821 100644 --- a/commands/lib/install.go +++ b/commands/lib/install.go @@ -77,28 +77,22 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa if err != nil { return err } - libReleasesToInstall = append(libReleasesToInstall, libRelease) - } - - // Check if any of the libraries to install is already installed and remove it from the list - j := 0 - for i, libRelease := range libReleasesToInstall { _, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease.Library.Name, libRelease.Version, installLocation) if errors.Is(err, librariesmanager.ErrAlreadyInstalled) { taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true}) - } else if err != nil { + continue + } + if err != nil { return err - } else { - libReleasesToInstall[j] = libReleasesToInstall[i] - j++ } + if req.GetNoOverwrite() { if libReplaced != nil { return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", libRelease, libReplaced)) } } + libReleasesToInstall = append(libReleasesToInstall, libRelease) } - libReleasesToInstall = libReleasesToInstall[:j] didInstall := false for _, libRelease := range libReleasesToInstall { From 106a5451063ff33b963849480e4dd26141c54bac Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 11 Nov 2022 09:58:41 +0100 Subject: [PATCH 08/13] Factored some of the checks in LibrariesManager.InstallPrerequisiteCheck They were duplicated and spread around all the library install functions. --- arduino/libraries/librariesmanager/install.go | 150 +++++++++--------- commands/lib/install.go | 64 +++----- 2 files changed, 95 insertions(+), 119 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index ecee7f3d351..6bb1e45dc72 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -17,7 +17,6 @@ package librariesmanager import ( "context" - "errors" "fmt" "net/url" "os" @@ -35,43 +34,41 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing" ) -type alreadyInstalledError struct{} +// LibraryInstallPlan contains the main information required to perform a library +// install, like the path where the library should be installed and the library +// that is going to be replaced by the new one. +// This is the result of a call to InstallPrerequisiteCheck. +type LibraryInstallPlan struct { + // TargetPath is the path where the library should be installed. + TargetPath *paths.Path -func (e *alreadyInstalledError) Error() string { - return tr("library already installed") -} + // ReplacedLib is the library that is going to be replaced by the new one. + ReplacedLib *libraries.Library -var ( - // ErrAlreadyInstalled is returned when a library is already installed and task - // cannot proceed. - ErrAlreadyInstalled = &alreadyInstalledError{} -) + // UpToDate is true if the library to install has the same version of the library we are going to replace. + UpToDate bool +} // InstallPrerequisiteCheck performs prequisite checks to install a library. It returns the // install path, where the library should be installed and the possible library that is already // installed on the same folder and it's going to be replaced by the new one. -func (lm *LibrariesManager) InstallPrerequisiteCheck(name string, version *semver.Version, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) { +func (lm *LibrariesManager) InstallPrerequisiteCheck(name string, version *semver.Version, installLocation libraries.LibraryLocation) (*LibraryInstallPlan, error) { installDir := lm.getLibrariesDir(installLocation) if installDir == nil { if installLocation == libraries.User { - return nil, nil, fmt.Errorf(tr("User directory not set")) + return nil, fmt.Errorf(tr("User directory not set")) } - return nil, nil, fmt.Errorf(tr("Builtin libraries directory not set")) + return nil, fmt.Errorf(tr("Builtin libraries directory not set")) } libs := lm.FindByReference(&librariesindex.Reference{Name: name}, installLocation) - for _, lib := range libs { - if lib.Version != nil && lib.Version.Equal(version) { - return lib.InstallDir, nil, ErrAlreadyInstalled - } - } if len(libs) > 1 { libsDir := paths.NewPathList() for _, lib := range libs { libsDir.Add(lib.InstallDir) } - return nil, nil, &arduino.MultipleLibraryInstallDetected{ + return nil, &arduino.MultipleLibraryInstallDetected{ LibName: name, LibsDir: libsDir, Message: tr("Automatic library install can't be performed in this case, please manually remove all duplicates and retry."), @@ -79,22 +76,41 @@ func (lm *LibrariesManager) InstallPrerequisiteCheck(name string, version *semve } var replaced *libraries.Library + var upToDate bool if len(libs) == 1 { - replaced = libs[0] + lib := libs[0] + replaced = lib + upToDate = lib.Version != nil && lib.Version.Equal(version) } libPath := installDir.Join(utils.SanitizeName(name)) - if replaced != nil && replaced.InstallDir.EquivalentTo(libPath) { - return libPath, replaced, nil - } else if libPath.IsDir() { - return nil, nil, fmt.Errorf(tr("destination dir %s already exists, cannot install"), libPath) + if libPath.IsDir() { + if replaced == nil || !replaced.InstallDir.EquivalentTo(libPath) { + return nil, fmt.Errorf(tr("destination dir %s already exists, cannot install"), libPath) + } } - return libPath, replaced, nil + + return &LibraryInstallPlan{ + TargetPath: libPath, + ReplacedLib: replaced, + UpToDate: upToDate, + }, nil } // Install installs a library on the specified path. -func (lm *LibrariesManager) Install(indexLibrary *librariesindex.Release, libPath *paths.Path) error { - return indexLibrary.Resource.Install(lm.DownloadsDir, libPath.Parent(), libPath) +func (lm *LibrariesManager) Install(indexLibrary *librariesindex.Release, installPath *paths.Path) error { + return indexLibrary.Resource.Install(lm.DownloadsDir, installPath.Parent(), installPath) +} + +// InstallLibraryFromFolder installs a library by copying it from the given folder. +func (lm *LibrariesManager) InstallLibraryFromFolder(libPath *paths.Path, installPath *paths.Path) error { + if installPath.Exist() { + return fmt.Errorf("%s: %s", tr("destination directory already exists"), installPath) + } + if err := libPath.CopyDirTo(installPath); err != nil { + return fmt.Errorf("%s: %w", tr("copying library to destination directory:"), err) + } + return nil } // Uninstall removes a Library @@ -103,7 +119,7 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error { return fmt.Errorf(tr("install directory not set")) } if err := lib.InstallDir.RemoveAll(); err != nil { - return fmt.Errorf(tr("removing lib directory: %s"), err) + return fmt.Errorf(tr("removing library directory: %s"), err) } alternatives := lm.Libraries[lib.Name] @@ -160,41 +176,29 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *path return err } - // Check if the library is already installed and determine install path - var installPath *paths.Path - libInstalled, libReplaced, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) - if errors.Is(err, ErrAlreadyInstalled) { + // Check if the library is already installed + installPlan, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) + if err != nil { + return err + } + if installPlan.UpToDate { if !overwrite { return fmt.Errorf(tr("library %s already installed"), library.Name) } - installPath = libInstalled - } else if err != nil { - return err - } else if libReplaced != nil { + } + + // Remove the old library if present + if installPlan.ReplacedLib != nil { if !overwrite { - return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, libReplaced)) + return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, installPlan.ReplacedLib)) } - installPath = libReplaced.InstallDir - } else { - installPath = installDir.Join(library.Name) - if !overwrite && installPath.IsDir() { - return fmt.Errorf(tr("library %s already installed", library.Name)) + if err := lm.Uninstall(installPlan.ReplacedLib); err != nil { + return err } } - // Deletes libraries folder if already installed - if installPath.IsDir() { - installPath.RemoveAll() - } - if installPath.Exist() { - return fmt.Errorf(tr("could not create directory %s: a file with the same name exists!", installPath)) - } - - // Copy extracted library in the destination directory - if err := installDir.MkdirAll(); err != nil { - return err - } - if err := tmpInstallPath.CopyDirTo(installPath); err != nil { + // Install extracted library in the destination directory + if err := lm.InstallLibraryFromFolder(tmpInstallPath, installPlan.TargetPath); err != nil { return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err) } @@ -257,39 +261,29 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { } // Check if the library is already installed and determine install path - var installPath *paths.Path - libInstalled, libReplaced, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) - if errors.Is(err, ErrAlreadyInstalled) { + installPlan, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) + if err != nil { + return err + } + if installPlan.UpToDate { if !overwrite { return fmt.Errorf(tr("library %s already installed"), library.Name) } - installPath = libInstalled - } else if err != nil { - return err - } else if libReplaced != nil { + } + if installPlan.ReplacedLib != nil { if !overwrite { - return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, libReplaced)) + return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, installPlan.ReplacedLib)) } - installPath = libReplaced.InstallDir - } else { - installPath = installDir.Join(library.Name) - if !overwrite && installPath.IsDir() { - return fmt.Errorf(tr("library %s already installed", library.Name)) + if err := lm.Uninstall(installPlan.ReplacedLib); err != nil { + return err } } - // Deletes libraries folder if already installed - if installPath.IsDir() { - installPath.RemoveAll() - } - if installPath.Exist() { - return fmt.Errorf(tr("could not create directory %s: a file with the same name exists!", installPath)) - } - - // Copy extracted library in the destination directory - if err := tmpInstallPath.CopyDirTo(installPath); err != nil { + // Install extracted library in the destination directory + if err := lm.InstallLibraryFromFolder(tmpInstallPath, installPlan.TargetPath); err != nil { return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err) } + return nil } diff --git a/commands/lib/install.go b/commands/lib/install.go index 4a14bba0821..f76d77a06d4 100644 --- a/commands/lib/install.go +++ b/commands/lib/install.go @@ -68,7 +68,7 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa } // Find the libReleasesToInstall to install - libReleasesToInstall := []*librariesindex.Release{} + libReleasesToInstall := map[*librariesindex.Release]*librariesmanager.LibraryInstallPlan{} for _, lib := range toInstall { libRelease, err := findLibraryIndexRelease(lm, &rpc.LibraryInstallRequest{ Name: lib.Name, @@ -77,73 +77,55 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa if err != nil { return err } - _, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease.Library.Name, libRelease.Version, installLocation) - if errors.Is(err, librariesmanager.ErrAlreadyInstalled) { - taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true}) - continue - } + + installTask, err := lm.InstallPrerequisiteCheck(libRelease.Library.Name, libRelease.Version, installLocation) if err != nil { return err } + if installTask.UpToDate { + taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true}) + continue + } if req.GetNoOverwrite() { - if libReplaced != nil { - return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", libRelease, libReplaced)) + if installTask.ReplacedLib != nil { + return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", libRelease, installTask.ReplacedLib)) } } - libReleasesToInstall = append(libReleasesToInstall, libRelease) + libReleasesToInstall[libRelease] = installTask } - didInstall := false - for _, libRelease := range libReleasesToInstall { + for libRelease, installTask := range libReleasesToInstall { if err := downloadLibrary(lm, libRelease, downloadCB, taskCB); err != nil { return err } - - if err := installLibrary(lm, libRelease, installLocation, taskCB); err != nil { - if errors.Is(err, librariesmanager.ErrAlreadyInstalled) { - continue - } else { - return err - } + if err := installLibrary(lm, libRelease, installTask, taskCB); err != nil { + return err } - didInstall = true } - if didInstall { - if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil { - return err - } + if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil { + return err } return nil } -func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *librariesindex.Release, installLocation libraries.LibraryLocation, taskCB rpc.TaskProgressCB) error { +func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *librariesindex.Release, installTask *librariesmanager.LibraryInstallPlan, taskCB rpc.TaskProgressCB) error { taskCB(&rpc.TaskProgress{Name: tr("Installing %s", libRelease)}) logrus.WithField("library", libRelease).Info("Installing library") - libPath, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease.Library.Name, libRelease.Version, installLocation) - if errors.Is(err, librariesmanager.ErrAlreadyInstalled) { - taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true}) - return err - } - if err != nil { - return &arduino.FailedInstallError{Message: tr("Checking lib install prerequisites"), Cause: err} - } - - if libReplaced != nil { + if libReplaced := installTask.ReplacedLib; libReplaced != nil { taskCB(&rpc.TaskProgress{Message: tr("Replacing %[1]s with %[2]s", libReplaced, libRelease)}) - } - - if err := lm.Install(libRelease, libPath); err != nil { - return &arduino.FailedLibraryInstallError{Cause: err} - } - if libReplaced != nil && !libReplaced.InstallDir.EquivalentTo(libPath) { if err := lm.Uninstall(libReplaced); err != nil { - return fmt.Errorf("%s: %s", tr("could not remove old library"), err) + return &arduino.FailedLibraryInstallError{ + Cause: fmt.Errorf("%s: %s", tr("could not remove old library"), err)} } } + if err := lm.Install(libRelease, installTask.TargetPath); err != nil { + return &arduino.FailedLibraryInstallError{Cause: err} + } + taskCB(&rpc.TaskProgress{Message: tr("Installed %s", libRelease), Completed: true}) return nil } From 529025a4391b5243499ca301dc4513d84bbedb27 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 11 Nov 2022 10:06:07 +0100 Subject: [PATCH 09/13] Refactored LibrariesManager.getLibrariesDir function This helped to find out 2 places where the `installDir` was unnecessary. --- arduino/libraries/librariesmanager/install.go | 19 +++---------------- .../librariesmanager/librariesmanager.go | 14 +++++++++++--- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index 6bb1e45dc72..fee086ddbe5 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -53,12 +53,9 @@ type LibraryInstallPlan struct { // install path, where the library should be installed and the possible library that is already // installed on the same folder and it's going to be replaced by the new one. func (lm *LibrariesManager) InstallPrerequisiteCheck(name string, version *semver.Version, installLocation libraries.LibraryLocation) (*LibraryInstallPlan, error) { - installDir := lm.getLibrariesDir(installLocation) - if installDir == nil { - if installLocation == libraries.User { - return nil, fmt.Errorf(tr("User directory not set")) - } - return nil, fmt.Errorf(tr("Builtin libraries directory not set")) + installDir, err := lm.getLibrariesDir(installLocation) + if err != nil { + return nil, err } libs := lm.FindByReference(&librariesindex.Reference{Name: name}, installLocation) @@ -130,11 +127,6 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error { // InstallZipLib installs a Zip library on the specified path. func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *paths.Path, overwrite bool) error { - installDir := lm.getLibrariesDir(libraries.User) - if installDir == nil { - return fmt.Errorf(tr("User directory not set")) - } - // Clone library in a temporary directory tmpDir, err := paths.MkTempDir("", "") if err != nil { @@ -207,11 +199,6 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *path // InstallGitLib installs a library hosted on a git repository on the specified path. func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { - installDir := lm.getLibrariesDir(libraries.User) - if installDir == nil { - return fmt.Errorf(tr("User directory not set")) - } - gitLibraryName, ref, err := parseGitURL(gitURL) if err != nil { return err diff --git a/arduino/libraries/librariesmanager/librariesmanager.go b/arduino/libraries/librariesmanager/librariesmanager.go index 9291db64117..30dbf69d644 100644 --- a/arduino/libraries/librariesmanager/librariesmanager.go +++ b/arduino/libraries/librariesmanager/librariesmanager.go @@ -16,6 +16,7 @@ package librariesmanager import ( + "errors" "fmt" "os" @@ -140,13 +141,20 @@ func (lm *LibrariesManager) RescanLibraries() []*status.Status { return statuses } -func (lm *LibrariesManager) getLibrariesDir(installLocation libraries.LibraryLocation) *paths.Path { +func (lm *LibrariesManager) getLibrariesDir(installLocation libraries.LibraryLocation) (*paths.Path, error) { for _, dir := range lm.LibrariesDir { if dir.Location == installLocation { - return dir.Path + return dir.Path, nil } } - return nil + switch installLocation { + case libraries.User: + return nil, errors.New(tr("user directory not set")) + case libraries.IDEBuiltIn: + return nil, errors.New(tr("built-in libraries directory not set")) + default: + return nil, fmt.Errorf("libraries directory not set: %s", installLocation.String()) + } } // LoadLibrariesFromDir loads all libraries in the given directory. Returns From 79d24103289d7f2a9d2e578ae4e7d4411e17ebca Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 11 Nov 2022 11:10:14 +0100 Subject: [PATCH 10/13] Factored all duplicated code for importing a library from a directory --- arduino/libraries/librariesmanager/install.go | 108 +++++++----------- 1 file changed, 43 insertions(+), 65 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index fee086ddbe5..5a3db0ff646 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -39,6 +39,12 @@ import ( // that is going to be replaced by the new one. // This is the result of a call to InstallPrerequisiteCheck. type LibraryInstallPlan struct { + // Name of the library to install + Name string + + // Version of the library to install + Version *semver.Version + // TargetPath is the path where the library should be installed. TargetPath *paths.Path @@ -88,6 +94,8 @@ func (lm *LibrariesManager) InstallPrerequisiteCheck(name string, version *semve } return &LibraryInstallPlan{ + Name: name, + Version: version, TargetPath: libPath, ReplacedLib: replaced, UpToDate: upToDate, @@ -99,12 +107,40 @@ func (lm *LibrariesManager) Install(indexLibrary *librariesindex.Release, instal return indexLibrary.Resource.Install(lm.DownloadsDir, installPath.Parent(), installPath) } -// InstallLibraryFromFolder installs a library by copying it from the given folder. -func (lm *LibrariesManager) InstallLibraryFromFolder(libPath *paths.Path, installPath *paths.Path) error { - if installPath.Exist() { - return fmt.Errorf("%s: %s", tr("destination directory already exists"), installPath) +// importLibraryFromDirectory installs a library by copying it from the given directory. +func (lm *LibrariesManager) importLibraryFromDirectory(libPath *paths.Path, overwrite bool) error { + // Check if the library is valid and load metatada + if err := validateLibrary(libPath); err != nil { + return err + } + library, err := libraries.Load(libPath, libraries.User) + if err != nil { + return err } - if err := libPath.CopyDirTo(installPath); err != nil { + + // Check if the library is already installed and determine install path + installPlan, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) + if err != nil { + return err + } + + if installPlan.UpToDate { + if !overwrite { + return fmt.Errorf(tr("library %s already installed"), installPlan.Name) + } + } + if installPlan.ReplacedLib != nil { + if !overwrite { + return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", installPlan.Name, installPlan.ReplacedLib)) + } + if err := lm.Uninstall(installPlan.ReplacedLib); err != nil { + return err + } + } + if installPlan.TargetPath.Exist() { + return fmt.Errorf("%s: %s", tr("destination directory already exists"), installPlan.TargetPath) + } + if err := libPath.CopyDirTo(installPlan.TargetPath); err != nil { return fmt.Errorf("%s: %w", tr("copying library to destination directory:"), err) } return nil @@ -159,38 +195,8 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *path } tmpInstallPath := libRootFiles[0] - // Check if the library is valid and load metatada - if err := validateLibrary(tmpInstallPath); err != nil { - return err - } - library, err := libraries.Load(tmpInstallPath, libraries.User) - if err != nil { - return err - } - - // Check if the library is already installed - installPlan, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) - if err != nil { - return err - } - if installPlan.UpToDate { - if !overwrite { - return fmt.Errorf(tr("library %s already installed"), library.Name) - } - } - - // Remove the old library if present - if installPlan.ReplacedLib != nil { - if !overwrite { - return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, installPlan.ReplacedLib)) - } - if err := lm.Uninstall(installPlan.ReplacedLib); err != nil { - return err - } - } - // Install extracted library in the destination directory - if err := lm.InstallLibraryFromFolder(tmpInstallPath, installPlan.TargetPath); err != nil { + if err := lm.importLibraryFromDirectory(tmpInstallPath, overwrite); err != nil { return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err) } @@ -238,36 +244,8 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error { // We don't want the installed library to be a git repository thus we delete this folder tmpInstallPath.Join(".git").RemoveAll() - // Check if the library is valid and load metatada - if err := validateLibrary(tmpInstallPath); err != nil { - return err - } - library, err := libraries.Load(tmpInstallPath, libraries.User) - if err != nil { - return err - } - - // Check if the library is already installed and determine install path - installPlan, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User) - if err != nil { - return err - } - if installPlan.UpToDate { - if !overwrite { - return fmt.Errorf(tr("library %s already installed"), library.Name) - } - } - if installPlan.ReplacedLib != nil { - if !overwrite { - return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", library.Name, installPlan.ReplacedLib)) - } - if err := lm.Uninstall(installPlan.ReplacedLib); err != nil { - return err - } - } - // Install extracted library in the destination directory - if err := lm.InstallLibraryFromFolder(tmpInstallPath, installPlan.TargetPath); err != nil { + if err := lm.importLibraryFromDirectory(tmpInstallPath, overwrite); err != nil { return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err) } From 174c2db47ff122eb7875753bcb9a53aabe745930 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 22 Nov 2022 15:59:10 +0100 Subject: [PATCH 11/13] Updated docs --- docs/UPGRADING.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index cd8bb72d709..e958f208073 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -16,6 +16,29 @@ The `sketch.json` file is now completely ignored. The `cc.arduino.cli.commands.v1.BoardAttach` gRPC command has been removed. This feature is no longer available through gRPC. +### golang API change in `github.com/arduino/arduino-cli/arduino/libraries/librariesmanager.LibrariesManager` + +The following `LibrariesManager.InstallPrerequisiteCheck` methods have changed prototype, from: + +```go +func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesindex.Release, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) { ... } +func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath string, overwrite bool) error { ... } +``` + +to + +```go +func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesindex.Release, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) { ... } +func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *paths.Path, overwrite bool) error { ... } +``` + +`InstallPrerequisiteCheck` now requires an explicit `name` and `version` instead of a `librariesindex.Release`, becuase +it can now be used to check any library, not only the libraries available in the index. Also the return value has +changed to a `LibraryInstallPlan` structure, it contains the same information as before (`TargetPath` and `ReplacedLib`) +plus `Name`, `Version`, and an `UpToDate` boolean flag. + +`InstallZipLib` method `archivePath` is now a `paths.Path` instead of a `string`. + ## 0.29.0 ### Removed gRPC API: `cc.arduino.cli.commands.v1.UpdateCoreLibrariesIndex`, `Outdated`, and `Upgrade` From de36f06f72a7a9003f621e6915bae59bcf97d54c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 22 Nov 2022 16:55:09 +0100 Subject: [PATCH 12/13] Fixed integration test The installation folder is now taken from the `name` field in `library.properties`. --- internal/integrationtest/compile_1/compile_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/integrationtest/compile_1/compile_test.go b/internal/integrationtest/compile_1/compile_test.go index c1f856d071b..7702ba0e4df 100644 --- a/internal/integrationtest/compile_1/compile_test.go +++ b/internal/integrationtest/compile_1/compile_test.go @@ -878,7 +878,7 @@ func TestCompileWithFullyPrecompiledLibrary(t *testing.T) { require.NoError(t, err) _, _, err = cli.Run("lib", "install", "--zip-path", wd.Parent().Join("testdata", "Arduino_TensorFlowLite-2.1.0-ALPHA-precompiled.zip").String()) require.NoError(t, err) - sketchFolder := cli.SketchbookDir().Join("libraries", "Arduino_TensorFlowLite-2.1.0-ALPHA-precompiled", "examples", "hello_world") + sketchFolder := cli.SketchbookDir().Join("libraries", "Arduino_TensorFlowLite", "examples", "hello_world") // Install example dependency _, _, err = cli.Run("lib", "install", "Arduino_LSM9DS1") From e5a77a0c93a678264428f9baa2dadebd74a6260c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 28 Nov 2022 18:28:00 +0100 Subject: [PATCH 13/13] Update docs/UPGRADING.md Co-authored-by: Umberto Baldi <34278123+umbynos@users.noreply.github.com> --- docs/UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index e958f208073..3ab8b55d26a 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -32,7 +32,7 @@ func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesinde func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *paths.Path, overwrite bool) error { ... } ``` -`InstallPrerequisiteCheck` now requires an explicit `name` and `version` instead of a `librariesindex.Release`, becuase +`InstallPrerequisiteCheck` now requires an explicit `name` and `version` instead of a `librariesindex.Release`, because it can now be used to check any library, not only the libraries available in the index. Also the return value has changed to a `LibraryInstallPlan` structure, it contains the same information as before (`TargetPath` and `ReplacedLib`) plus `Name`, `Version`, and an `UpToDate` boolean flag.