Skip to content

Commit 1a1b687

Browse files
committed
Added checks for multiple library installation
1 parent ae8c6d7 commit 1a1b687

File tree

4 files changed

+98
-20
lines changed

4 files changed

+98
-20
lines changed

Diff for: arduino/errors.go

+24
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/arduino/arduino-cli/i18n"
2323
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
24+
"github.com/arduino/go-paths-helper"
2425
"google.golang.org/grpc/codes"
2526
"google.golang.org/grpc/status"
2627
)
@@ -810,3 +811,26 @@ func (e *MultiplePlatformsError) Error() string {
810811
func (e *MultiplePlatformsError) ToRPCStatus() *status.Status {
811812
return status.New(codes.InvalidArgument, e.Error())
812813
}
814+
815+
// MultipleLibraryInstallDetected is returned when the user request an
816+
// operation on a library but multiple libraries with the same name
817+
// (in library.properties) are detected.
818+
type MultipleLibraryInstallDetected struct {
819+
LibName string
820+
LibsDir paths.PathList
821+
Message string
822+
}
823+
824+
func (e *MultipleLibraryInstallDetected) Error() string {
825+
res := tr("The library %s has multiple installations:", e.LibName) + "\n"
826+
for _, lib := range e.LibsDir {
827+
res += fmt.Sprintf("- %s\n", lib)
828+
}
829+
res += e.Message
830+
return res
831+
}
832+
833+
// ToRPCStatus converts the error into a *status.Status
834+
func (e *MultipleLibraryInstallDetected) ToRPCStatus() *status.Status {
835+
return status.New(codes.InvalidArgument, e.Error())
836+
}

Diff for: arduino/libraries/librariesmanager/install.go

+29-17
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"os"
2323
"strings"
2424

25+
"github.com/arduino/arduino-cli/arduino"
2526
"github.com/arduino/arduino-cli/arduino/globals"
2627
"github.com/arduino/arduino-cli/arduino/libraries"
2728
"github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
@@ -49,31 +50,42 @@ var (
4950
// install path, where the library should be installed and the possible library that is already
5051
// installed on the same folder and it's going to be replaced by the new one.
5152
func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesindex.Release, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) {
52-
var replaced *libraries.Library
53+
installDir := lm.getLibrariesDir(installLocation)
54+
if installDir == nil {
55+
if installLocation == libraries.User {
56+
return nil, nil, fmt.Errorf(tr("User directory not set"))
57+
}
58+
return nil, nil, fmt.Errorf(tr("Builtin libraries directory not set"))
59+
}
60+
5361
name := indexLibrary.Library.Name
54-
if installedLibs, have := lm.Libraries[name]; have {
55-
for _, installedLib := range installedLibs {
56-
if installedLib.Location != installLocation {
57-
continue
58-
}
59-
if installedLib.Version != nil && installedLib.Version.Equal(indexLibrary.Version) {
60-
return installedLib.InstallDir, nil, ErrAlreadyInstalled
61-
}
62-
replaced = installedLib
62+
libs := lm.FindByReference(&librariesindex.Reference{Name: name}, installLocation)
63+
for _, lib := range libs {
64+
if lib.Version != nil && lib.Version.Equal(indexLibrary.Version) {
65+
return lib.InstallDir, nil, ErrAlreadyInstalled
6366
}
6467
}
6568

66-
libsDir := lm.getLibrariesDir(installLocation)
67-
if libsDir == nil {
68-
if installLocation == libraries.User {
69-
return nil, nil, fmt.Errorf(tr("User directory not set"))
69+
if len(libs) > 1 {
70+
libsDir := paths.NewPathList()
71+
for _, lib := range libs {
72+
libsDir.Add(lib.InstallDir)
73+
}
74+
return nil, nil, &arduino.MultipleLibraryInstallDetected{
75+
LibName: name,
76+
LibsDir: libsDir,
77+
Message: tr("Automatic library install can't be performed in this case, please manually remove all duplicates and retry."),
7078
}
71-
return nil, nil, fmt.Errorf(tr("Builtin libraries directory not set"))
7279
}
7380

74-
libPath := libsDir.Join(utils.SanitizeName(indexLibrary.Library.Name))
75-
if replaced != nil && replaced.InstallDir.EquivalentTo(libPath) {
81+
var replaced *libraries.Library
82+
if len(libs) == 1 {
83+
replaced = libs[0]
84+
}
7685

86+
libPath := installDir.Join(utils.SanitizeName(indexLibrary.Library.Name))
87+
if replaced != nil && replaced.InstallDir.EquivalentTo(libPath) {
88+
return libPath, replaced, nil
7789
} else if libPath.IsDir() {
7890
return nil, nil, fmt.Errorf(tr("destination dir %s already exists, cannot install"), libPath)
7991
}

Diff for: commands/lib/uninstall.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/arduino/arduino-cli/arduino/libraries"
2323
"github.com/arduino/arduino-cli/commands"
2424
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
25+
"github.com/arduino/go-paths-helper"
2526
)
2627

2728
// LibraryUninstall FIXMEDOC
@@ -36,11 +37,23 @@ func LibraryUninstall(ctx context.Context, req *rpc.LibraryUninstallRequest, tas
3637

3738
if len(libs) == 0 {
3839
taskCB(&rpc.TaskProgress{Message: tr("Library %s is not installed", req.Name), Completed: true})
39-
} else {
40-
taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s", libs[0])})
40+
return nil
41+
}
42+
43+
if len(libs) == 1 {
44+
taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s", libs)})
4145
lm.Uninstall(libs[0])
4246
taskCB(&rpc.TaskProgress{Completed: true})
47+
return nil
4348
}
4449

45-
return nil
50+
libsDir := paths.NewPathList()
51+
for _, lib := range libs {
52+
libsDir.Add(lib.InstallDir)
53+
}
54+
return &arduino.MultipleLibraryInstallDetected{
55+
LibName: libs[0].RealName,
56+
LibsDir: libsDir,
57+
Message: tr("Automatic library uninstall can't be performed in this case, please manually remove them."),
58+
}
4659
}

Diff for: internal/integrationtest/lib/lib_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,32 @@ func TestLibUpgradeCommand(t *testing.T) {
6464
require.NoError(t, err)
6565
requirejson.Query(t, stdOut, `.[].library | select(.name=="Servo") | .version`, servoVersion)
6666
}
67+
68+
func TestLibInstallMultipleSameLibrary(t *testing.T) {
69+
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
70+
defer env.CleanUp()
71+
cliEnv := cli.GetDefaultEnv()
72+
cliEnv["ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL"] = "true"
73+
74+
// Check that 'lib install' didn't create a double install
75+
// https://github.com/arduino/arduino-cli/issues/1870
76+
_, _, err := cli.RunWithCustomEnv(cliEnv, "lib", "install", "--git-url", "https://github.com/arduino-libraries/SigFox#1.0.3")
77+
require.NoError(t, err)
78+
_, _, err = cli.Run("lib", "install", "Arduino SigFox for MKRFox1200")
79+
require.NoError(t, err)
80+
jsonOut, _, err := cli.Run("lib", "list", "--format", "json")
81+
require.NoError(t, err)
82+
requirejson.Len(t, jsonOut, 1, "A duplicate library install has been detected")
83+
84+
// Check that 'lib upgrade' didn't create a double install
85+
// https://github.com/arduino/arduino-cli/issues/1870
86+
_, _, err = cli.Run("lib", "uninstall", "Arduino SigFox for MKRFox1200")
87+
require.NoError(t, err)
88+
_, _, err = cli.RunWithCustomEnv(cliEnv, "lib", "install", "--git-url", "https://github.com/arduino-libraries/SigFox#1.0.3")
89+
require.NoError(t, err)
90+
_, _, err = cli.Run("lib", "upgrade", "Arduino SigFox for MKRFox1200")
91+
require.NoError(t, err)
92+
jsonOut, _, err = cli.Run("lib", "list", "--format", "json")
93+
require.NoError(t, err)
94+
requirejson.Len(t, jsonOut, 1, "A duplicate library install has been detected")
95+
}

0 commit comments

Comments
 (0)