func (c *Client) UploadArchive(id *charm.URL, body io.ReadSeeker, hash string, size int64, promulgatedRevision int, chans []params.Channel) (*charm.URL, error) {
	// When uploading archives, it can be a problem that the
	// an error response is returned while we are still writing
	// the body data.
	// To avoid this, we log in first so that we don't need to
	// do the macaroon exchange after POST.
	// Unfortunately this won't help matters if the user is logged in but
	// doesn't have privileges to write to the stated charm.
	// A better solution would be to fix https://github.com/golang/go/issues/3665
	// and use the 100-Continue client functionality.
	//
	// We only need to do this when basic auth credentials are not provided.
	if c.params.User == "" {
		if err := c.Login(); err != nil {
			return nil, errgo.NoteMask(err, "cannot log in", isAPIError)
		}
	}
	method := "POST"
	urlParams := url.Values{
		"hash": {hash},
	}
	if id.Revision != -1 {
		method = "PUT"
		if promulgatedRevision != -1 {
			pr := *id
			pr.User = ""
			pr.Revision = promulgatedRevision
			urlParams.Set("promulgated", pr.Path())
		}
	}

	// Prepare the request.
	req, err := http.NewRequest(method, "", body)
	if err != nil {
		return nil, errgo.Notef(err, "cannot make new request")
	}
	req.Header.Set("Content-Type", "application/zip")
	req.ContentLength = size
	for _, c := range chans {
		urlParams["channel"] = append(urlParams["channel"], string(c))
	}

	// Send the request.
	resp, err := c.Do(
		req,
		"/"+id.Path()+"/archive?"+urlParams.Encode(),
	)
	if err != nil {
		return nil, errgo.NoteMask(err, "cannot post archive", isAPIError)
	}
	defer resp.Body.Close()

	// Parse the response.
	var result params.ArchiveUploadResponse
	if err := httprequest.UnmarshalJSONResponse(resp, &result); err != nil {
		return nil, errgo.NoteMask(err, "cannot unmarshal response", errgo.Any)
	}
	return result.Id, nil
}
// UploadArchive pushes the archive for the charm or bundle represented by
// the given body, its hex-encoded SHA384 hash and its size. It returns
// the resulting entity reference. The given id should include the series
// should usually include the revision, unless a specific revision is required
// (for example when synchronizing between charmstores). If a revision
// is specified, then PUT will be used instead of POST.
//
// This is the method used internally by UploadBundle, UploadCharm and UploadCharmWithRevision;
// one of those methods should usually be used in preference.
UploadArchive pushes the archive for the charm or bundle represented by
the given body, its hex-encoded SHA384 hash and its size. It returns
the resulting entity reference. The given id should include the series
should usually include the revision, unless a specific revision is required
(for example when synchronizing between charmstores). If a revision
is specified, then PUT will be used instead of POST.

This is the method used internally by UploadBundle, UploadCharm and UploadCharmWithRevision;
one of those methods should usually be used in preference.
// UploadArchive pushes the archive for the charm or bundle represented by // the given body its hex - encoded SHA384 hash and its size . It returns // the resulting entity reference . The given id should include the series // should usually include the revision unless a specific revision is required // ( for example when synchronizing between charmstores ) . If a revision // is specified then PUT will be used instead of POST . // // This is the method used internally by UploadBundle UploadCharm and UploadCharmWithRevision ; // one of those methods should usually be used in preference .
func (c *Client) UploadArchive(id *charm.URL, body io.ReadSeeker, hash string, size int64, promulgatedRevision int, chans []params.Channel) (*charm.URL, error) {
	 We only need to do this when basic auth credentials are not provided.
	if c.params.User == "" {
		if err := c.Login(); err != nil {
			return nil, errgo.NoteMask(err, "cannot log in", isAPIError)
		}
	}
	method := "POST"
	urlParams := url.Values{
		"hash": {hash},
	}
	if id.Revision != -1 {
		method = "PUT"
		if promulgatedRevision != -1 {
			pr := *id
			pr.User = ""
			pr.Revision = promulgatedRevision
			urlParams.Set("promulgated", pr.Path())
		}
	}
	 Prepare the request.
	req, err := http.NewRequest(method, "", body)
	if err != nil {
		return nil, errgo.Notef(err, "cannot make new request")
	}
	req.Header.Set("Content-Type", "application/zip")
	req.ContentLength = size
	for _, c := range chans {
		urlParams["channel"] = append(urlParams["channel"], string(c))
	}
	 Send the request.
	resp, err := c.Do(
		req,
		"/"+id.Path()+"/archive?"+urlParams.Encode(),
	)
	if err != nil {
		return nil, errgo.NoteMask(err, "cannot post archive", isAPIError)
	}
	defer resp.Body.Close()
	 Parse the response.
	var result params.ArchiveUploadResponse
	if err := httprequest.UnmarshalJSONResponse(resp, &result); err != nil {
		return nil, errgo.NoteMask(err, "cannot unmarshal response", errgo.Any)
	}
	return result.Id, nil
}
func ( c * Client ) UploadArchive ( id * charm . URL , body io . ReadSeeker , hash string , size int64 , promulgatedRevision int , chans [ ] params . Channel ) ( * charm . URL , error ) { if c . params . User == " " { if err := c . Login ( ) ; err != nil { return nil , errgo . NoteMask ( err , " " , isAPIError ) } } method := " " urlParams := url . Values { " " : { hash } , } if id . Revision != - 1 { method = " " if promulgatedRevision != - 1 { pr := * id pr . User = " " pr . Revision = promulgatedRevision urlParams . Set ( " " , pr . Path ( ) ) } } req , err := http . NewRequest ( method , " " , body ) if err != nil { return nil , errgo . Notef ( err , " " ) } req . Header . Set ( " " , " " ) req . ContentLength = size for _ , c := range chans { urlParams [ " " ] = append ( urlParams [ " " ] , string ( c ) ) } resp , err := c . Do ( req , " " + id . Path ( ) + " " + urlParams . Encode ( ) , ) if err != nil { return nil , errgo . NoteMask ( err , " " , isAPIError ) } defer resp . Body . Close ( ) var result params . ArchiveUploadResponse if err := httprequest . UnmarshalJSONResponse ( resp , & result ) ; err != nil { return nil , errgo . NoteMask ( err , " " , errgo . Any ) } return result . Id , nil }
UploadArchive pushes the archive for the charm or bundle represented by
the given body, its hex-encoded SHA384 hash and its size.
UploadArchive pushes the archive for the charm or bundle represented by the given body its hex - encoded SHA384 hash and its size .
// When uploading archives, it can be a problem that the // an error response is returned while we are still writing // the body data. // To avoid this, we log in first so that we don't need to // do the macaroon exchange after POST. // Unfortunately this won't help matters if the user is logged in but // doesn't have privileges to write to the stated charm. // A better solution would be to fix https://github.com/golang/go/issues/3665 // and use the 100-Continue client functionality. // // We only need to do this when basic auth credentials are not provided. // Prepare the request. // Send the request. // Parse the response.