Skip to content

Commit

Permalink
fix: adds error channel to RenderProgressBarForLocalDirWrite (#2117)
Browse files Browse the repository at this point in the history
## Description
Adds an error channel to `utils.RenderProgressBarForLocalDirWrite` to
handle the case where an operation (e.g. `oras.Copy`) is not successful
and we want to kill the goroutine without displaying a 'success' message

Co-authored-by: Wayne Starr <[email protected]>
  • Loading branch information
UncleGedd and Racer159 authored Nov 8, 2023
1 parent 2e0fe5b commit ce4e953
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 6 deletions.
7 changes: 4 additions & 3 deletions src/internal/packager/images/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,11 @@ func (i *ImageConfig) PullAll() ([]ImgInfo, error) {

// Create a thread to update a progress bar as we save the image files to disk
doneSaving := make(chan int)
errorSaving := make(chan int)
var progressBarWaitGroup sync.WaitGroup
progressBarWaitGroup.Add(1)
updateText := fmt.Sprintf("Pulling %d images", imageCount)
go utils.RenderProgressBarForLocalDirWrite(i.ImagesPath, totalBytes, &progressBarWaitGroup, doneSaving, updateText, updateText)
go utils.RenderProgressBarForLocalDirWrite(i.ImagesPath, totalBytes, &progressBarWaitGroup, doneSaving, errorSaving, updateText, updateText)

// Spawn a goroutine for each layer to write it to disk using crane

Expand Down Expand Up @@ -324,7 +325,7 @@ func (i *ImageConfig) PullAll() ([]ImgInfo, error) {

onLayerWritingError := func(err error) error {
// Send a signal to the progress bar that we're done and wait for the thread to finish
doneSaving <- 1
errorSaving <- 1
progressBarWaitGroup.Wait()
message.WarnErr(err, "Failed to write image layers, trying again up to 3 times...")
if strings.HasPrefix(err.Error(), "expected blob size") {
Expand Down Expand Up @@ -391,7 +392,7 @@ func (i *ImageConfig) PullAll() ([]ImgInfo, error) {

onImageSavingError := func(err error) error {
// Send a signal to the progress bar that we're done and wait for the thread to finish
doneSaving <- 1
errorSaving <- 1
progressBarWaitGroup.Wait()
message.WarnErr(err, "Failed to write image config or manifest, trying again up to 3 times...")
return err
Expand Down
4 changes: 3 additions & 1 deletion src/pkg/oci/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,14 @@ func (o *OrasRemote) CopyWithProgress(layers []ocispec.Descriptor, store oras.Ta

// Create a thread to update a progress bar as we save the package to disk
doneSaving := make(chan int)
encounteredErr := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
successText := fmt.Sprintf("Pulling %q", helpers.OCIURLPrefix+o.repo.Reference.String())
go utils.RenderProgressBarForLocalDirWrite(destinationDir, estimatedBytes, &wg, doneSaving, "Pulling", successText)
go utils.RenderProgressBarForLocalDirWrite(destinationDir, estimatedBytes, &wg, doneSaving, encounteredErr, "Pulling", successText)
_, err := oras.Copy(o.ctx, o.repo, o.repo.Reference.String(), store, o.repo.Reference.String(), copyOpts)
if err != nil {
encounteredErr <- 1
return err
}

Expand Down
9 changes: 7 additions & 2 deletions src/pkg/utils/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ func ByteFormat(inputNum float64, precision int) string {
}

// RenderProgressBarForLocalDirWrite creates a progress bar that continuously tracks the progress of writing files to a local directory and all of its subdirectories.
// NOTE: This function runs infinitely until the completeChan is triggered, this function should be run in a goroutine while a different thread/process is writing to the directory.
func RenderProgressBarForLocalDirWrite(filepath string, expectedTotal int64, wg *sync.WaitGroup, completeChan chan int, updateText string, successText string) {
// NOTE: This function runs infinitely until either completeChan or errChan is triggered, this function should be run in a goroutine while a different thread/process is writing to the directory.
func RenderProgressBarForLocalDirWrite(filepath string, expectedTotal int64, wg *sync.WaitGroup, completeChan chan int, errChan chan int, updateText string, successText string) {

// Create a progress bar
title := fmt.Sprintf("%s (%s of %s)", updateText, ByteFormat(float64(0), 2), ByteFormat(float64(expectedTotal), 2))
Expand All @@ -72,6 +72,11 @@ func RenderProgressBarForLocalDirWrite(filepath string, expectedTotal int64, wg
wg.Done()
return

case <-errChan:
progressBar.Stop()
wg.Done()
return

default:
// Read the directory size
currentBytes, dirErr := GetDirSize(filepath)
Expand Down

0 comments on commit ce4e953

Please sign in to comment.