@@ -20,7 +20,9 @@ import (
20
20
"fmt"
21
21
"net/url"
22
22
"path/filepath"
23
+ "runtime"
23
24
"strings"
25
+ "time"
24
26
25
27
"github.com/arduino/arduino-cli/commands/cmderrors"
26
28
"github.com/arduino/arduino-cli/commands/internal/instances"
@@ -406,30 +408,59 @@ func Destroy(ctx context.Context, req *rpc.DestroyRequest) (*rpc.DestroyResponse
406
408
}
407
409
408
410
// UpdateLibrariesIndex updates the library_index.json
409
- func UpdateLibrariesIndex (ctx context.Context , req * rpc.UpdateLibrariesIndexRequest , downloadCB rpc.DownloadProgressCB ) error {
411
+ func UpdateLibrariesIndex (ctx context.Context , req * rpc.UpdateLibrariesIndexRequest , downloadCB rpc.DownloadProgressCB ) ( * rpc. UpdateLibrariesIndexResponse_Result , error ) {
410
412
logrus .Info ("Updating libraries index" )
413
+
411
414
pme , release , err := instances .GetPackageManagerExplorer (req .GetInstance ())
412
415
if err != nil {
413
- return err
416
+ return nil , err
414
417
}
415
418
indexDir := pme .IndexDir
416
419
release ()
417
420
421
+ index := globals .LibrariesIndexResource
422
+ result := func (status rpc.IndexUpdateReport_Status ) * rpc.UpdateLibrariesIndexResponse_Result {
423
+ return & rpc.UpdateLibrariesIndexResponse_Result {
424
+ LibrariesIndex : & rpc.IndexUpdateReport {
425
+ IndexUrl : globals .LibrariesIndexResource .URL .String (),
426
+ Status : status ,
427
+ },
428
+ }
429
+ }
430
+
431
+ // Create the index directory if it doesn't exist
418
432
if err := indexDir .MkdirAll (); err != nil {
419
- return & cmderrors.PermissionDeniedError {Message : tr ("Could not create index directory" ), Cause : err }
433
+ return result (rpc .IndexUpdateReport_STATUS_FAILED ), & cmderrors.PermissionDeniedError {Message : tr ("Could not create index directory" ), Cause : err }
434
+ }
435
+
436
+ // Check if the index file is already up-to-date
437
+ indexFileName , _ := index .IndexFileName ()
438
+ if info , err := indexDir .Join (indexFileName ).Stat (); err == nil {
439
+ ageSecs := int64 (time .Since (info .ModTime ()).Seconds ())
440
+ if ageSecs < req .GetUpdateIfOlderThanSecs () {
441
+ return result (rpc .IndexUpdateReport_STATUS_ALREADY_UP_TO_DATE ), nil
442
+ }
420
443
}
421
444
445
+ // Perform index update
422
446
if err := globals .LibrariesIndexResource .Download (indexDir , downloadCB ); err != nil {
423
- return err
447
+ return nil , err
424
448
}
425
449
426
- return nil
450
+ return result ( rpc . IndexUpdateReport_STATUS_UPDATED ), nil
427
451
}
428
452
429
453
// UpdateIndex FIXMEDOC
430
- func UpdateIndex (ctx context.Context , req * rpc.UpdateIndexRequest , downloadCB rpc.DownloadProgressCB ) error {
454
+ func UpdateIndex (ctx context.Context , req * rpc.UpdateIndexRequest , downloadCB rpc.DownloadProgressCB ) ( * rpc. UpdateIndexResponse_Result , error ) {
431
455
if ! instances .IsValid (req .GetInstance ()) {
432
- return & cmderrors.InvalidInstanceError {}
456
+ return nil , & cmderrors.InvalidInstanceError {}
457
+ }
458
+
459
+ report := func (indexURL * url.URL , status rpc.IndexUpdateReport_Status ) * rpc.IndexUpdateReport {
460
+ return & rpc.IndexUpdateReport {
461
+ IndexUrl : indexURL .String (),
462
+ Status : status ,
463
+ }
433
464
}
434
465
435
466
indexpath := configuration .DataDir (configuration .Settings )
@@ -440,46 +471,75 @@ func UpdateIndex(ctx context.Context, req *rpc.UpdateIndexRequest, downloadCB rp
440
471
}
441
472
442
473
failed := false
474
+ result := & rpc.UpdateIndexResponse_Result {}
443
475
for _ , u := range urls {
444
- URL , err := utils . URLParse (u )
476
+ URL , err := url . Parse (u )
445
477
if err != nil {
446
478
logrus .Warnf ("unable to parse additional URL: %s" , u )
447
479
msg := fmt .Sprintf ("%s: %v" , tr ("Unable to parse URL" ), err )
448
480
downloadCB .Start (u , tr ("Downloading index: %s" , u ))
449
481
downloadCB .End (false , msg )
450
482
failed = true
483
+ result .UpdatedIndexes = append (result .UpdatedIndexes , report (URL , rpc .IndexUpdateReport_STATUS_FAILED ))
451
484
continue
452
485
}
453
486
454
487
logrus .WithField ("url" , URL ).Print ("Updating index" )
455
488
456
489
if URL .Scheme == "file" {
457
- downloadCB .Start (u , tr ("Downloading index: %s" , filepath .Base (URL .Path )))
458
490
path := paths .New (URL .Path )
491
+ if URL .Scheme == "file" && runtime .GOOS == "windows" && len (URL .Path ) > 1 {
492
+ // https://github.com/golang/go/issues/32456
493
+ // Parsed local file URLs on Windows are returned with a leading / so we remove it
494
+ path = paths .New (URL .Path [1 :])
495
+ }
459
496
if _ , err := packageindex .LoadIndexNoSign (path ); err != nil {
460
497
msg := fmt .Sprintf ("%s: %v" , tr ("Invalid package index in %s" , path ), err )
498
+ downloadCB .Start (u , tr ("Downloading index: %s" , filepath .Base (URL .Path )))
461
499
downloadCB .End (false , msg )
462
500
failed = true
501
+ result .UpdatedIndexes = append (result .UpdatedIndexes , report (URL , rpc .IndexUpdateReport_STATUS_FAILED ))
463
502
} else {
464
- downloadCB . End ( true , "" )
503
+ result . UpdatedIndexes = append ( result . UpdatedIndexes , report ( URL , rpc . IndexUpdateReport_STATUS_SKIPPED ) )
465
504
}
466
505
continue
467
506
}
468
507
508
+ // Check if the index is up-to-date
469
509
indexResource := resources.IndexResource {URL : URL }
510
+ indexFileName , err := indexResource .IndexFileName ()
511
+ if err != nil {
512
+ downloadCB .Start (u , tr ("Downloading index: %s" , filepath .Base (URL .Path )))
513
+ downloadCB .End (false , tr ("Invalid index URL: %s" , err ))
514
+ failed = true
515
+ result .UpdatedIndexes = append (result .UpdatedIndexes , report (URL , rpc .IndexUpdateReport_STATUS_FAILED ))
516
+ continue
517
+ }
518
+ indexFile := indexpath .Join (indexFileName )
519
+ if info , err := indexFile .Stat (); err == nil {
520
+ ageSecs := int64 (time .Since (info .ModTime ()).Seconds ())
521
+ if ageSecs < req .GetUpdateIfOlderThanSecs () {
522
+ result .UpdatedIndexes = append (result .UpdatedIndexes , report (URL , rpc .IndexUpdateReport_STATUS_ALREADY_UP_TO_DATE ))
523
+ continue
524
+ }
525
+ }
526
+
470
527
if strings .HasSuffix (URL .Host , "arduino.cc" ) && strings .HasSuffix (URL .Path , ".json" ) {
471
528
indexResource .SignatureURL , _ = url .Parse (u ) // should not fail because we already parsed it
472
529
indexResource .SignatureURL .Path += ".sig"
473
530
}
474
531
if err := indexResource .Download (indexpath , downloadCB ); err != nil {
475
532
failed = true
533
+ result .UpdatedIndexes = append (result .UpdatedIndexes , report (URL , rpc .IndexUpdateReport_STATUS_FAILED ))
534
+ } else {
535
+ result .UpdatedIndexes = append (result .UpdatedIndexes , report (URL , rpc .IndexUpdateReport_STATUS_UPDATED ))
476
536
}
477
537
}
478
538
479
539
if failed {
480
- return & cmderrors.FailedDownloadError {Message : tr ("Some indexes could not be updated." )}
540
+ return result , & cmderrors.FailedDownloadError {Message : tr ("Some indexes could not be updated." )}
481
541
}
482
- return nil
542
+ return result , nil
483
543
}
484
544
485
545
// firstUpdate downloads libraries and packages indexes if they don't exist.
@@ -493,7 +553,7 @@ func firstUpdate(ctx context.Context, instance *rpc.Instance, downloadCb func(ms
493
553
// The library_index.json file doesn't exists, that means the CLI is run for the first time
494
554
// so we proceed with the first update that downloads the file
495
555
req := & rpc.UpdateLibrariesIndexRequest {Instance : instance }
496
- if err := UpdateLibrariesIndex (ctx , req , downloadCb ); err != nil {
556
+ if _ , err := UpdateLibrariesIndex (ctx , req , downloadCb ); err != nil {
497
557
return err
498
558
}
499
559
}
@@ -515,7 +575,7 @@ func firstUpdate(ctx context.Context, instance *rpc.Instance, downloadCb func(ms
515
575
// library update we download that file and all the other package indexes from
516
576
// additional_urls
517
577
req := & rpc.UpdateIndexRequest {Instance : instance }
518
- if err := UpdateIndex (ctx , req , downloadCb ); err != nil {
578
+ if _ , err := UpdateIndex (ctx , req , downloadCb ); err != nil {
519
579
return err
520
580
}
521
581
break
0 commit comments