func (c *DownloadClient) Download(ctx context.Context, resourceURL *url.URL, archivePath string, options ...DownloadOption) error {
	opts := newDownloadOptions()
	for _, option := range options {
		option(opts)
	}

	f, err := c.fileSystem.Create(archivePath)
	if err != nil {
		return errors.Trace(err)
	}
	defer func() {
		_ = f.Close()
	}()

	r, err := c.downloadFromURL(ctx, resourceURL)
	if err != nil {
		return errors.Annotatef(err, "cannot retrieve %q", resourceURL)
	}
	defer func() {
		_ = r.Body.Close()
	}()

	var writer io.Writer = f
	if opts.progressBar != nil {
		// Progress bar has this nifty feature where you can supply a name. In
		// this case we can supply one to help with UI feedback.
		var name string
		if n := ctx.Value(DownloadNameKey); n != nil {
			if s, ok := n.(string); ok && s != "" {
				name = s
			}
		}

		// TODO (stickupkid): Would be good to verify the size, but
		// unfortunately we don't have the information to hand. That information
		// is further up the stack.
		downloadSize := float64(r.ContentLength)
		opts.progressBar.Start(name, downloadSize)
		defer opts.progressBar.Finished()

		writer = io.MultiWriter(f, opts.progressBar)
	}

	if _, err := io.Copy(writer, r.Body); err != nil {
		return errors.Trace(err)
	}

	return nil
}
// Download returns the raw charm zip file, which is retrieved from the given
// URL.
// It is expected that the archive path doesn't already exist and if it does, it
// will error out. It is expected that the callee handles the clean up of the
// archivePath.
// TODO (stickupkid): We should either create and remove, or take a file and
// let the callee remove. The fact that the operations are asymmetrical can lead
// to unexpected expectations; namely leaking of files.
Download returns the raw charm zip file, which is retrieved from the given
URL.
It is expected that the archive path doesn't already exist and if it does, it
will error out. It is expected that the callee handles the clean up of the
archivePath.
TODO (stickupkid): We should either create and remove, or take a file and
let the callee remove. The fact that the operations are asymmetrical can lead
to unexpected expectations; namely leaking of files.
// Download returns the raw charm zip file which is retrieved from the given // URL . // It is expected that the archive path doesn ' t already exist and if it does it // will error out . It is expected that the callee handles the clean up of the // archivePath . // TODO ( stickupkid ) : We should either create and remove or take a file and // let the callee remove . The fact that the operations are asymmetrical can lead // to unexpected expectations ; namely leaking of files .
func (c *DownloadClient) Download(ctx context.Context, resourceURL *url.URL, archivePath string, options ...DownloadOption) error {
	opts := newDownloadOptions()
	for _, option := range options {
		option(opts)
	}
	f, err := c.fileSystem.Create(archivePath)
	if err != nil {
		return errors.Trace(err)
	}
	defer func() {
		_ = f.Close()
	}()
	r, err := c.downloadFromURL(ctx, resourceURL)
	if err != nil {
		return errors.Annotatef(err, "cannot retrieve %q", resourceURL)
	}
	defer func() {
		_ = r.Body.Close()
	}()
	var writer io.Writer = f
	if opts.progressBar != nil {
		var name string
		if n := ctx.Value(DownloadNameKey); n != nil {
			if s, ok := n.(string); ok && s != "" {
				name = s
			}
		}
		downloadSize := float64(r.ContentLength)
		opts.progressBar.Start(name, downloadSize)
		defer opts.progressBar.Finished()
		writer = io.MultiWriter(f, opts.progressBar)
	}
	if _, err := io.Copy(writer, r.Body); err != nil {
		return errors.Trace(err)
	}
	return nil
}
func ( c * DownloadClient ) Download ( ctx context . Context , resourceURL * url . URL , archivePath string , options ... DownloadOption ) error { opts := newDownloadOptions ( ) for _ , option := range options { option ( opts ) } f , err := c . fileSystem . Create ( archivePath ) if err != nil { return errors . Trace ( err ) } defer func ( ) { _ = f . Close ( ) } ( ) r , err := c . downloadFromURL ( ctx , resourceURL ) if err != nil { return errors . Annotatef ( err , " " , resourceURL ) } defer func ( ) { _ = r . Body . Close ( ) } ( ) var writer io . Writer = f if opts . progressBar != nil { var name string if n := ctx . Value ( DownloadNameKey ) ; n != nil { if s , ok := n . ( string ) ; ok && s != " " { name = s } } downloadSize := float64 ( r . ContentLength ) opts . progressBar . Start ( name , downloadSize ) defer opts . progressBar . Finished ( ) writer = io . MultiWriter ( f , opts . progressBar ) } if _ , err := io . Copy ( writer , r . Body ) ; err != nil { return errors . Trace ( err ) } return nil }
Download returns the raw charm zip file, which is retrieved from the given
URL.
Download returns the raw charm zip file which is retrieved from the given URL .
// Progress bar has this nifty feature where you can supply a name. In // this case we can supply one to help with UI feedback. // TODO (stickupkid): Would be good to verify the size, but // unfortunately we don't have the information to hand. That information // is further up the stack.