// Charm returns the charm for the input charmURL.
// If the charm is not found, a NotFoundError is returned.
325243
func (m *Model) Charm(charmURL string) (*Charm, error) {
	defer m.doLocked()()

	charm, found := m.charms[charmURL]
	if !found {
		return nil, errors.NotFoundf("charm %q", charmURL)
	}
	return charm, nil
}
339186
func (st *State) cleanupCharm(charmURL string) error {
	curl, err := charm.ParseURL(charmURL)
	if err != nil {
		return errors.Annotatef(err, "invalid charm URL %v", charmURL)
	}

	ch, err := st.Charm(curl)
	if errors.IsNotFound(err) {
		// Charm already removed.
		logger.Tracef("cleanup charm(%s) no-op, charm already gone", charmURL)
		return nil
	} else if err != nil {
		return errors.Annotate(err, "reading charm")
	}

	logger.Tracef("cleanup charm(%s): Destroy", charmURL)
	err = ch.Destroy()
	switch errors.Cause(err) {
	case nil:
	case errCharmInUse:
		// No cleanup necessary at this time.
		logger.Tracef("cleanup charm(%s): charm still in use", charmURL)
		return nil
	default:
		return errors.Annotate(err, "destroying charm")
	}

	logger.Tracef("cleanup charm(%s): Remove", charmURL)
	if err := ch.Remove(); err != nil {
		return errors.Trace(err)
	}
	return nil
}
589293
func (u *Unit) CharmURL() (*charm.URL, bool) {
	if u.doc.CharmURL == nil {
		return nil, false
	}
	return u.doc.CharmURL, true
}
1329700
func (st *State) AddCharm(info CharmInfo) (stch *Charm, err error) {
	charms, closer := st.db().GetCollection(charmsC)
	defer closer()

	if err := validateCharmVersion(info.Charm); err != nil {
		return nil, errors.Trace(err)
	}
	model, err := st.Model()
	if err != nil {
		return nil, errors.Trace(err)
	}
	if err := validateCharmSeries(model.Type(), info.ID.Series, info.Charm); err != nil {
		return nil, errors.Trace(err)
	}

	query := charms.FindId(info.ID.String()).Select(bson.M{
		"placeholder":   1,
		"pendingupload": 1,
	})
	buildTxn := func(attempt int) ([]txn.Op, error) {
		var doc charmDoc
		if err := query.One(&doc); err == mgo.ErrNotFound {
			if info.ID.Schema == "local" {
				curl, err := st.PrepareLocalCharmUpload(info.ID)
				if err != nil {
					return nil, errors.Trace(err)
				}
				info.ID = curl
				return updateCharmOps(st, info, stillPending)
			}
			return insertCharmOps(st, info)
		} else if err != nil {
			return nil, errors.Trace(err)
		} else if doc.PendingUpload {
			return updateCharmOps(st, info, stillPending)
		} else if doc.Placeholder {
			return updateCharmOps(st, info, stillPlaceholder)
		}
		return nil, errors.AlreadyExistsf("charm %q", info.ID)
	}
	if err = st.db().Run(buildTxn); err == nil {
		return st.Charm(info.ID)
	}
	return nil, errors.Trace(err)
}
416133
func (mr *MockProfileMachineMockRecorder) CharmProfiles() *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CharmProfiles", reflect.TypeOf((*MockProfileMachine)(nil).CharmProfiles))
}
1286348
func (r Repository) Get(id *charm.URL) (charm.Charm, error) {
	withRevision := r.addRevision(id)
	charmData := r.charms[r.channel][*withRevision]
	if charmData == nil {
		return charmData, errors.NotFoundf("cannot retrieve \"%v\": charm", id.String())
	}
	return charmData, nil
}
280332
func (h *charmsHandler) processGet(r *http.Request, st *state.State) (
	archivePath string,
	fileArg string,
	serveIcon bool,
	err error,
) {
	errRet := func(err error) (string, string, bool, error) {
		return "", "", false, err
	}

	query := r.URL.Query()

	// Retrieve and validate query parameters.
	curlString := query.Get("url")
	if curlString == "" {
		return errRet(errors.Errorf("expected url=CharmURL query argument"))
	}
	curl, err := charm.ParseURL(curlString)
	if err != nil {
		return errRet(errors.Trace(err))
	}
	fileArg = query.Get("file")
	if fileArg != "" {
		fileArg = path.Clean(fileArg)
	} else if query.Get("icon") == "1" {
		serveIcon = true
		fileArg = "icon.svg"
	}

	store := storage.NewStorage(st.ModelUUID(), st.MongoSession())
	// Use the storage to retrieve and save the charm archive.
	ch, err := st.Charm(curl)
	if err != nil {
		return errRet(errors.Annotate(err, "cannot get charm from state"))
	}
	charmFileName, err := common.ReadCharmFromStorage(store, h.dataDir, ch.StoragePath())
	if err != nil {
		return errRet(errors.Annotatef(err, "cannot read charm %q from storage", curl))
	}
	return charmFileName, fileArg, serveIcon, nil
}
377405
func (api *APIBase) getConfig(
	args params.ApplicationGet,
	describe func(settings charm.Settings, config *charm.Config) map[string]interface{},
) (params.ApplicationGetResults, error) {
	if err := api.checkCanRead(); err != nil {
		return params.ApplicationGetResults{}, err
	}

	app, err := api.backend.Application(args.ApplicationName)
	if err != nil {
		return params.ApplicationGetResults{}, err
	}

	// We need a guard on the API server-side for direct API callers such as
	// python-libjuju. Always default to the master branch.
	if args.BranchName == "" {
		args.BranchName = model.GenerationMaster
	}
	settings, err := app.CharmConfig(args.BranchName)
	if err != nil {
		return params.ApplicationGetResults{}, err
	}

	ch, _, err := app.Charm()
	if err != nil {
		return params.ApplicationGetResults{}, err
	}
	configInfo := describe(settings, ch.Config())
	appConfig, err := app.ApplicationConfig()
	if err != nil {
		return params.ApplicationGetResults{}, err
	}

	providerSchema, providerDefaults, err := applicationConfigSchema(api.modelType)
	if err != nil {
		return params.ApplicationGetResults{}, err
	}
	appConfigInfo := describeAppConfig(appConfig, providerSchema, caas.ConfigDefaults(providerDefaults))
	var cons constraints.Value
	if app.IsPrincipal() {
		cons, err = app.Constraints()
		if err != nil {
			return params.ApplicationGetResults{}, err
		}
	}
	return params.ApplicationGetResults{
		Application:       args.ApplicationName,
		Charm:             ch.Meta().Name,
		CharmConfig:       configInfo,
		ApplicationConfig: appConfigInfo,
		Constraints:       cons,
		Series:            app.Series(),
		Channel:           string(app.Channel()),
	}, nil
}
1143438
func (a *Application) charmConfigKey() string {
	return applicationCharmConfigKey(a.doc.Name, a.doc.CharmURL)
}
999397
func (mr *MockProfileBackendMockRecorder) Charm(arg0 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Charm", reflect.TypeOf((*MockProfileBackend)(nil).Charm), arg0)
}
754035
func (api *APIBase) GetCharmURL(args params.ApplicationGet) (params.StringResult, error) {
	if err := api.checkCanWrite(); err != nil {
		return params.StringResult{}, errors.Trace(err)
	}
	application, err := api.backend.Application(args.ApplicationName)
	if err != nil {
		return params.StringResult{}, errors.Trace(err)
	}
	charmURL, _ := application.CharmURL()
	return params.StringResult{Result: charmURL.String()}, nil
}
837208
func (r Repository) CharmInfo(charmURL string) (*charms.CharmInfo, error) {
	charmId, err := charm.ParseURL(charmURL)
	if err != nil {
		return nil, errors.Trace(err)
	}
	charmDetails, err := r.Get(charmId)
	if err != nil {
		return nil, errors.Trace(err)
	}

	info := charms.CharmInfo{
		Revision: charmDetails.Revision(),
		URL:      charmId.String(),
		Config:   charmDetails.Config(),
		Meta:     charmDetails.Meta(),
		Actions:  charmDetails.Actions(),
		Metrics:  charmDetails.Metrics(),
	}
	return &info, nil
}
564132
func (c Config) CharmStoreURL() string {
	url := c.asString(CharmStoreURL)
	if url == "" {
		return csclient.ServerURL
	}
	return url
}
850223
func (c *Client) GetCharmURL(branchName, applicationName string) (*charm.URL, error) {
	result := new(params.StringResult)
	args := params.ApplicationGet{
		ApplicationName: applicationName,
		BranchName:      branchName,
	}
	err := c.facade.FacadeCall("GetCharmURL", args, result)
	if err != nil {
		return nil, errors.Trace(err)
	}
	if result.Error != nil {
		return nil, errors.Trace(result.Error)
	}
	return charm.ParseURL(result.Result)
}
892780
func (c *Charm) Macaroon() (macaroon.Slice, error) {
	if len(c.doc.Macaroon) == 0 {
		return nil, nil
	}
	var m macaroon.Slice
	if err := m.UnmarshalBinary(c.doc.Macaroon); err != nil {
		return nil, errors.Trace(err)
	}

	return m, nil
}
1370918
func ReadCharmURL(path string) (*charm.URL, error) {
	surl := ""
	if err := utils.ReadYaml(path, &surl); err != nil {
		return nil, err
	}
	return charm.ParseURL(surl)
}
464391
func (r *UtilService) Uuid() *UtilUuidCall {
	c := &UtilUuidCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	return c
}