@@ -210,7 +210,8 @@ def install_arduino_cli(self):
210
210
url = arduino_cli_archive_download_url_prefix + arduino_cli_archive_file_name ,
211
211
# The Arduino CLI has no root folder, so just install the arduino-cli executable from the archive root
212
212
source_path = "arduino-cli" ,
213
- destination_parent_path = self .arduino_cli_installation_path
213
+ destination_parent_path = self .arduino_cli_installation_path ,
214
+ force = False
214
215
)
215
216
216
217
# Configure the location of the Arduino CLI user directory
@@ -424,20 +425,32 @@ def install_platforms_from_path(self, platform_list):
424
425
425
426
# Install the platform
426
427
install_from_path (source_path = source_path ,
427
- destination_parent_path = platform_installation_path .parent ,
428
- destination_name = platform_installation_path .name )
428
+ destination_parent_path = platform_installation_path .path .parent ,
429
+ destination_name = platform_installation_path .path .name ,
430
+ force = platform_installation_path .is_overwrite )
429
431
430
432
def get_platform_installation_path (self , platform ):
431
- """Return the correct installation path for the given platform
433
+ """Determines the correct installation path for the given platform and returns an object with the attributes:
434
+ path -- correct installation path for the platform (pathlib.Path() object)
435
+ is_overwrite -- whether there is an existing installation of the platform (True, False)
432
436
433
437
Keyword arguments:
434
438
platform -- dictionary defining the platform dependency
435
439
"""
440
+
441
+ class PlatformInstallationPath :
442
+ def __init__ (self ):
443
+ self .path = pathlib .Path ()
444
+ self .is_overwrite = False
445
+
446
+ platform_installation_path = PlatformInstallationPath ()
447
+
448
+ # Default to installing to the sketchbook
436
449
platform_vendor = platform [self .dependency_name_key ].split (sep = ":" )[0 ]
437
450
platform_architecture = platform [self .dependency_name_key ].rsplit (sep = ":" , maxsplit = 1 )[1 ]
438
451
439
452
# Default to installing to the sketchbook
440
- platform_installation_path = self .user_platforms_path .joinpath (platform_vendor , platform_architecture )
453
+ platform_installation_path . path = self .user_platforms_path .joinpath (platform_vendor , platform_architecture )
441
454
442
455
# I have no clue why this is needed, but arduino-cli core list fails if this isn't done first. The 3rd party
443
456
# platforms are still shown in the list even if their index URLs are not specified to the command via the
@@ -449,15 +462,13 @@ def get_platform_installation_path(self, platform):
449
462
for installed_platform in installed_platform_list :
450
463
if installed_platform ["ID" ] == platform [self .dependency_name_key ]:
451
464
# The platform has been installed via Board Manager, so do an overwrite
452
- platform_installation_path = (
465
+ platform_installation_path . path = (
453
466
self .board_manager_platforms_path .joinpath (platform_vendor ,
454
467
"hardware" ,
455
468
platform_architecture ,
456
469
installed_platform ["Installed" ])
457
470
)
458
-
459
- # Remove the existing installation so it can be replaced by the installation function
460
- shutil .rmtree (path = platform_installation_path )
471
+ platform_installation_path .is_overwrite = True
461
472
462
473
break
463
474
@@ -484,8 +495,9 @@ def install_platforms_from_repository(self, platform_list):
484
495
self .install_from_repository (url = platform [self .dependency_source_url_key ],
485
496
git_ref = git_ref ,
486
497
source_path = source_path ,
487
- destination_parent_path = destination_path .parent ,
488
- destination_name = destination_path .name )
498
+ destination_parent_path = destination_path .path .parent ,
499
+ destination_name = destination_path .path .name ,
500
+ force = destination_path .is_overwrite )
489
501
490
502
def get_repository_dependency_ref (self , dependency ):
491
503
"""Return the appropriate git ref value for a repository dependency
@@ -500,7 +512,13 @@ def get_repository_dependency_ref(self, dependency):
500
512
501
513
return git_ref
502
514
503
- def install_from_repository (self , url , git_ref , source_path , destination_parent_path , destination_name = None ):
515
+ def install_from_repository (self ,
516
+ url ,
517
+ git_ref ,
518
+ source_path ,
519
+ destination_parent_path ,
520
+ destination_name = None ,
521
+ force = False ):
504
522
"""Install by cloning a repository
505
523
506
524
Keyword arguments:
@@ -510,6 +528,7 @@ def install_from_repository(self, url, git_ref, source_path, destination_parent_
510
528
destination_parent_path -- path under which to install
511
529
destination_name -- folder name to use for the installation. Set to None to use the repository name.
512
530
(default None)
531
+ force -- replace existing destination folder if present. (default False)
513
532
"""
514
533
if destination_name is None and source_path .rstrip ("/" ) == "." :
515
534
# Use the repository name
@@ -521,7 +540,8 @@ def install_from_repository(self, url, git_ref, source_path, destination_parent_
521
540
# Install to the final location
522
541
install_from_path (source_path = pathlib .Path (clone_folder , source_path ),
523
542
destination_parent_path = destination_parent_path ,
524
- destination_name = destination_name )
543
+ destination_name = destination_name ,
544
+ force = force )
525
545
526
546
def clone_repository (self , url , git_ref , destination_path ):
527
547
"""Clone a Git repository to a specified location and check out the specified ref
@@ -567,8 +587,9 @@ def install_platforms_from_download(self, platform_list):
567
587
568
588
install_from_download (url = platform [self .dependency_source_url_key ],
569
589
source_path = source_path ,
570
- destination_parent_path = destination_path .parent ,
571
- destination_name = destination_path .name )
590
+ destination_parent_path = destination_path .path .parent ,
591
+ destination_name = destination_path .path .name ,
592
+ force = destination_path .is_overwrite )
572
593
573
594
def install_libraries (self ):
574
595
"""Install Arduino libraries."""
@@ -587,6 +608,9 @@ def install_libraries(self):
587
608
# that behavior is retained when using the old input syntax
588
609
library_list .path = [{self .dependency_source_path_key : os .environ ["GITHUB_WORKSPACE" ]}]
589
610
611
+ # Dependencies of Library Manager sourced libraries (as defined by the library's metadata file) are
612
+ # automatically installed. For this reason, LM-sources must be installed first so the library dependencies from
613
+ # other sources which were explicitly defined won't be replaced.
590
614
if len (library_list .manager ) > 0 :
591
615
self .install_libraries_from_library_manager (library_list = library_list .manager )
592
616
@@ -639,7 +663,8 @@ def install_libraries_from_path(self, library_list):
639
663
640
664
install_from_path (source_path = source_path ,
641
665
destination_parent_path = self .libraries_path ,
642
- destination_name = destination_name )
666
+ destination_name = destination_name ,
667
+ force = True )
643
668
644
669
def install_libraries_from_repository (self , library_list ):
645
670
"""Install libraries by cloning Git repositories
@@ -669,7 +694,8 @@ def install_libraries_from_repository(self, library_list):
669
694
git_ref = git_ref ,
670
695
source_path = source_path ,
671
696
destination_parent_path = self .libraries_path ,
672
- destination_name = destination_name )
697
+ destination_name = destination_name ,
698
+ force = True )
673
699
674
700
def install_libraries_from_download (self , library_list ):
675
701
"""Install libraries by downloading them
@@ -692,7 +718,8 @@ def install_libraries_from_download(self, library_list):
692
718
install_from_download (url = library [self .dependency_source_url_key ],
693
719
source_path = source_path ,
694
720
destination_parent_path = self .libraries_path ,
695
- destination_name = destination_name )
721
+ destination_name = destination_name ,
722
+ force = True )
696
723
697
724
def find_sketches (self ):
698
725
"""Return a list of all sketches under the paths specified in the sketch paths list recursively."""
@@ -1269,23 +1296,32 @@ def __init__(self):
1269
1296
return input_list
1270
1297
1271
1298
1272
- def install_from_path (source_path , destination_parent_path , destination_name = None ):
1299
+ def install_from_path (source_path , destination_parent_path , destination_name = None , force = False ):
1273
1300
"""Copy the source path to the destination path.
1274
1301
1275
1302
Keyword arguments:
1276
1303
source_path -- path to install
1277
1304
destination_parent_path -- path under which to install
1278
1305
destination_name -- folder or filename name to use for the installation. Set to None to take the name from
1279
1306
source_path. (default None)
1307
+ force -- replace existing destination if present. (default False)
1280
1308
"""
1281
1309
if destination_name is None :
1282
1310
destination_name = source_path .name
1283
1311
1312
+ destination_path = destination_parent_path .joinpath (destination_name )
1313
+
1314
+ if destination_path .exists ():
1315
+ if force :
1316
+ # Clear existing folder
1317
+ shutil .rmtree (path = destination_path )
1318
+ else :
1319
+ print ("::error::Installation already exists:" , destination_path )
1320
+ sys .exit (1 )
1321
+
1284
1322
# Create the parent path if it doesn't already exist
1285
1323
destination_parent_path .mkdir (parents = True , exist_ok = True )
1286
1324
1287
- destination_path = destination_parent_path .joinpath (destination_name )
1288
-
1289
1325
if source_path .is_dir ():
1290
1326
shutil .copytree (src = source_path , dst = destination_path )
1291
1327
else :
@@ -1321,7 +1357,7 @@ def list_to_string(list_input):
1321
1357
return " " .join ([str (item ) for item in list_input ])
1322
1358
1323
1359
1324
- def install_from_download (url , source_path , destination_parent_path , destination_name = None ):
1360
+ def install_from_download (url , source_path , destination_parent_path , destination_name = None , force = False ):
1325
1361
"""Download an archive, extract, and install.
1326
1362
1327
1363
Keyword arguments:
@@ -1330,6 +1366,7 @@ def install_from_download(url, source_path, destination_parent_path, destination
1330
1366
destination_parent_path -- path under which to install
1331
1367
destination_name -- folder name to use for the installation. Set to None to take the name from source_path.
1332
1368
(default None)
1369
+ force -- replace existing destination folder if present. (default False)
1333
1370
"""
1334
1371
destination_parent_path = pathlib .Path (destination_parent_path )
1335
1372
@@ -1362,7 +1399,8 @@ def install_from_download(url, source_path, destination_parent_path, destination
1362
1399
1363
1400
install_from_path (source_path = absolute_source_path ,
1364
1401
destination_parent_path = destination_parent_path ,
1365
- destination_name = destination_name )
1402
+ destination_name = destination_name ,
1403
+ force = force )
1366
1404
1367
1405
1368
1406
def get_archive_root_path (archive_extract_path ):
0 commit comments