@@ -17,7 +17,6 @@ package librariesmanager
17
17
18
18
import (
19
19
"context"
20
- "errors"
21
20
"fmt"
22
21
"net/url"
23
22
"os"
@@ -35,66 +34,83 @@ import (
35
34
"gopkg.in/src-d/go-git.v4/plumbing"
36
35
)
37
36
38
- type alreadyInstalledError struct {}
37
+ // LibraryInstallPlan contains the main information required to perform a library
38
+ // install, like the path where the library should be installed and the library
39
+ // that is going to be replaced by the new one.
40
+ // This is the result of a call to InstallPrerequisiteCheck.
41
+ type LibraryInstallPlan struct {
42
+ // TargetPath is the path where the library should be installed.
43
+ TargetPath * paths.Path
39
44
40
- func (e * alreadyInstalledError ) Error () string {
41
- return tr ("library already installed" )
42
- }
45
+ // ReplacedLib is the library that is going to be replaced by the new one.
46
+ ReplacedLib * libraries.Library
43
47
44
- var (
45
- // ErrAlreadyInstalled is returned when a library is already installed and task
46
- // cannot proceed.
47
- ErrAlreadyInstalled = & alreadyInstalledError {}
48
- )
48
+ // UpToDate is true if the library to install has the same version of the library we are going to replace.
49
+ UpToDate bool
50
+ }
49
51
50
52
// InstallPrerequisiteCheck performs prequisite checks to install a library. It returns the
51
53
// install path, where the library should be installed and the possible library that is already
52
54
// installed on the same folder and it's going to be replaced by the new one.
53
- func (lm * LibrariesManager ) InstallPrerequisiteCheck (name string , version * semver.Version , installLocation libraries.LibraryLocation ) (* paths. Path , * libraries. Library , error ) {
55
+ func (lm * LibrariesManager ) InstallPrerequisiteCheck (name string , version * semver.Version , installLocation libraries.LibraryLocation ) (* LibraryInstallPlan , error ) {
54
56
installDir := lm .getLibrariesDir (installLocation )
55
57
if installDir == nil {
56
58
if installLocation == libraries .User {
57
- return nil , nil , fmt .Errorf (tr ("User directory not set" ))
59
+ return nil , fmt .Errorf (tr ("User directory not set" ))
58
60
}
59
- return nil , nil , fmt .Errorf (tr ("Builtin libraries directory not set" ))
61
+ return nil , fmt .Errorf (tr ("Builtin libraries directory not set" ))
60
62
}
61
63
62
64
libs := lm .FindByReference (& librariesindex.Reference {Name : name }, installLocation )
63
- for _ , lib := range libs {
64
- if lib .Version != nil && lib .Version .Equal (version ) {
65
- return lib .InstallDir , nil , ErrAlreadyInstalled
66
- }
67
- }
68
65
69
66
if len (libs ) > 1 {
70
67
libsDir := paths .NewPathList ()
71
68
for _ , lib := range libs {
72
69
libsDir .Add (lib .InstallDir )
73
70
}
74
- return nil , nil , & arduino.MultipleLibraryInstallDetected {
71
+ return nil , & arduino.MultipleLibraryInstallDetected {
75
72
LibName : name ,
76
73
LibsDir : libsDir ,
77
74
Message : tr ("Automatic library install can't be performed in this case, please manually remove all duplicates and retry." ),
78
75
}
79
76
}
80
77
81
78
var replaced * libraries.Library
79
+ var upToDate bool
82
80
if len (libs ) == 1 {
83
- replaced = libs [0 ]
81
+ lib := libs [0 ]
82
+ replaced = lib
83
+ upToDate = lib .Version != nil && lib .Version .Equal (version )
84
84
}
85
85
86
86
libPath := installDir .Join (utils .SanitizeName (name ))
87
- if replaced != nil && replaced . InstallDir . EquivalentTo ( libPath ) {
88
- return libPath , replaced , nil
89
- } else if libPath . IsDir () {
90
- return nil , nil , fmt . Errorf ( tr ( "destination dir %s already exists, cannot install" ), libPath )
87
+ if libPath . IsDir ( ) {
88
+ if replaced == nil || ! replaced . InstallDir . EquivalentTo ( libPath ) {
89
+ return nil , fmt . Errorf ( tr ( "destination dir %s already exists, cannot install" ), libPath )
90
+ }
91
91
}
92
- return libPath , replaced , nil
92
+
93
+ return & LibraryInstallPlan {
94
+ TargetPath : libPath ,
95
+ ReplacedLib : replaced ,
96
+ UpToDate : upToDate ,
97
+ }, nil
93
98
}
94
99
95
100
// Install installs a library on the specified path.
96
- func (lm * LibrariesManager ) Install (indexLibrary * librariesindex.Release , libPath * paths.Path ) error {
97
- return indexLibrary .Resource .Install (lm .DownloadsDir , libPath .Parent (), libPath )
101
+ func (lm * LibrariesManager ) Install (indexLibrary * librariesindex.Release , installPath * paths.Path ) error {
102
+ return indexLibrary .Resource .Install (lm .DownloadsDir , installPath .Parent (), installPath )
103
+ }
104
+
105
+ // InstallLibraryFromFolder installs a library by copying it from the given folder.
106
+ func (lm * LibrariesManager ) InstallLibraryFromFolder (libPath * paths.Path , installPath * paths.Path ) error {
107
+ if installPath .Exist () {
108
+ return fmt .Errorf ("%s: %s" , tr ("destination directory already exists" ), installPath )
109
+ }
110
+ if err := libPath .CopyDirTo (installPath ); err != nil {
111
+ return fmt .Errorf ("%s: %w" , tr ("copying library to destination directory:" ), err )
112
+ }
113
+ return nil
98
114
}
99
115
100
116
// Uninstall removes a Library
@@ -103,7 +119,7 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error {
103
119
return fmt .Errorf (tr ("install directory not set" ))
104
120
}
105
121
if err := lib .InstallDir .RemoveAll (); err != nil {
106
- return fmt .Errorf (tr ("removing lib directory: %s" ), err )
122
+ return fmt .Errorf (tr ("removing library directory: %s" ), err )
107
123
}
108
124
109
125
alternatives := lm .Libraries [lib .Name ]
@@ -160,41 +176,29 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *path
160
176
return err
161
177
}
162
178
163
- // Check if the library is already installed and determine install path
164
- var installPath * paths.Path
165
- libInstalled , libReplaced , err := lm .InstallPrerequisiteCheck (library .Name , library .Version , libraries .User )
166
- if errors .Is (err , ErrAlreadyInstalled ) {
179
+ // Check if the library is already installed
180
+ installPlan , err := lm .InstallPrerequisiteCheck (library .Name , library .Version , libraries .User )
181
+ if err != nil {
182
+ return err
183
+ }
184
+ if installPlan .UpToDate {
167
185
if ! overwrite {
168
186
return fmt .Errorf (tr ("library %s already installed" ), library .Name )
169
187
}
170
- installPath = libInstalled
171
- } else if err != nil {
172
- return err
173
- } else if libReplaced != nil {
188
+ }
189
+
190
+ // Remove the old library if present
191
+ if installPlan . ReplacedLib != nil {
174
192
if ! overwrite {
175
- return fmt .Errorf (tr ("Library %[1]s is already installed, but with a different version: %[2]s" , library .Name , libReplaced ))
193
+ return fmt .Errorf (tr ("Library %[1]s is already installed, but with a different version: %[2]s" , library .Name , installPlan . ReplacedLib ))
176
194
}
177
- installPath = libReplaced .InstallDir
178
- } else {
179
- installPath = installDir .Join (library .Name )
180
- if ! overwrite && installPath .IsDir () {
181
- return fmt .Errorf (tr ("library %s already installed" , library .Name ))
195
+ if err := lm .Uninstall (installPlan .ReplacedLib ); err != nil {
196
+ return err
182
197
}
183
198
}
184
199
185
- // Deletes libraries folder if already installed
186
- if installPath .IsDir () {
187
- installPath .RemoveAll ()
188
- }
189
- if installPath .Exist () {
190
- return fmt .Errorf (tr ("could not create directory %s: a file with the same name exists!" , installPath ))
191
- }
192
-
193
- // Copy extracted library in the destination directory
194
- if err := installDir .MkdirAll (); err != nil {
195
- return err
196
- }
197
- if err := tmpInstallPath .CopyDirTo (installPath ); err != nil {
200
+ // Install extracted library in the destination directory
201
+ if err := lm .InstallLibraryFromFolder (tmpInstallPath , installPlan .TargetPath ); err != nil {
198
202
return fmt .Errorf (tr ("moving extracted archive to destination dir: %s" ), err )
199
203
}
200
204
@@ -257,39 +261,29 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
257
261
}
258
262
259
263
// Check if the library is already installed and determine install path
260
- var installPath * paths.Path
261
- libInstalled , libReplaced , err := lm .InstallPrerequisiteCheck (library .Name , library .Version , libraries .User )
262
- if errors .Is (err , ErrAlreadyInstalled ) {
264
+ installPlan , err := lm .InstallPrerequisiteCheck (library .Name , library .Version , libraries .User )
265
+ if err != nil {
266
+ return err
267
+ }
268
+ if installPlan .UpToDate {
263
269
if ! overwrite {
264
270
return fmt .Errorf (tr ("library %s already installed" ), library .Name )
265
271
}
266
- installPath = libInstalled
267
- } else if err != nil {
268
- return err
269
- } else if libReplaced != nil {
272
+ }
273
+ if installPlan .ReplacedLib != nil {
270
274
if ! overwrite {
271
- return fmt .Errorf (tr ("Library %[1]s is already installed, but with a different version: %[2]s" , library .Name , libReplaced ))
275
+ return fmt .Errorf (tr ("Library %[1]s is already installed, but with a different version: %[2]s" , library .Name , installPlan . ReplacedLib ))
272
276
}
273
- installPath = libReplaced .InstallDir
274
- } else {
275
- installPath = installDir .Join (library .Name )
276
- if ! overwrite && installPath .IsDir () {
277
- return fmt .Errorf (tr ("library %s already installed" , library .Name ))
277
+ if err := lm .Uninstall (installPlan .ReplacedLib ); err != nil {
278
+ return err
278
279
}
279
280
}
280
281
281
- // Deletes libraries folder if already installed
282
- if installPath .IsDir () {
283
- installPath .RemoveAll ()
284
- }
285
- if installPath .Exist () {
286
- return fmt .Errorf (tr ("could not create directory %s: a file with the same name exists!" , installPath ))
287
- }
288
-
289
- // Copy extracted library in the destination directory
290
- if err := tmpInstallPath .CopyDirTo (installPath ); err != nil {
282
+ // Install extracted library in the destination directory
283
+ if err := lm .InstallLibraryFromFolder (tmpInstallPath , installPlan .TargetPath ); err != nil {
291
284
return fmt .Errorf (tr ("moving extracted archive to destination dir: %s" ), err )
292
285
}
286
+
293
287
return nil
294
288
}
295
289
0 commit comments