func (c *Client) uploadPart(uploadId string, part int, r io.ReaderAt, p0, p1 int64, progress Progress) (string, error) {
	h := sha512.New384()
	if _, err := io.Copy(h, io.NewSectionReader(r, p0, p1-p0)); err != nil {
		return "", errgo.Notef(err, "cannot read resource")
	}
	hash := fmt.Sprintf("%x", h.Sum(nil))
	var lastError error
	section := newProgressReader(io.NewSectionReader(r, p0, p1-p0), progress, p0)
	for i := 0; i < 10; i++ {
		req, err := http.NewRequest("PUT", "", section)
		if err != nil {
			return "", errgo.Mask(err)
		}
		req.Header.Set("Content-Type", "application/octet-stream")
		req.ContentLength = p1 - p0
		resp, err := c.Do(req, fmt.Sprintf("/upload/%s/%d?hash=%s&offset=%d", uploadId, part, hash, p0))
		if err == nil {
			// Success
			resp.Body.Close()
			return hash, nil
		}
		if isAPIError(err) {
			// It's a genuine error from the charm store, so
			// stop trying.
			return "", errgo.Mask(err, isAPIError)
		}
		progress.Error(err)
		lastError = err
		section.Seek(0, 0)
		// Try again.
	}
	return "", errgo.Notef(lastError, "too many attempts; last error")
}
// uploadPart uploads a single part of a multipart upload
// and returns the hash of the part.
uploadPart uploads a single part of a multipart upload
and returns the hash of the part.
// uploadPart uploads a single part of a multipart upload // and returns the hash of the part .
func (c *Client) uploadPart(uploadId string, part int, r io.ReaderAt, p0, p1 int64, progress Progress) (string, error) {
	h := sha512.New384()
	if _, err := io.Copy(h, io.NewSectionReader(r, p0, p1-p0)); err != nil {
		return "", errgo.Notef(err, "cannot read resource")
	}
	hash := fmt.Sprintf("%x", h.Sum(nil))
	var lastError error
	section := newProgressReader(io.NewSectionReader(r, p0, p1-p0), progress, p0)
	for i := 0; i < 10; i++ {
		req, err := http.NewRequest("PUT", "", section)
		if err != nil {
			return "", errgo.Mask(err)
		}
		req.Header.Set("Content-Type", "application/octet-stream")
		req.ContentLength = p1 - p0
		resp, err := c.Do(req, fmt.Sprintf("/upload/%s/%d?hash=%s&offset=%d", uploadId, part, hash, p0))
		if err == nil {
			resp.Body.Close()
			return hash, nil
		}
		if isAPIError(err) {
			return "", errgo.Mask(err, isAPIError)
		}
		progress.Error(err)
		lastError = err
		section.Seek(0, 0)
	}
	return "", errgo.Notef(lastError, "too many attempts; last error")
}
func ( c * Client ) uploadPart ( uploadId string , part int , r io . ReaderAt , p0 , p1 int64 , progress Progress ) ( string , error ) { h := sha512 . New384 ( ) if _ , err := io . Copy ( h , io . NewSectionReader ( r , p0 , p1 - p0 ) ) ; err != nil { return " " , errgo . Notef ( err , " " ) } hash := fmt . Sprintf ( " " , h . Sum ( nil ) ) var lastError error section := newProgressReader ( io . NewSectionReader ( r , p0 , p1 - p0 ) , progress , p0 ) for i := 0 ; i < 10 ; i ++ { req , err := http . NewRequest ( " " , " " , section ) if err != nil { return " " , errgo . Mask ( err ) } req . Header . Set ( " " , " " ) req . ContentLength = p1 - p0 resp , err := c . Do ( req , fmt . Sprintf ( " " , uploadId , part , hash , p0 ) ) if err == nil { resp . Body . Close ( ) return hash , nil } if isAPIError ( err ) { return " " , errgo . Mask ( err , isAPIError ) } progress . Error ( err ) lastError = err section . Seek ( 0 , 0 ) } return " " , errgo . Notef ( lastError , " " ) }
uploadPart uploads a single part of a multipart upload
and returns the hash of the part.
uploadPart uploads a single part of a multipart upload and returns the hash of the part .
// Success // It's a genuine error from the charm store, so // stop trying. // Try again.