@@ -23,6 +23,7 @@ import (
2323 "github.com/open-cmsis-pack/cpackget/cmd/ui"
2424 "github.com/open-cmsis-pack/cpackget/cmd/utils"
2525 "github.com/open-cmsis-pack/cpackget/cmd/xml"
26+ "github.com/schollz/progressbar/v3"
2627 log "github.com/sirupsen/logrus"
2728 "github.com/spf13/viper"
2829 "golang.org/x/mod/semver"
@@ -400,13 +401,14 @@ func RemovePdsc(pdscPath string) error {
400401// Parameters:
401402// - pdscTag: The PDSC tag containing information about the files to be downloaded.
402403// - skipInstalledPdscFiles: A boolean flag indicating whether to skip already installed PDSC files.
404+ // - showInfo: If true, logs informational messages about the download.
403405// - timeout: An integer specifying the timeout duration in seconds.
404406//
405407// Example:
406408//
407409// massDownloadPdscFiles(pdscTag, true, 30)
408- func massDownloadPdscFiles (pdscTag xml.PdscTag , skipInstalledPdscFiles bool , timeout int , errTags * lockedSlice ) {
409- if err := Installation .downloadPdscFile (pdscTag , skipInstalledPdscFiles , true , timeout ); err != nil {
410+ func massDownloadPdscFiles (pdscTag xml.PdscTag , skipInstalledPdscFiles , showInfo bool , timeout int , errTags * lockedSlice ) {
411+ if err := Installation .downloadPdscFile (pdscTag , skipInstalledPdscFiles , showInfo , false , timeout ); err != nil {
410412 errTags .lock .Lock ()
411413 errTags .slice = append (errTags .slice , pdscTag )
412414 errTags .lock .Unlock ()
@@ -613,7 +615,7 @@ func DownloadPDSCFiles(skipInstalledPdscFiles bool, concurrency int, timeout int
613615
614616 for _ , pdscTag := range pdscTags {
615617 if concurrency == 0 {
616- massDownloadPdscFiles (pdscTag , skipInstalledPdscFiles , timeout , & errTags )
618+ massDownloadPdscFiles (pdscTag , skipInstalledPdscFiles , true , timeout , & errTags )
617619 } else {
618620 if err := sem .Acquire (ctx , 1 ); err != nil {
619621 log .Errorf ("Failed to acquire semaphore: %v" , err )
@@ -622,7 +624,7 @@ func DownloadPDSCFiles(skipInstalledPdscFiles bool, concurrency int, timeout int
622624
623625 go func (pdscTag xml.PdscTag , errTags * lockedSlice ) {
624626 defer sem .Release (1 )
625- massDownloadPdscFiles (pdscTag , skipInstalledPdscFiles , timeout , errTags )
627+ massDownloadPdscFiles (pdscTag , skipInstalledPdscFiles , true , timeout , errTags )
626628 }(pdscTag , & errTags )
627629 }
628630 }
@@ -635,54 +637,96 @@ func DownloadPDSCFiles(skipInstalledPdscFiles bool, concurrency int, timeout int
635637 return nil
636638}
637639
638- // UpdateInstalledPDSCFiles updates the PDSC files of installed packs referenced in the public index.
639- // It checks if the PDSC files need updating and downloads the latest versions if necessary.
640+ // UpdateInstalledPDSCFiles updates the installed PDSC files for both public and private packs.
641+ // It compares the provided pidxXML (current index) and oldPidxXML (previous index) to determine
642+ // which PDSC files need to be updated. For public packs, it downloads new versions of PDSC files
643+ // if available, using concurrency control. If any errors occur during download, it attempts to
644+ // revert to previous versions. After updating, it writes the updated index and moves it to the
645+ // installation directory, handling file permissions appropriately.
646+ //
647+ // For private packs, it scans the local directory for PDSC files and checks if they need updating
648+ // by loading the latest version from the source. If an update is available, it logs the upgrade
649+ // information. The function supports configurable concurrency and timeout for downloads.
640650//
641651// Parameters:
642- // - pidxXML: A pointer to the PidxXML structure containing the public index data.
643- // - concurrency: The number of concurrent downloads allowed. If set to 0, downloads are performed sequentially.
644- // - timeout: The timeout duration for downloading PDSC files.
652+ // - pidxXML: The current public index XML structure.
653+ // - oldPidxXML: The previous public index XML structure (can be nil).
654+ // - updatePrivatePdsc: Whether to update private PDSC files.
655+ // - showInfo: If true, logs informational messages about the download.
656+ // - concurrency: Number of concurrent downloads allowed.
657+ // - timeout: Timeout in seconds for downloading PDSC files.
645658//
646659// Returns:
647- // - error: An error if any issue occurs during the update process.
648- //
649- // The function performs the following steps:
650- // 1. Lists all PDSC files in the installation web directory.
651- // 2. For each PDSC file, it reads the file and checks if the pack is still present in the public index.
652- // 3. If the pack is no longer present, it deletes the PDSC file.
653- // 4. If the pack is present but has a newer version in the public index, it downloads the latest version.
654- // 5. Lists all PDSC files in the local directory and repeats the update process for these files.
655- func UpdateInstalledPDSCFiles (pidxXML , oldPidxXML * xml.PidxXML , concurrency int , timeout int ) error {
656- log .Info ("Updating PDSC files of public packs" )
657-
660+ // - error: An error if any operation fails, otherwise nil.
661+ func UpdateInstalledPDSCFiles (pidxXML , oldPidxXML * xml.PidxXML , updatePrivatePdsc , showInfo bool , concurrency int , timeout int ) error {
658662 ctx := context .TODO ()
659663 concurrency = CheckConcurrency (concurrency )
660664 sem := semaphore .NewWeighted (int64 (concurrency ))
661665
662666 var errTags lockedSlice
663667
664668 if oldPidxXML != nil && ! oldPidxXML .Empty () {
669+ var pdscToUpdate []xml.PdscTag
670+ updatingMessageShown := false
671+ // Find all pdsc tags that are in the new pidxXML but not in the oldPidxXML
672+ // or have a different URL (indicating a new version)
673+ // and add them to the pdscToUpdate slice
665674 for _ , pdscTag := range pidxXML .ListPdscTags () {
666675 if oldPidxXML .HasPdsc (pdscTag ) != xml .PdscIndexNotFound {
667676 continue // found in old pidx and same URL
668677 }
669678 oldTags := oldPidxXML .FindPdscNameTags (pdscTag )
670679 if len (oldTags ) != 0 {
671- log .Infof ("%s::%s has a new version %q, previous was %q" , pdscTag .Vendor , pdscTag .Name , pdscTag .Version , oldTags [0 ].Version )
680+ if ! updatingMessageShown {
681+ log .Info ("Updating cached public PDSC files with new version" )
682+ updatingMessageShown = true
683+ }
684+ if showInfo {
685+ log .Infof ("%s::%s has a new version %q, previous was %q" , pdscTag .Vendor , pdscTag .Name , pdscTag .Version , oldTags [0 ].Version )
686+ }
687+ pdscToUpdate = append (pdscToUpdate , pdscTag )
688+ }
689+ }
690+ // Avoid repeated calls to IsTerminalInteractive
691+ // as it cleans the stdout buffer
692+ interactiveTerminal := utils .IsTerminalInteractive ()
693+ var progress * progressbar.ProgressBar
694+ var encodedProgress * utils.EncodedProgress
672695
673- if concurrency == 0 {
674- massDownloadPdscFiles (pdscTag , false , timeout , & errTags )
675- } else {
676- if err := sem .Acquire (ctx , 1 ); err != nil {
677- log .Errorf ("Failed to acquire semaphore: %v" , err )
678- break
696+ if ! showInfo && len (pdscToUpdate ) > 0 {
697+ if utils .GetEncodedProgress () {
698+ encodedProgress = utils .NewEncodedProgress (int64 (len (pdscToUpdate )), 0 , "PDSC files updated:" )
699+ } else if interactiveTerminal && log .GetLevel () != log .ErrorLevel {
700+ progress = progressbar .Default (int64 (len (pdscToUpdate )), "I:" )
701+ }
702+ }
703+ for _ , pdscTag := range pdscToUpdate {
704+ if concurrency == 0 {
705+ if ! showInfo {
706+ if utils .GetEncodedProgress () {
707+ _ = encodedProgress .Add (1 )
708+ } else if interactiveTerminal && log .GetLevel () != log .ErrorLevel {
709+ _ = progress .Add64 (1 )
679710 }
680-
681- go func (pdscTag xml.PdscTag , errTags * lockedSlice ) {
682- defer sem .Release (1 )
683- massDownloadPdscFiles (pdscTag , false , timeout , errTags )
684- }(pdscTag , & errTags )
685711 }
712+ massDownloadPdscFiles (pdscTag , false , showInfo , timeout , & errTags )
713+ } else {
714+ if err := sem .Acquire (ctx , 1 ); err != nil {
715+ log .Errorf ("Failed to acquire semaphore: %v" , err )
716+ break
717+ }
718+
719+ go func (pdscTag xml.PdscTag , errTags * lockedSlice ) {
720+ defer sem .Release (1 )
721+ if ! showInfo {
722+ if utils .GetEncodedProgress () {
723+ _ = encodedProgress .Add (1 )
724+ } else if interactiveTerminal && log .GetLevel () != log .ErrorLevel {
725+ _ = progress .Add64 (1 )
726+ }
727+ }
728+ massDownloadPdscFiles (pdscTag , false , showInfo , timeout , errTags )
729+ }(pdscTag , & errTags )
686730 }
687731 }
688732 if len (errTags .slice ) > 0 {
@@ -712,6 +756,10 @@ func UpdateInstalledPDSCFiles(pidxXML, oldPidxXML *xml.PidxXML, concurrency int,
712756 utils .SetReadOnly (Installation .PublicIndex )
713757 }
714758
759+ if ! updatePrivatePdsc {
760+ return nil
761+ }
762+
715763 pdscFiles , err := utils .ListDir (Installation .LocalDir , ".pdsc$" )
716764 if err != nil {
717765 return err
@@ -721,6 +769,11 @@ func UpdateInstalledPDSCFiles(pidxXML, oldPidxXML *xml.PidxXML, concurrency int,
721769 if utils .GetEncodedProgress () {
722770 log .Infof ("[J%d:F%q]" , numPdsc , Installation .LocalDir )
723771 }
772+ if numPdsc == 0 {
773+ return nil
774+ }
775+
776+ log .Info ("Updating PDSC files of private packs" )
724777
725778 for _ , pdscFile := range pdscFiles {
726779 log .Debugf ("Checking if %q needs updating" , pdscFile )
@@ -816,7 +869,7 @@ func UpdatePublicIndexIfOnline() error {
816869 err = Installation .checkUpdateCfg (& updateConf )
817870 if err != nil {
818871 UnlockPackRoot ()
819- err1 := UpdatePublicIndex (ActualPublicIndex , true , false , false , false , 0 , 0 )
872+ err1 := UpdatePublicIndex (ActualPublicIndex , true , false , false , false , false , false , 0 , 0 )
820873 if err1 != nil {
821874 return err1
822875 }
@@ -829,7 +882,7 @@ func UpdatePublicIndexIfOnline() error {
829882 // if public index does not or not yet exist then download without check
830883 if ! utils .FileExists (Installation .PublicIndex ) {
831884 UnlockPackRoot ()
832- err1 := UpdatePublicIndex (ActualPublicIndex , true , false , false , false , 0 , 0 )
885+ err1 := UpdatePublicIndex (ActualPublicIndex , true , false , false , false , false , false , 0 , 0 )
833886 if err1 != nil {
834887 return err1
835888 }
@@ -848,12 +901,14 @@ func UpdatePublicIndexIfOnline() error {
848901// - sparse: A boolean flag to indicate whether to perform a sparse update.
849902// - downloadPdsc: A boolean flag to indicate whether to download PDSC files.
850903// - downloadRemainingPdscFiles: A boolean flag to indicate whether to download all remaining PDSC files.
904+ // - updatePrivatePdsc: If true, updates private PDSC files during the update process.
905+ // - showInfo: If true, logs informational messages about the download.
851906// - concurrency: The number of concurrent operations allowed.
852907// - timeout: The timeout duration for network operations.
853908//
854909// Returns:
855910// - error: An error if the update fails, otherwise nil.
856- func UpdatePublicIndex (indexPath string , overwrite bool , sparse bool , downloadPdsc bool , downloadRemainingPdscFiles bool , concurrency int , timeout int ) error {
911+ func UpdatePublicIndex (indexPath string , overwrite , sparse , downloadPdsc , downloadRemainingPdscFiles , updatePrivatePdsc , showInfo bool , concurrency int , timeout int ) error {
857912 // TODO: Remove overwrite when cpackget v1 gets released
858913 if ! overwrite {
859914 return errs .ErrCannotOverwritePublicIndex
@@ -886,7 +941,7 @@ func UpdatePublicIndex(indexPath string, overwrite bool, sparse bool, downloadPd
886941 log .Warnf ("Non-HTTPS url: %q" , indexPath )
887942 }
888943
889- indexPath , err = utils .DownloadFile (indexPath , false , false , timeout )
944+ indexPath , err = utils .DownloadFile (indexPath , false , true , true , timeout )
890945 if err != nil {
891946 return err
892947 }
@@ -933,7 +988,7 @@ func UpdatePublicIndex(indexPath string, overwrite bool, sparse bool, downloadPd
933988 }
934989
935990 if ! sparse {
936- err = UpdateInstalledPDSCFiles (Installation .PublicIndexXML , oldPidxXML , concurrency , timeout )
991+ err = UpdateInstalledPDSCFiles (Installation .PublicIndexXML , oldPidxXML , updatePrivatePdsc , showInfo , concurrency , timeout )
937992 if err != nil {
938993 return err
939994 }
@@ -1320,7 +1375,7 @@ func FindPackURL(pack *PackType, testing bool) (string, error) {
13201375 Name : pack .Name ,
13211376 })
13221377 if len (tags ) != 0 {
1323- if err := Installation .downloadPdscFile (tags [0 ], true , false , 0 ); err != nil {
1378+ if err := Installation .downloadPdscFile (tags [0 ], true , true , true , 0 ); err != nil {
13241379 return "" , err
13251380 }
13261381 } else {
@@ -1331,7 +1386,7 @@ func FindPackURL(pack *PackType, testing bool) (string, error) {
13311386 URL : pack .URL ,
13321387 Vendor : pack .Vendor ,
13331388 Name : pack .Name ,
1334- }, true , false , 0 ); err != nil {
1389+ }, true , true , true , 0 ); err != nil {
13351390 return "" , err
13361391 }
13371392 }
@@ -1358,7 +1413,7 @@ func FindPackURL(pack *PackType, testing bool) (string, error) {
13581413 URL : pack .URL ,
13591414 Vendor : pack .Vendor ,
13601415 Name : pack .Name ,
1361- }, false , false , 0 ); err != nil {
1416+ }, false , true , true , 0 ); err != nil {
13621417 log .Warnf ("Latest pdsc %q does not exist in public index" , xmlTag .Key ())
13631418 return "" , err
13641419 }
@@ -1962,7 +2017,8 @@ func (p *PacksInstallationType) packIsPublic(pack *PackType, pdscTag *xml.PdscTa
19622017// Parameters:
19632018// - pdscTag: An xml.PdscTag object containing metadata about the PDSC file to be downloaded.
19642019// - skipInstalledPdscFiles: A boolean flag indicating whether to skip downloading if the PDSC file already exists locally.
1965- // - noProgressBar: A boolean flag indicating whether to suppress the progress bar during the download.
2020+ // - showInfo: If true, logs informational messages about the download.
2021+ // - showProgressBar: A boolean flag indicating whether to show the progress bar during the download.
19662022// - timeout: An integer specifying the timeout duration (in seconds) for the download operation.
19672023//
19682024// Returns:
@@ -1974,7 +2030,7 @@ func (p *PacksInstallationType) packIsPublic(pack *PackType, pdscTag *xml.PdscTa
19742030// the function switches to the cache URL for downloading.
19752031// - The function downloads the PDSC file, temporarily saves it, and then moves it to the target location,
19762032// ensuring proper file permissions are set before and after the operation.
1977- func (p * PacksInstallationType ) downloadPdscFile (pdscTag xml.PdscTag , skipInstalledPdscFiles , noProgressBar bool , timeout int ) error {
2033+ func (p * PacksInstallationType ) downloadPdscFile (pdscTag xml.PdscTag , skipInstalledPdscFiles , showInfo , showProgressBar bool , timeout int ) error {
19782034 basePdscFile := fmt .Sprintf ("%s.pdsc" , pdscTag .VName ())
19792035 pdscFilePath := filepath .Join (p .WebDir , basePdscFile )
19802036
@@ -2004,7 +2060,7 @@ func (p *PacksInstallationType) downloadPdscFile(pdscTag xml.PdscTag, skipInstal
20042060
20052061 pdscFileURL .Path = path .Join (pdscFileURL .Path , basePdscFile )
20062062
2007- localFileName , err := utils .DownloadFile (pdscFileURL .String (), true , noProgressBar , timeout )
2063+ localFileName , err := utils .DownloadFile (pdscFileURL .String (), true , showInfo , showProgressBar , timeout )
20082064 defer os .Remove (localFileName )
20092065
20102066 if err != nil {
@@ -2066,7 +2122,7 @@ func (p *PacksInstallationType) loadPdscFile(pdscTag xml.PdscTag, timeout int) e
20662122 return nil
20672123 }
20682124
2069- localFileName , err := utils .DownloadFile (pdscFileURL .String (), true , false , timeout )
2125+ localFileName , err := utils .DownloadFile (pdscFileURL .String (), true , true , true , timeout )
20702126 defer os .Remove (localFileName )
20712127
20722128 if err != nil {
0 commit comments