From f8192e937b84ed0c6eca12ad7b38f6fb99b8b23e Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Tue, 5 Jan 2021 15:57:59 -0800 Subject: [PATCH 1/8] add flags to state pull --- cmd/state/internal/cmdtree/pull.go | 19 ++++++- internal/runners/pull/pull.go | 82 +++++++++++++++++++++++++++--- locale/en-us.yaml | 4 +- test/integration/pull_int_test.go | 31 +++++++++++ 4 files changed, 124 insertions(+), 12 deletions(-) diff --git a/cmd/state/internal/cmdtree/pull.go b/cmd/state/internal/cmdtree/pull.go index edb9dc7df2..75584db654 100644 --- a/cmd/state/internal/cmdtree/pull.go +++ b/cmd/state/internal/cmdtree/pull.go @@ -10,14 +10,29 @@ import ( func newPullCommand(prime *primer.Values) *captain.Command { runner := pull.New(prime) + params := &pull.PullParams{} + return captain.NewCommand( "pull", locale.Tl("pull_title", "Pulling Remote Project"), locale.Tl("pull_description", "Pull in the latest version of your project from the ActiveState Platform"), prime.Output(), - []*captain.Flag{}, + []*captain.Flag{ + { + Name: "force", + Shorthand: "", + Description: locale.Tl("flag_state_pull_force_description", "Force pulling specified project even if it is unrelated to checked out one"), + Value: ¶ms.Force, + }, + { + Name: "set-project", + Shorthand: "", + Description: locale.Tl("flag_state_pull_set_project_description", "project even if it is unrelated to checked out one"), + Value: ¶ms.SetProject, + }, + }, []*captain.Argument{}, func(cmd *captain.Command, args []string) error { - return runner.Run() + return runner.Run(params) }).SetGroup(VCSGroup) } diff --git a/internal/runners/pull/pull.go b/internal/runners/pull/pull.go index 8bdb51b147..9822ae394a 100644 --- a/internal/runners/pull/pull.go +++ b/internal/runners/pull/pull.go @@ -6,27 +6,38 @@ import ( "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" + "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/hail" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/logging" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/primer" + "github.com/ActiveState/cli/internal/prompt" "github.com/ActiveState/cli/pkg/platform/model" "github.com/ActiveState/cli/pkg/project" + "github.com/go-openapi/strfmt" ) type Pull struct { + prompt prompt.Prompter project *project.Project out output.Outputer } +type PullParams struct { + Force bool + SetProject string +} + type primeable interface { + primer.Prompter primer.Projecter primer.Outputer } func New(prime primeable) *Pull { return &Pull{ + prime.Prompt(), prime.Project(), prime.Output(), } @@ -48,30 +59,49 @@ func (f *outputFormat) MarshalOutput(format output.Format) interface{} { return f } -func (p *Pull) Run() error { +func (p *Pull) Run(params *PullParams) error { if p.project == nil { return locale.NewInputError("err_no_project") } - if p.project.IsHeadless() { + if p.project.IsHeadless() && params.SetProject == "" { return locale.NewInputError("err_pull_headless", "You must first create a project. Please visit {{.V0}} to create your project.", p.project.URL()) } - // Retrieve latest commit ID on platform - latestID, err := model.LatestCommitID(p.project.Owner(), p.project.Name()) + // Determine the project to pull from + target, err := targetProject(p.project, params.SetProject) if err != nil { - return locale.WrapInputError(err, "err_pull_commit", "Could not retrieve the latest commit for your project.") + return errs.Wrap(err, "Unable to determine target project") + } + + if params.SetProject != "" { + related, err := areCommitsRelated(*target.CommitID, p.project.CommitUUID()) + if !related && !params.Force { + confirmed, err := p.prompt.Confirm(locale.T("confirm"), locale.Tl("confirm_unrelated_pull_set_project", "If you switch to {{.V0}}, you may lose changes to your project.", target.String()), false) + if err != nil { + return locale.WrapError(err, "err_pull_confirm", "Failed to get user confirmation to update project") + } + if !confirmed { + return locale.NewInputError("err_pull_aborted", "Pull aborted by user") + } + } + + err = p.project.Source().SetNamespace(target.Owner, target.Project) + if err != nil { + return locale.WrapError(err, "err_pull_update_namespace", "Cannot update the namespace in your project file.") + } } // Update the commit ID in the activestate.yaml - if p.project.CommitID() != latestID.String() { - err := p.project.Source().SetCommit(latestID.String(), false) + if p.project.CommitID() != target.CommitID.String() { + p.project.Source().SetNamespace(target.Owner, target.Project) + err := p.project.Source().SetCommit(target.CommitID.String(), false) if err != nil { return locale.WrapError(err, "err_pull_update", "Cannot update the commit in your project file.") } p.out.Print(&outputFormat{ - locale.T("pull_updated"), + locale.Tr("pull_updated", target.String(), target.CommitID.String()), true, }) } else { @@ -96,3 +126,39 @@ func (p *Pull) Run() error { return nil } + +func targetProject(prj *project.Project, overwrite string) (*project.Namespaced, error) { + ns := prj.Namespace() + if overwrite != "" { + var err error + ns, err = project.ParseNamespace(overwrite) + if err != nil { + return nil, locale.WrapInputError(err, "pull_set_project_parse_err", "Failed to parse namespace {{.V0}}", overwrite) + } + } + + // Retrieve commit ID to set the project to (if unset) + if ns.CommitID == nil || *ns.CommitID == "" { + var err error + ns.CommitID, err = model.LatestCommitID(ns.Owner, ns.Project) + if err != nil { + return nil, locale.WrapError(err, "err_pull_commit", "Could not retrieve the latest commit for your project.") + } + } + + return ns, nil +} + +func areCommitsRelated(targetCommit strfmt.UUID, sourceCommmit strfmt.UUID) (bool, error) { + history, err := model.CommitHistoryFromID(targetCommit) + if err != nil { + return false, locale.WrapError(err, "err_pull_commit_history", "Could not fetch commit history for target project.") + } + + for _, c := range history { + if sourceCommmit.String() == c.CommitID.String() { + return true, nil + } + } + return false, nil +} diff --git a/locale/en-us.yaml b/locale/en-us.yaml index ba732bd025..732f8fc5f7 100644 --- a/locale/en-us.yaml +++ b/locale/en-us.yaml @@ -637,7 +637,7 @@ secrets_row_value_unset: pull_not_updated: other: Your activestate.yaml is already up to date! pull_updated: - other: Your activestate.yaml has been updated to the latest version available. + other: Your project in the activestate.yaml has been updated to {{.V0}}@{{.V1}}. keypair_cmd_description: other: Manage Your Keypair keypair_generate_cmd_description: @@ -1628,4 +1628,4 @@ package_ingredient_alternatives_more: bundle_ingredient_alternatives_more: other: " - .. (to see more results run `state bundles search {{.V0}}`)" err_lock_version_invalid: - other: "The locked version '{{.V0}}' could not be verified, are you sure it's valid?" \ No newline at end of file + other: "The locked version '{{.V0}}' could not be verified, are you sure it's valid?" diff --git a/test/integration/pull_int_test.go b/test/integration/pull_int_test.go index dcc3db5f32..3a48908dbc 100644 --- a/test/integration/pull_int_test.go +++ b/test/integration/pull_int_test.go @@ -29,6 +29,37 @@ func (suite *PullIntegrationTestSuite) TestPull() { cp.ExpectExitCode(0) } +func (suite *PullIntegrationTestSuite) TestPullSetProject() { + suite.OnlyRunForTags(tagsuite.Pull) + ts := e2e.New(suite.T(), false) + defer ts.Close() + + ts.PrepareActiveStateYAML(`project: https://platform.activestate.com/ActiveState-CLI/small-python?commitID=9733d11a-dfb3-41de-a37a-843b7c421db4`) + + // update to related project + cp := ts.Spawn("pull", "--set-project", "ActiveState-CLI/small-python-fork") + cp.Expect("activestate.yaml has been updated") + cp.ExpectExitCode(0) +} + +func (suite *PullIntegrationTestSuite) TestPullSetProjectUnrelated() { + suite.OnlyRunForTags(tagsuite.Pull) + ts := e2e.New(suite.T(), false) + defer ts.Close() + + ts.PrepareActiveStateYAML(`project: "https://platform.activestate.com/ActiveState-CLI/small-python?commitID=9733d11a-dfb3-41de-a37a-843b7c421db4"`) + + cp := ts.Spawn("pull", "--set-project", "ActiveState-CLI/Python3") + cp.ExpectLongString("you may lose changes to your project") + cp.SendLine("n") + cp.Expect("Pull aborted by user") + cp.ExpectNotExitCode(0) + + cp = ts.Spawn("pull", "--force", "--set-project", "ActiveState-CLI/Python3") + cp.Expect("activestate.yaml has been updated") + cp.ExpectExitCode(0) +} + func TestPullIntegrationTestSuite(t *testing.T) { suite.Run(t, new(PullIntegrationTestSuite)) } From 266342077614d945b2880ee5ac811fe38e07ed85 Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Tue, 5 Jan 2021 16:05:43 -0800 Subject: [PATCH 2/8] fix integration tests --- test/integration/activate_int_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/activate_int_test.go b/test/integration/activate_int_test.go index 31f5e1808c..b3ba0b2431 100644 --- a/test/integration/activate_int_test.go +++ b/test/integration/activate_int_test.go @@ -244,7 +244,7 @@ version: %s e2e.WithArgs("pull"), e2e.AppendEnv("ACTIVESTATE_CLI_DISABLE_RUNTIME=false"), ) - cp.Expect("Your activestate.yaml has been updated to the latest version available") + cp.Expect("Your activestate.yaml has been updated to") cp.ExpectExitCode(0) c2 := ts.Spawn("activate") @@ -363,7 +363,7 @@ version: %s // Pull to ensure we have an up to date config file cp := ts.Spawn("pull") - cp.Expect("Your activestate.yaml has been updated to the latest version available") + cp.Expect("Your activestate.yaml has been updated to") cp.ExpectExitCode(0) // Activate in the subdirectory @@ -398,7 +398,7 @@ project: "https://platform.activestate.com/ActiveState-CLI/Python3" // Pull to ensure we have an up to date config file cp := ts.Spawn("pull") - cp.Expect("Your activestate.yaml has been updated to the latest version available") + cp.Expect("Your activestate.yaml has been updated to") cp.ExpectExitCode(0) // Activate in the subdirectory From f89442ac8f4f7e5a68ad6549cd4c44b1fc920f1f Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Wed, 6 Jan 2021 10:22:41 -0800 Subject: [PATCH 3/8] fix tests again --- test/integration/activate_int_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/activate_int_test.go b/test/integration/activate_int_test.go index b3ba0b2431..c4f9d58d6a 100644 --- a/test/integration/activate_int_test.go +++ b/test/integration/activate_int_test.go @@ -244,7 +244,7 @@ version: %s e2e.WithArgs("pull"), e2e.AppendEnv("ACTIVESTATE_CLI_DISABLE_RUNTIME=false"), ) - cp.Expect("Your activestate.yaml has been updated to") + cp.Expect("activestate.yaml has been updated to") cp.ExpectExitCode(0) c2 := ts.Spawn("activate") @@ -363,7 +363,7 @@ version: %s // Pull to ensure we have an up to date config file cp := ts.Spawn("pull") - cp.Expect("Your activestate.yaml has been updated to") + cp.Expect("activestate.yaml has been updated to") cp.ExpectExitCode(0) // Activate in the subdirectory @@ -398,7 +398,7 @@ project: "https://platform.activestate.com/ActiveState-CLI/Python3" // Pull to ensure we have an up to date config file cp := ts.Spawn("pull") - cp.Expect("Your activestate.yaml has been updated to") + cp.Expect("activestate.yaml has been updated to") cp.ExpectExitCode(0) // Activate in the subdirectory From fca00b1703218d21bb6a4759836fe21912bb4a5b Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Thu, 7 Jan 2021 10:21:02 -0800 Subject: [PATCH 4/8] remove os.Exit from config --- cmd/state/forward.go | 15 ++--- cmd/state/internal/cmdtree/activate.go | 1 + cmd/state/internal/cmdtree/auth.go | 3 + cmd/state/internal/cmdtree/bundles.go | 4 ++ cmd/state/internal/cmdtree/clean.go | 4 ++ cmd/state/internal/cmdtree/cmdtree.go | 2 + cmd/state/internal/cmdtree/deploy.go | 5 ++ cmd/state/internal/cmdtree/events.go | 2 + cmd/state/internal/cmdtree/export.go | 7 ++ cmd/state/internal/cmdtree/fork.go | 1 + cmd/state/internal/cmdtree/history.go | 1 + cmd/state/internal/cmdtree/init.go | 1 + cmd/state/internal/cmdtree/invite.go | 1 + cmd/state/internal/cmdtree/languages.go | 2 + cmd/state/internal/cmdtree/organizations.go | 1 + cmd/state/internal/cmdtree/packages.go | 6 ++ cmd/state/internal/cmdtree/platforms.go | 4 ++ cmd/state/internal/cmdtree/prepare.go | 1 + cmd/state/internal/cmdtree/projects.go | 7 +- cmd/state/internal/cmdtree/protocol.go | 1 + cmd/state/internal/cmdtree/pull.go | 1 + cmd/state/internal/cmdtree/push.go | 4 +- cmd/state/internal/cmdtree/revert.go | 1 + cmd/state/internal/cmdtree/run.go | 1 + cmd/state/internal/cmdtree/scripts.go | 2 + cmd/state/internal/cmdtree/secrets.go | 4 ++ cmd/state/internal/cmdtree/shim.go | 1 + cmd/state/internal/cmdtree/show.go | 1 + cmd/state/internal/cmdtree/tutorial.go | 2 + cmd/state/internal/cmdtree/update.go | 2 + cmd/state/main.go | 9 ++- internal/analytics/analytics.go | 18 +++-- internal/analytics/deferred.go | 33 +++++---- internal/captain/command.go | 6 +- internal/config/instance.go | 74 ++++++++++++--------- internal/deprecation/deprecation.go | 9 ++- internal/events/cmdcall/cmdcall.go | 3 +- internal/globaldefault/default.go | 32 ++++----- internal/keypairs/local.go | 24 +++++-- internal/locale/locale.go | 29 +++++--- internal/logging/defaults.go | 19 ++++-- internal/logging/rollbar.go | 10 ++- internal/machineid/machineid.go | 10 ++- internal/primer/primer.go | 13 +++- internal/process/process.go | 21 +++--- internal/runners/activate/activate.go | 10 +-- internal/runners/activate/activation.go | 4 +- internal/runners/activate/namespace.go | 17 +++-- internal/runners/clean/cache.go | 7 +- internal/runners/clean/config.go | 19 ++++-- internal/runners/clean/run.go | 4 +- internal/runners/clean/run_lin_mac.go | 7 +- internal/runners/clean/run_win.go | 7 +- internal/runners/clean/uninstall.go | 14 ++-- internal/runners/deploy/deploy.go | 22 +++--- internal/runners/events/events.go | 1 + internal/runners/events/log.go | 4 +- internal/runners/export/config/config.go | 11 ++- internal/runners/export/privkey.go | 6 +- internal/runners/prepare/prepare.go | 9 ++- internal/runners/projects/projects.go | 5 +- internal/runners/projects/remote.go | 2 +- internal/runners/pull/pull.go | 5 +- internal/runners/push/push.go | 5 +- internal/runners/run/run.go | 10 ++- internal/runners/tutorial/tutorial.go | 14 +++- internal/scriptrun/scriptrun.go | 6 +- internal/subshell/bash/bash.go | 6 +- internal/subshell/cmd/cmd.go | 11 ++- internal/subshell/fish/fish.go | 6 +- internal/subshell/sscommon/rcfile.go | 14 ++-- internal/subshell/subshell.go | 6 +- internal/subshell/tcsh/tcsh.go | 6 +- internal/subshell/zsh/zsh.go | 6 +- locale/en-us.yaml | 2 + pkg/cmdlets/auth/signup.go | 7 +- pkg/platform/authentication/auth.go | 37 ++++++++--- pkg/platform/runtime/runtime.go | 6 +- pkg/projectfile/projectfile.go | 34 +++++++--- 79 files changed, 485 insertions(+), 243 deletions(-) diff --git a/cmd/state/forward.go b/cmd/state/forward.go index 1f6d0c1ae3..5e8dced37b 100644 --- a/cmd/state/forward.go +++ b/cmd/state/forward.go @@ -8,7 +8,6 @@ import ( "github.com/phayes/permbits" "github.com/thoas/go-funk" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" @@ -28,7 +27,7 @@ const LatestVersion = "latest" type forwardFunc func() (int, error) -func forwardFn(args []string, out output.Outputer, pj *project.Project) (forwardFunc, error) { +func forwardFn(bindir string, args []string, out output.Outputer, pj *project.Project) (forwardFunc, error) { if pj == nil { return nil, nil } @@ -58,7 +57,7 @@ func forwardFn(args []string, out output.Outputer, pj *project.Project) (forward // Perform the forward out.Notice(output.Heading(locale.Tl("forward_title", "Version Locked"))) out.Notice(locale.Tr("forward_version", versionInfo.Version)) - code, err := forward(args, versionInfo, out) + code, err := forward(bindir, args, versionInfo, out) if err != nil { if code == 0 { code = 1 @@ -77,9 +76,9 @@ func forwardFn(args []string, out output.Outputer, pj *project.Project) (forward } // forward will forward the call to the appropriate State Tool version if necessary -func forward(args []string, versionInfo *projectfile.VersionInfo, out output.Outputer) (int, error) { +func forward(bindir string, args []string, versionInfo *projectfile.VersionInfo, out output.Outputer) (int, error) { logging.Debug("Forwarding to version %s/%s, arguments: %v", versionInfo.Branch, versionInfo.Version, args[1:]) - binary := forwardBin(versionInfo) + binary := forwardBin(bindir, versionInfo) err := ensureForwardExists(binary, versionInfo, out) if err != nil { return 1, err @@ -98,15 +97,14 @@ func execForward(binary string, args []string) (int, error) { return code, nil } -func forwardBin(versionInfo *projectfile.VersionInfo) string { +func forwardBin(bindir string, versionInfo *projectfile.VersionInfo) string { filename := fmt.Sprintf("%s-%s-%s", constants.CommandName, versionInfo.Branch, versionInfo.Version) if forceFileExt != "" { filename += forceFileExt } else if runtime.GOOS == "windows" { filename += ".exe" } - datadir := config.Get().ConfigPath() - return filepath.Join(datadir, "version-cache", filename) + return filepath.Join(bindir, "version-cache", filename) } func ensureForwardExists(binary string, versionInfo *projectfile.VersionInfo, out output.Outputer) error { @@ -151,4 +149,3 @@ func ensureForwardExists(binary string, versionInfo *projectfile.VersionInfo, ou return nil } - diff --git a/cmd/state/internal/cmdtree/activate.go b/cmd/state/internal/cmdtree/activate.go index b9ddbeb9e8..12e68dcc8f 100644 --- a/cmd/state/internal/cmdtree/activate.go +++ b/cmd/state/internal/cmdtree/activate.go @@ -27,6 +27,7 @@ func newActivateCommand(prime *primer.Values) *captain.Command { "", locale.T("activate_project"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/auth.go b/cmd/state/internal/cmdtree/auth.go index bf9bb57d70..bce3d7f678 100644 --- a/cmd/state/internal/cmdtree/auth.go +++ b/cmd/state/internal/cmdtree/auth.go @@ -17,6 +17,7 @@ func newAuthCommand(prime *primer.Values) *captain.Command { locale.Tl("auth_title", "Signing In To The ActiveState Platform"), locale.T("auth_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "token", @@ -57,6 +58,7 @@ func newSignupCommand(prime *primer.Values) *captain.Command { locale.Tl("signup_title", "Signing Up With The ActiveState Platform"), locale.T("signup_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -72,6 +74,7 @@ func newLogoutCommand(prime *primer.Values) *captain.Command { locale.Tl("logout_title", "Logging Out Of The ActiveState Platform"), locale.T("logout_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { diff --git a/cmd/state/internal/cmdtree/bundles.go b/cmd/state/internal/cmdtree/bundles.go index 9ef7c7af01..755e4e5fb4 100644 --- a/cmd/state/internal/cmdtree/bundles.go +++ b/cmd/state/internal/cmdtree/bundles.go @@ -18,6 +18,7 @@ func newBundlesCommand(prime *primer.Values) *captain.Command { locale.Tl("bundles_title", "Listing Bundles"), locale.Tl("bundles_cmd_description", "Manage bundles used in your project"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "commit", @@ -56,6 +57,7 @@ func newBundleInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("bundle_install_title", "Installing Bundle"), locale.Tl("bundle_install_cmd_description", "Add a new bundle to your project"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -81,6 +83,7 @@ func newBundleUninstallCommand(prime *primer.Values) *captain.Command { locale.Tl("bundle_uninstall_title", "Uninstalling Bundle"), locale.Tl("bundle_uninstall_cmd_description", "Remove bundle from your project"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -106,6 +109,7 @@ func newBundlesSearchCommand(prime *primer.Values) *captain.Command { locale.Tl("bundle_search_title", "Searching Bundles"), locale.Tl("bundle_search_cmd_description", "Search for all available bundles that can be added to your project"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "language", diff --git a/cmd/state/internal/cmdtree/clean.go b/cmd/state/internal/cmdtree/clean.go index 81b67d60b7..58db767abb 100644 --- a/cmd/state/internal/cmdtree/clean.go +++ b/cmd/state/internal/cmdtree/clean.go @@ -13,6 +13,7 @@ func newCleanCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_title", "Cleaning Resources"), locale.T("clean_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { @@ -29,6 +30,7 @@ func newCleanUninstallCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_uninstall_title", "Uninstalling"), locale.T("uninstall_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "force", @@ -57,6 +59,7 @@ func newCleanCacheCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_cache_title", "Cleaning Cached Runtimes"), locale.T("cache_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "force", @@ -87,6 +90,7 @@ func newCleanConfigCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_config_title", "Cleaning Configuration"), locale.T("config_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "force", diff --git a/cmd/state/internal/cmdtree/cmdtree.go b/cmd/state/internal/cmdtree/cmdtree.go index 67821bfdfb..767d9f2641 100644 --- a/cmd/state/internal/cmdtree/cmdtree.go +++ b/cmd/state/internal/cmdtree/cmdtree.go @@ -183,6 +183,7 @@ func newStateCommand(globals *globalOptions, prime *primer.Values) *captain.Comm "", locale.T("state_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "locale", @@ -274,6 +275,7 @@ func (a *addCmdAs) deprecatedAlias(aliased *captain.Command, name string) { aliased.Title(), aliased.Description(), a.prime.Output(), + a.prime.Config(), aliased.Flags(), aliased.Arguments(), func(c *captain.Command, args []string) error { diff --git a/cmd/state/internal/cmdtree/deploy.go b/cmd/state/internal/cmdtree/deploy.go index 583e5c70e2..9d8b6928da 100644 --- a/cmd/state/internal/cmdtree/deploy.go +++ b/cmd/state/internal/cmdtree/deploy.go @@ -39,6 +39,7 @@ func newDeployCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_title", "Deploying Runtime"), locale.T("deploy_cmd_description"), prime.Output(), + prime.Config(), flags, []*captain.Argument{ { @@ -63,6 +64,7 @@ func newDeployInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_install_title", "Installing Runtime (Unconfigured)"), locale.T("deploy_install_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "path", @@ -108,6 +110,7 @@ func newDeployConfigureCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_configure_title", "Configuring Runtime For Your Shell"), locale.T("deploy_configure_cmd_description"), prime.Output(), + prime.Config(), flags, []*captain.Argument{ { @@ -132,6 +135,7 @@ func newDeploySymlinkCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_symlink_title", "Symlinking Executables"), locale.T("deploy_symlink_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "path", @@ -167,6 +171,7 @@ func newDeployReportCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_report_title", "Reporting Deployment Information"), locale.T("deploy_report_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/events.go b/cmd/state/internal/cmdtree/events.go index ef480f3747..af0e1061ca 100644 --- a/cmd/state/internal/cmdtree/events.go +++ b/cmd/state/internal/cmdtree/events.go @@ -15,6 +15,7 @@ func newEventsCommand(prime *primer.Values) *captain.Command { locale.Tl("events_title", "Listing Events"), locale.Tl("events_description", "Manage project events"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(cmd *captain.Command, args []string) error { @@ -31,6 +32,7 @@ func newEventsLogCommand(prime *primer.Values) *captain.Command { locale.Tl("events_log_title", "Showing Events Log"), locale.Tl("events_log_description", "View a log of events"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "follow", diff --git a/cmd/state/internal/cmdtree/export.go b/cmd/state/internal/cmdtree/export.go index acb2efb0dd..2baa51a448 100644 --- a/cmd/state/internal/cmdtree/export.go +++ b/cmd/state/internal/cmdtree/export.go @@ -19,6 +19,7 @@ func newExportCommand(prime *primer.Values) *captain.Command { locale.Tl("export_title", "Exporting Information"), locale.T("export_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -36,6 +37,7 @@ func newRecipeCommand(prime *primer.Values) *captain.Command { locale.Tl("export_recipe_title", "Exporting Recipe Data"), locale.T("export_recipe_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "pretty", @@ -71,6 +73,7 @@ func newJWTCommand(prime *primer.Values) *captain.Command { locale.Tl("export_jwt_title", "Exporting Credentials"), locale.T("export_jwt_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -88,6 +91,7 @@ func newPrivateKeyCommand(prime *primer.Values) *captain.Command { locale.Tl("export_privkey_title", "Exporting Private Key"), locale.T("export_privkey_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -104,6 +108,7 @@ func newAPIKeyCommand(prime *primer.Values) *captain.Command { locale.Tl("export_new_api_key_title", "Exporting New API Key"), locale.T("export_new_api_key_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -128,6 +133,7 @@ func newExportConfigCommand(prime *primer.Values) *captain.Command { locale.Tl("export_config_title", "Exporting Configuration Data"), locale.T("export_config_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "filter", @@ -153,6 +159,7 @@ func newExportGithubActionCommand(prime *primer.Values) *captain.Command { locale.Tl("export_ghactions_title", "Exporting Github Action Workflow"), locale.Tl("export_ghactions_description", "Create a github action workflow for your project"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/fork.go b/cmd/state/internal/cmdtree/fork.go index 8c7de4de57..a102ae66f8 100644 --- a/cmd/state/internal/cmdtree/fork.go +++ b/cmd/state/internal/cmdtree/fork.go @@ -16,6 +16,7 @@ func newForkCommand(prime *primer.Values) *captain.Command { locale.Tl("fork_title", "Forking Project"), locale.Tl("fork_description", "Fork an existing ActiveState Platform project"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "org", diff --git a/cmd/state/internal/cmdtree/history.go b/cmd/state/internal/cmdtree/history.go index 1a52df1e45..c0ac150c9d 100644 --- a/cmd/state/internal/cmdtree/history.go +++ b/cmd/state/internal/cmdtree/history.go @@ -20,6 +20,7 @@ func newHistoryCommand(prime *primer.Values) *captain.Command { locale.Tl("history_title", "Viewing Project History"), locale.T("history_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "namespace", diff --git a/cmd/state/internal/cmdtree/init.go b/cmd/state/internal/cmdtree/init.go index d1f4335a67..2365462e8a 100644 --- a/cmd/state/internal/cmdtree/init.go +++ b/cmd/state/internal/cmdtree/init.go @@ -20,6 +20,7 @@ func newInitCommand(prime *primer.Values) *captain.Command { locale.Tl("init_title", "Initializing Project"), locale.T("init_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/invite.go b/cmd/state/internal/cmdtree/invite.go index 22b0eae911..1156278d31 100644 --- a/cmd/state/internal/cmdtree/invite.go +++ b/cmd/state/internal/cmdtree/invite.go @@ -17,6 +17,7 @@ func newInviteCommand(prime *primer.Values) *captain.Command { locale.Tl("invite_title", "Inviting New Members"), locale.Tl("invite_description", "Invite new members to an organization"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "organization", diff --git a/cmd/state/internal/cmdtree/languages.go b/cmd/state/internal/cmdtree/languages.go index 36e5baca65..5e68aea833 100644 --- a/cmd/state/internal/cmdtree/languages.go +++ b/cmd/state/internal/cmdtree/languages.go @@ -15,6 +15,7 @@ func newLanguagesCommand(prime *primer.Values) *captain.Command { locale.Tl("languages_title", "Listing Languages"), locale.T("languages_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { @@ -33,6 +34,7 @@ func newLanguageInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("languages_install_title", "Installing Language"), locale.T("languages_install_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/organizations.go b/cmd/state/internal/cmdtree/organizations.go index ccff0588bb..e8918b1321 100644 --- a/cmd/state/internal/cmdtree/organizations.go +++ b/cmd/state/internal/cmdtree/organizations.go @@ -17,6 +17,7 @@ func newOrganizationsCommand(prime *primer.Values) *captain.Command { locale.Tl("organizations_title", "Listing Organizations"), locale.T("organizations_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/packages.go b/cmd/state/internal/cmdtree/packages.go index e81303a1d3..44316d64cc 100644 --- a/cmd/state/internal/cmdtree/packages.go +++ b/cmd/state/internal/cmdtree/packages.go @@ -18,6 +18,7 @@ func newPackagesCommand(prime *primer.Values) *captain.Command { locale.Tl("package_title", "Listing Packages"), locale.T("package_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "commit", @@ -57,6 +58,7 @@ func newInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("package_install_title", "Installing Package"), locale.T("package_install_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -82,6 +84,7 @@ func newUninstallCommand(prime *primer.Values) *captain.Command { locale.Tl("package_uninstall_title", "Uninstalling Package"), locale.T("package_uninstall_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -107,6 +110,7 @@ func newImportCommand(prime *primer.Values) *captain.Command { locale.Tl("package_import_title", "Importing Packages"), locale.T("package_import_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "force", @@ -138,6 +142,7 @@ func newSearchCommand(prime *primer.Values) *captain.Command { locale.Tl("package_search_title", "Searching Packages"), locale.T("package_search_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "language", @@ -174,6 +179,7 @@ func newInfoCommand(prime *primer.Values) *captain.Command { locale.Tl("package_info_title", "Displaying Package Information"), locale.T("package_info_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "language", diff --git a/cmd/state/internal/cmdtree/platforms.go b/cmd/state/internal/cmdtree/platforms.go index f224647ee0..13e34bb86d 100644 --- a/cmd/state/internal/cmdtree/platforms.go +++ b/cmd/state/internal/cmdtree/platforms.go @@ -18,6 +18,7 @@ func newPlatformsCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_title", "Listing Platforms"), locale.T("platforms_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(_ *captain.Command, _ []string) error { @@ -40,6 +41,7 @@ func newPlatformsSearchCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_search_title", "Searching Platforms"), locale.T("platforms_search_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(_ *captain.Command, _ []string) error { @@ -58,6 +60,7 @@ func newPlatformsAddCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_add_title", "Adding Platform"), locale.T("platforms_add_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: locale.T("flag_platforms_shared_bitwidth"), @@ -95,6 +98,7 @@ func newPlatformsRemoveCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_remove_title", "Removing Platform"), locale.T("platforms_remove_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: locale.T("flag_platforms_shared_bitwidth"), diff --git a/cmd/state/internal/cmdtree/prepare.go b/cmd/state/internal/cmdtree/prepare.go index 17690ed39d..557fea1bab 100644 --- a/cmd/state/internal/cmdtree/prepare.go +++ b/cmd/state/internal/cmdtree/prepare.go @@ -15,6 +15,7 @@ func newPrepareCommand(prime *primer.Values) *captain.Command { "", locale.Tl("prepare_description", "Prepare environment for use with the State Tool."), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(_ *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/projects.go b/cmd/state/internal/cmdtree/projects.go index c3c25d0826..34f28867bd 100644 --- a/cmd/state/internal/cmdtree/projects.go +++ b/cmd/state/internal/cmdtree/projects.go @@ -2,14 +2,13 @@ package cmdtree import ( "github.com/ActiveState/cli/internal/captain" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/primer" "github.com/ActiveState/cli/internal/runners/projects" ) func newProjectsCommand(prime *primer.Values) *captain.Command { - runner := projects.NewProjects(prime, config.Get()) + runner := projects.NewProjects(prime) params := projects.NewParams() return captain.NewCommand( @@ -17,6 +16,7 @@ func newProjectsCommand(prime *primer.Values) *captain.Command { locale.Tl("projects_title", "Listing Projects"), locale.T("projects_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -26,7 +26,7 @@ func newProjectsCommand(prime *primer.Values) *captain.Command { } func newRemoteProjectsCommand(prime *primer.Values) *captain.Command { - runner := projects.NewProjects(prime, config.Get()) + runner := projects.NewProjects(prime) params := projects.NewParams() return captain.NewCommand( @@ -34,6 +34,7 @@ func newRemoteProjectsCommand(prime *primer.Values) *captain.Command { locale.Tl("projects_remote_title", "Listing Remote Projects"), locale.Tl("projects_remote_description", "Manage all projects, including ones you have not checked out locally"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { diff --git a/cmd/state/internal/cmdtree/protocol.go b/cmd/state/internal/cmdtree/protocol.go index 129d1799b9..b860758d3c 100644 --- a/cmd/state/internal/cmdtree/protocol.go +++ b/cmd/state/internal/cmdtree/protocol.go @@ -16,6 +16,7 @@ func newProtocolCommand(prime *primer.Values) *captain.Command { "", locale.Tl("protocol_description", "Process URLs that use the state protocol"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/pull.go b/cmd/state/internal/cmdtree/pull.go index 75584db654..1acedeea54 100644 --- a/cmd/state/internal/cmdtree/pull.go +++ b/cmd/state/internal/cmdtree/pull.go @@ -17,6 +17,7 @@ func newPullCommand(prime *primer.Values) *captain.Command { locale.Tl("pull_title", "Pulling Remote Project"), locale.Tl("pull_description", "Pull in the latest version of your project from the ActiveState Platform"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "force", diff --git a/cmd/state/internal/cmdtree/push.go b/cmd/state/internal/cmdtree/push.go index 6febc3a77e..3c3ff44f03 100644 --- a/cmd/state/internal/cmdtree/push.go +++ b/cmd/state/internal/cmdtree/push.go @@ -2,7 +2,6 @@ package cmdtree import ( "github.com/ActiveState/cli/internal/captain" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/primer" "github.com/ActiveState/cli/internal/runners/push" @@ -10,7 +9,7 @@ import ( ) func newPushCommand(prime *primer.Values) *captain.Command { - pushRunner := push.NewPush(config.Get(), prime) + pushRunner := push.NewPush(prime) params := push.PushParams{ Namespace: &project.Namespaced{}, @@ -21,6 +20,7 @@ func newPushCommand(prime *primer.Values) *captain.Command { locale.Tl("push_title", "Pushing Local Project"), locale.T("push_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/revert.go b/cmd/state/internal/cmdtree/revert.go index a49192f643..570d22bbc6 100644 --- a/cmd/state/internal/cmdtree/revert.go +++ b/cmd/state/internal/cmdtree/revert.go @@ -16,6 +16,7 @@ func newRevertCommand(prime *primer.Values) *captain.Command { locale.Tl("revert_title", "Reverting Commit"), locale.Tl("revert_description", "Revert a commit"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/run.go b/cmd/state/internal/cmdtree/run.go index 3a45b0a628..17e20fd36f 100644 --- a/cmd/state/internal/cmdtree/run.go +++ b/cmd/state/internal/cmdtree/run.go @@ -17,6 +17,7 @@ func newRunCommand(prime *primer.Values) *captain.Command { "", locale.T("run_description"), prime.Output(), + prime.Config(), nil, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/scripts.go b/cmd/state/internal/cmdtree/scripts.go index 413639d99f..2849edf4b7 100644 --- a/cmd/state/internal/cmdtree/scripts.go +++ b/cmd/state/internal/cmdtree/scripts.go @@ -15,6 +15,7 @@ func newScriptsCommand(prime *primer.Values) *captain.Command { locale.Tl("scripts_title", "Listing Scripts"), locale.T("scripts_description"), prime.Output(), + prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -31,6 +32,7 @@ func newScriptsEditCommand(prime *primer.Values) *captain.Command { locale.Tl("scripts_edit_title", "Editing Script"), locale.T("edit_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "expand", diff --git a/cmd/state/internal/cmdtree/secrets.go b/cmd/state/internal/cmdtree/secrets.go index 807d068f19..a1ec80cf6d 100644 --- a/cmd/state/internal/cmdtree/secrets.go +++ b/cmd/state/internal/cmdtree/secrets.go @@ -20,6 +20,7 @@ func newSecretsCommand(secretsClient *secretsapi.Client, prime *primer.Values) * locale.Tl("secrets_title", "Listing Secrets"), locale.T("secrets_cmd_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "filter-usedby", @@ -54,6 +55,7 @@ func newSecretsGetCommand(prime *primer.Values) *captain.Command { locale.Tl("secrets_get_title", "Getting Secret"), locale.T("secrets_get_cmd_description"), prime.Output(), + prime.Config(), nil, []*captain.Argument{ { @@ -79,6 +81,7 @@ func newSecretsSetCommand(prime *primer.Values) *captain.Command { locale.Tl("secrets_set_title", "Setting Secret"), locale.T("secrets_set_cmd_description"), prime.Output(), + prime.Config(), nil, []*captain.Argument{ { @@ -108,6 +111,7 @@ func newSecretsSyncCommand(secretsClient *secretsapi.Client, prime *primer.Value locale.Tl("secrets_sync_title", "Synchronizing Secrets"), locale.T("secrets_sync_cmd_description"), prime.Output(), + prime.Config(), nil, nil, func(_ *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/shim.go b/cmd/state/internal/cmdtree/shim.go index c91b1a0cc3..fed5927677 100644 --- a/cmd/state/internal/cmdtree/shim.go +++ b/cmd/state/internal/cmdtree/shim.go @@ -19,6 +19,7 @@ func newShimCommand(prime *primer.Values, args ...string) *captain.Command { "", locale.T("shim_description"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/show.go b/cmd/state/internal/cmdtree/show.go index 458a6fc556..464ca65ed4 100644 --- a/cmd/state/internal/cmdtree/show.go +++ b/cmd/state/internal/cmdtree/show.go @@ -17,6 +17,7 @@ func newShowCommand(prime *primer.Values) *captain.Command { locale.Tl("show_title", "Showing Project Details"), locale.T("show_project"), prime.Output(), + prime.Config(), nil, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/tutorial.go b/cmd/state/internal/cmdtree/tutorial.go index d100c28c20..9359d73242 100644 --- a/cmd/state/internal/cmdtree/tutorial.go +++ b/cmd/state/internal/cmdtree/tutorial.go @@ -15,6 +15,7 @@ func newTutorialCommand(prime *primer.Values) *captain.Command { locale.Tl("tutorial_title", "Running Tutorial"), locale.Tl("tutorial_description", "Learn how to use the State Tool"), prime.Output(), + prime.Config(), nil, nil, func(ccmd *captain.Command, args []string) error { @@ -37,6 +38,7 @@ func newTutorialProjectCommand(prime *primer.Values) *captain.Command { locale.Tl("tutorial_new_project", `Running "New Project" Tutorial`), locale.Tl("tutorial_description", "Learn how to create new projects. (ie. virtual environments)"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "skip-intro", diff --git a/cmd/state/internal/cmdtree/update.go b/cmd/state/internal/cmdtree/update.go index b0e05c6356..31a13d0ada 100644 --- a/cmd/state/internal/cmdtree/update.go +++ b/cmd/state/internal/cmdtree/update.go @@ -17,6 +17,7 @@ func newUpdateCommand(prime *primer.Values) *captain.Command { locale.Tl("update_title", "Updating The State Tool"), locale.Tl("update_description", "Updates the State Tool to the latest available version"), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "set-channel", @@ -43,6 +44,7 @@ func newUpdateLockCommand(prime *primer.Values) *captain.Command { locale.Tl("lock_title", "Lock the State Tool version"), locale.Tl("lock_description", "Lock the State Tool at the current version, this disables automatic updates."), prime.Output(), + prime.Config(), []*captain.Flag{ { Name: "set-channel", diff --git a/cmd/state/main.go b/cmd/state/main.go index aca65b6ff1..2f148f911d 100644 --- a/cmd/state/main.go +++ b/cmd/state/main.go @@ -100,7 +100,10 @@ func run(args []string, isInteractive bool, out output.Outputer) (int, error) { verbose := os.Getenv("VERBOSE") != "" || argsHaveVerbose(args) logging.CurrentHandler().SetVerbose(verbose) - cfg := config.Get() + cfg, err := config.Get() + if err != nil { + return 1, locale.WrapError(err, "config_get_error", "Failed to load configuration.") + } logging.Debug("ConfigPath: %s", cfg.ConfigPath()) logging.Debug("CachePath: %s", cfg.CachePath()) @@ -131,7 +134,7 @@ func run(args []string, isInteractive bool, out output.Outputer) (int, error) { } // Forward call to specific state tool version, if warranted - forward, err := forwardFn(args, out, pj) + forward, err := forwardFn(cfg.ConfigPath(), args, out, pj) if err != nil { return 1, err } @@ -156,7 +159,7 @@ func run(args []string, isInteractive bool, out output.Outputer) (int, error) { project.RegisterExpander("secrets", project.NewSecretPromptingExpander(secretsapi.Get(), prompter)) // Run the actual command - cmds := cmdtree.New(primer.New(pj, out, auth, prompter, sshell, conditional), args...) + cmds := cmdtree.New(primer.New(pj, out, auth, prompter, sshell, conditional, cfg), args...) childCmd, err := cmds.Command().Find(args[1:]) if err != nil { diff --git a/internal/analytics/analytics.go b/internal/analytics/analytics.go index aa17e534ce..126abeb4ad 100644 --- a/internal/analytics/analytics.go +++ b/internal/analytics/analytics.go @@ -150,13 +150,19 @@ func setup() { logging.SendToRollbarWhenReady("warning", fmt.Sprintf("Cannot detect the OS version: %v", err)) } + installSource := "unknown-due-to-config-error" + cfg, err := config.Get() + if err != nil { + installSource = cfg.InstallSource() + } + CustomDimensions = &customDimensions{ version: constants.Version, branchName: constants.BranchName, userID: userIDString, osName: osName, osVersion: osVersion, - installSource: config.Get().InstallSource(), + installSource: installSource, machineID: machineid.UniqID(), output: string(output.PlainFormatName), } @@ -202,11 +208,15 @@ func sendEventAndLog(category, action, label string, dimensions map[string]strin func sendEvent(category, action, label string, dimensions map[string]string) error { if deferAnalytics { - if err := deferEvent(category, action, label, dimensions); err != nil { + // TODO: figure out a way to pass configuration + cfg, err := config.Get() + if err != nil { + return locale.WrapError(err, "config_get_error") + } + if err := deferEvent(cfg, category, action, label, dimensions); err != nil { return locale.WrapError(err, "err_analytics_defer", "Could not defer event") } - // TODO: figure out a way to pass configuration - if err := config.Get().Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 + if err := cfg.Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 return locale.WrapError(err, "err_viper_write_defer", "Could not save configuration on defer") } } diff --git a/internal/analytics/deferred.go b/internal/analytics/deferred.go index 990a318f23..7545e4b05b 100644 --- a/internal/analytics/deferred.go +++ b/internal/analytics/deferred.go @@ -3,7 +3,6 @@ package analytics import ( "encoding/json" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/logging" @@ -20,7 +19,7 @@ type deferredData struct { const deferredCfgKey = "deferrer_analytics" -func SetDeferred(da bool) { +func SetDeferred(cfg Configurable, da bool) { deferAnalytics = da if deferAnalytics { return @@ -28,28 +27,34 @@ func SetDeferred(da bool) { eventWaitGroup.Add(1) go func() { defer eventWaitGroup.Done() - if err := sendDeferred(sendEvent); err != nil { + if err := sendDeferred(cfg, sendEvent); err != nil { logging.Errorf("Could not send deferred events: %v", err) } }() } -func deferEvent(category, action, label string, dimensions map[string]string) error { +type Configurable interface { + Set(string, interface{}) + Save() error + GetString(string) string +} + +func deferEvent(cfg Configurable, category, action, label string, dimensions map[string]string) error { logging.Debug("Deferring: %s, %s, %s", category, action, label) - deferred, err := loadDeferred() + deferred, err := loadDeferred(cfg) if err != nil { return errs.Wrap(err, "Could not load events on defer") } deferred = append(deferred, deferredData{category, action, label, dimensions}) - if err := saveDeferred(deferred); err != nil { + if err := saveDeferred(cfg, deferred); err != nil { return errs.Wrap(err, "Could not save event on defer") } return nil } -func sendDeferred(sender func(string, string, string, map[string]string) error) error { - deferred, err := loadDeferred() +func sendDeferred(cfg Configurable, sender func(string, string, string, map[string]string) error) error { + deferred, err := loadDeferred(cfg) if err != nil { return errs.Wrap(err, "Could not load events on send") } @@ -57,27 +62,27 @@ func sendDeferred(sender func(string, string, string, map[string]string) error) if err := sender(event.Category, event.Action, event.Label, event.Dimensions); err != nil { return errs.Wrap(err, "Could not send deferred event") } - if err := saveDeferred(deferred[n+1:]); err != nil { + if err := saveDeferred(cfg, deferred[n+1:]); err != nil { return errs.Wrap(err, "Could not save deferred event on send") } } - if err := config.Get().Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 + if err := cfg.Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 return locale.WrapError(err, "err_viper_write_send_defer", "Could not save configuration on send deferred") } return nil } -func saveDeferred(v []deferredData) error { +func saveDeferred(cfg Configurable, v []deferredData) error { s, err := json.Marshal(v) if err != nil { return errs.New("Could not serialize deferred analytics: %v, error: %v", v, err) } - config.Get().Set(deferredCfgKey, string(s)) + cfg.Set(deferredCfgKey, string(s)) return nil } -func loadDeferred() ([]deferredData, error) { - v := config.Get().GetString(deferredCfgKey) +func loadDeferred(cfg Configurable) ([]deferredData, error) { + v := cfg.GetString(deferredCfgKey) d := []deferredData{} if v != "" { err := json.Unmarshal([]byte(v), &d) diff --git a/internal/captain/command.go b/internal/captain/command.go index 01ac8f9be3..623f582264 100644 --- a/internal/captain/command.go +++ b/internal/captain/command.go @@ -75,9 +75,10 @@ type Command struct { skipChecks bool out output.Outputer + cfg analytics.Configurable } -func NewCommand(name, title, description string, out output.Outputer, flags []*Flag, args []*Argument, execute ExecuteFunc) *Command { +func NewCommand(name, title, description string, out output.Outputer, cfg analytics.Configurable, flags []*Flag, args []*Argument, execute ExecuteFunc) *Command { // Validate args for idx, arg := range args { if idx > 0 && arg.Required && !args[idx-1].Required { @@ -96,6 +97,7 @@ func NewCommand(name, title, description string, out output.Outputer, flags []*F flags: flags, commands: make([]*Command, 0), out: out, + cfg: cfg, } short := description @@ -399,7 +401,7 @@ func (c *Command) subCommandNames() []string { } func (c *Command) runner(cobraCmd *cobra.Command, args []string) error { - analytics.SetDeferred(c.deferAnalytics) + analytics.SetDeferred(c.cfg, c.deferAnalytics) outputFlag := cobraCmd.Flag("output") if outputFlag != nil && outputFlag.Changed { diff --git a/internal/config/instance.go b/internal/config/instance.go index aac763ade7..791d0f5933 100644 --- a/internal/config/instance.go +++ b/internal/config/instance.go @@ -13,11 +13,10 @@ import ( "github.com/google/uuid" "github.com/shibukawa/configdir" "github.com/spf13/viper" - "github.com/thoas/go-funk" "github.com/ActiveState/cli/internal/condition" C "github.com/ActiveState/cli/internal/constants" - "github.com/ActiveState/cli/internal/osutils/stacktrace" + "github.com/ActiveState/cli/internal/errs" ) var defaultConfig *Instance @@ -30,27 +29,39 @@ type Instance struct { localPath string installSource string noSave bool - Exit func(code int) } -func new(localPath string) *Instance { +func new(localPath string) (*Instance, error) { instance := &Instance{ viper: viper.New(), localPath: localPath, - Exit: os.Exit, } - instance.Reload() + err := instance.Reload() + if err != nil { + return instance, errs.Wrap(err, "Failed to load configuration.") + } - return instance + return instance, nil } // Reload reloads the configuration data from the config file -func (i *Instance) Reload() { - i.ensureConfigExists() - i.ensureCacheExists() - i.ReadInConfig() +func (i *Instance) Reload() error { + err := i.ensureConfigExists() + if err != nil { + return err + } + err = i.ensureCacheExists() + if err != nil { + return err + } + err = i.ReadInConfig() + if err != nil { + return err + } i.readInstallSource() + + return nil } func configPathInTest() (string, error) { @@ -66,7 +77,7 @@ func configPathInTest() (string, error) { } // New creates a new config instance -func New() *Instance { +func New() (*Instance, error) { localPath := os.Getenv(C.ConfigEnvVarName) if condition.InTest() { @@ -82,16 +93,20 @@ func New() *Instance { } // NewWithDir creates a new instance at the given directory -func NewWithDir(dir string) *Instance { +func NewWithDir(dir string) (*Instance, error) { return new(dir) } // Get returns the default configuration instance -func Get() *Instance { +func Get() (*Instance, error) { if defaultConfig == nil { - defaultConfig = New() + var err error + defaultConfig, err = New() + if err != nil { + return defaultConfig, err + } } - return defaultConfig + return defaultConfig, nil } // Set sets a value at the given key @@ -179,7 +194,7 @@ func (i *Instance) InstallSource() string { } // ReadInConfig reads in config from the config file -func (i *Instance) ReadInConfig() { +func (i *Instance) ReadInConfig() error { // Prepare viper, which is a library that automates configuration // management between files, env vars and the CLI i.viper.SetConfigName(i.Name()) @@ -188,8 +203,9 @@ func (i *Instance) ReadInConfig() { i.viper.AddConfigPath(".") if err := i.viper.ReadInConfig(); err != nil { - i.exit("Can't read config: %s", err) + return errs.Wrap(err, "Cannot read config.") } + return nil } // Save saves the config file @@ -210,7 +226,7 @@ func (i *Instance) SkipSave(b bool) { i.noSave = b } -func (i *Instance) ensureConfigExists() { +func (i *Instance) ensureConfigExists() error { // Prepare our config dir, eg. ~/.config/activestate/cli configDirs := configdir.New(i.Namespace(), i.AppName()) @@ -225,7 +241,7 @@ func (i *Instance) ensureConfigExists() { i.localPath, err = ioutil.TempDir("", "cli-config-test") } if err != nil { - i.exit("Cannot establish a config directory, HOME environment variable is not set and fallbacks have failed") + return errs.Wrap(err, "Cannot establish a config directory, HOME environment variable is not set and fallbacks have failed") } } @@ -239,17 +255,18 @@ func (i *Instance) ensureConfigExists() { if !i.configDir.Exists(i.Filename()) { configFile, err := i.configDir.Create(i.Filename()) if err != nil { - i.exit("Can't create config: %s", err) + return errs.Wrap(err, "Cannot create config") } err = configFile.Close() if err != nil { - i.exit("Can't close config file: %s", err) + return errs.Wrap(err, "Cannot close config file") } } + return nil } -func (i *Instance) ensureCacheExists() { +func (i *Instance) ensureCacheExists() error { // When running tests we use a unique cache dir that's located in a temp folder, to avoid collisions if condition.InTest() { path, err := tempDir("state-cache-tests") @@ -269,16 +286,9 @@ func (i *Instance) ensureCacheExists() { i.cacheDir = configdir.New(i.Namespace(), "").QueryCacheFolder() } if err := i.cacheDir.MkdirAll(); err != nil { - i.exit("Can't create cache directory: %s", err) - } -} - -func (i *Instance) exit(message string, a ...interface{}) { - fmt.Fprintf(os.Stderr, message, a...) - if funk.Contains(os.Args, "-v") || condition.InTest() { - fmt.Fprint(os.Stderr, stacktrace.Get().String()) + return errs.Wrap(err, "Cannot create cache directory") } - i.Exit(1) + return nil } // tempDir returns a temp directory path at the topmost directory possible diff --git a/internal/deprecation/deprecation.go b/internal/deprecation/deprecation.go index 095a78e6d4..94e3594da9 100644 --- a/internal/deprecation/deprecation.go +++ b/internal/deprecation/deprecation.go @@ -50,6 +50,7 @@ type Checker struct { } type configable interface { + ConfigPath() string GetTime(key string) time.Time Set(key string, value interface{}) } @@ -59,7 +60,7 @@ func NewChecker(timeout time.Duration, configuration configable) *Checker { return &Checker{ timeout, configuration, - filepath.Join(config.Get().ConfigPath(), "deprecation.json"), + filepath.Join(configuration.ConfigPath(), "deprecation.json"), } } @@ -70,7 +71,11 @@ func Check() (*Info, error) { // CheckVersionNumber will run a Checker.Check with defaults func CheckVersionNumber(versionNumber string) (*Info, error) { - checker := NewChecker(DefaultTimeout, config.Get()) + cfg, err := config.Get() + if err != nil { + return nil, errs.Wrap(err, "Could not load configuration required to check version number") + } + checker := NewChecker(DefaultTimeout, cfg) return checker.check(versionNumber) } diff --git a/internal/events/cmdcall/cmdcall.go b/internal/events/cmdcall/cmdcall.go index 2eae2fb81e..7d5a90c860 100644 --- a/internal/events/cmdcall/cmdcall.go +++ b/internal/events/cmdcall/cmdcall.go @@ -16,6 +16,7 @@ type primeable interface { primer.Outputer primer.Projecter primer.Subsheller + primer.Configurer } // CmdCall manages dependencies for the handling of events triggered by command @@ -37,7 +38,7 @@ func New(p primeable, cmdList string) *CmdCall { subshell: p.Subshell(), cmdList: cmdList, p: p, - scriptrun: scriptrun.New(p.Output(), p.Subshell(), p.Project()), + scriptrun: scriptrun.New(p.Output(), p.Subshell(), p.Project(), p.Config()), } } diff --git a/internal/globaldefault/default.go b/internal/globaldefault/default.go index 1237f201d4..9d701c0954 100644 --- a/internal/globaldefault/default.go +++ b/internal/globaldefault/default.go @@ -11,7 +11,6 @@ import ( "github.com/gobuffalo/packr" "github.com/thoas/go-funk" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/exeutils" @@ -30,13 +29,14 @@ import ( const shimDenoter = "!DO NOT EDIT! State Tool Shim !DO NOT EDIT!" type DefaultConfigurer interface { - Set(key string, value interface{}) + sscommon.Configurable Save() error + CachePath() string } // BinDir returns the global binary directory -func BinDir() string { - return filepath.Join(config.Get().CachePath(), "bin") +func BinDir(cfg DefaultConfigurer) string { + return filepath.Join(cfg.CachePath(), "bin") } func isBinDirOnWindowsUserPath(binDir string) bool { @@ -57,9 +57,9 @@ func isBinDirOnWindowsUserPath(binDir string) bool { ) } -func Prepare(subshell subshell.SubShell) error { +func Prepare(cfg DefaultConfigurer, subshell subshell.SubShell) error { logging.Debug("Preparing globaldefault") - binDir := BinDir() + binDir := BinDir(cfg) // Don't run prepare if we're already on PATH path := strings.Split(os.Getenv("PATH"), string(os.PathListSeparator)) @@ -90,7 +90,7 @@ func Prepare(subshell subshell.SubShell) error { "PATH": binDir, } - if err := subshell.WriteUserEnv(envUpdates, sscommon.Default, true); err != nil { + if err := subshell.WriteUserEnv(cfg, envUpdates, sscommon.Default, true); err != nil { return locale.WrapError(err, "err_globaldefault_update_env", "Could not write to user environment.") } @@ -125,7 +125,7 @@ func WarningForAdministrator(out output.Outputer) { // SetupDefaultActivation sets symlinks in the global bin directory to the currently activated runtime func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, runtime *runtime.Runtime, projectPath string) error { logging.Debug("Setting up globaldefault") - if err := Prepare(subshell); err != nil { + if err := Prepare(cfg, subshell); err != nil { return locale.WrapError(err, "err_globaldefault_prepare", "Could not prepare environment.") } @@ -140,7 +140,7 @@ func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, r } // roll back old symlinks - if err := cleanup(); err != nil { + if err := cleanup(cfg); err != nil { return locale.WrapError(err, "err_rollback_shim", "Could not clean up previous default installation.") } @@ -161,7 +161,7 @@ func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, r return locale.WrapError(err, "err_unique_exes", "Could not detect unique executables, make sure your PATH and PATHEXT environment variables are properly configured.") } - if err := createShims(exes, projectPath); err != nil { + if err := createShims(exes, projectPath, cfg); err != nil { return locale.WrapError(err, "err_createshims", "Could not create shim files to set up the default runtime environment.") } @@ -170,8 +170,8 @@ func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, r return nil } -func cleanup() error { - binDir := BinDir() +func cleanup(cfg DefaultConfigurer) error { + binDir := BinDir(cfg) if err := fileutils.MkdirUnlessExists(binDir); err != nil { return locale.WrapError(err, "err_globaldefault_mkdir", "Could not create bin directory: {{.V0}}.", binDir) } @@ -197,9 +197,9 @@ func cleanup() error { return nil } -func createShims(exePaths []string, projectPath string) error { +func createShims(exePaths []string, projectPath string, cfg DefaultConfigurer) error { for _, exePath := range exePaths { - if err := createShim(exePath, projectPath); err != nil { + if err := createShim(exePath, projectPath, cfg); err != nil { return locale.WrapError(err, "err_createshim", "Could not create shim for {{.V0}}.", exePath) } } @@ -207,8 +207,8 @@ func createShims(exePaths []string, projectPath string) error { return nil } -func createShim(exePath, projectPath string) error { - target := filepath.Clean(filepath.Join(BinDir(), filepath.Base(exePath))) +func createShim(exePath, projectPath string, cfg DefaultConfigurer) error { + target := filepath.Clean(filepath.Join(BinDir(cfg), filepath.Base(exePath))) if rt.GOOS == "windows" { oldExt := filepath.Ext(target) target = target[0:len(target)-len(oldExt)] + ".bat" diff --git a/internal/keypairs/local.go b/internal/keypairs/local.go index 2e31699a49..f03f7d5494 100644 --- a/internal/keypairs/local.go +++ b/internal/keypairs/local.go @@ -19,7 +19,10 @@ import ( // the user's file system; specifically from the config dir. It is assumed that // this keypair file has no passphrase, even if it is encrypted. func Load(keyName string) (Keypair, error) { - keyFilename := LocalKeyFilename(keyName) + keyFilename, err := LocalKeyFilename(keyName) + if err != nil { + return nil, errs.Wrap(err, "Failed to get key file name to load.") + } if err := validateKeyFile(keyFilename); err != nil { return nil, err } @@ -29,7 +32,11 @@ func Load(keyName string) (Keypair, error) { // Save will save the unencrypted and encoded private key to a local config // file. The filename will be the value of `keyName` and suffixed with `.key`. func Save(kp Keypair, keyName string) error { - err := ioutil.WriteFile(LocalKeyFilename(keyName), []byte(kp.EncodePrivateKey()), 0600) + keyFileName, err := LocalKeyFilename(keyName) + if err != nil { + return errs.Wrap(err, "Failed to get key file name to save.") + } + err = ioutil.WriteFile(keyFileName, []byte(kp.EncodePrivateKey()), 0600) if err != nil { return errs.Wrap(err, "WriteFile failed") } @@ -39,7 +46,10 @@ func Save(kp Keypair, keyName string) error { // Delete will delete an unencrypted and encoded private key from the local // config directory. The base filename (sans suffix) must be provided. func Delete(keyName string) error { - filename := LocalKeyFilename(keyName) + filename, err := LocalKeyFilename(keyName) + if err != nil { + return errs.Wrap(err, "Failed to get key file name to delete.") + } if fileutils.FileExists(filename) { if err := os.Remove(filename); err != nil { return errs.Wrap(err, "os.Remove %s failed", filename) @@ -92,8 +102,12 @@ func DeleteWithDefaults() error { } // LocalKeyFilename returns the full filepath for the given key name -func LocalKeyFilename(keyName string) string { - return filepath.Join(config.Get().ConfigPath(), keyName+".key") +func LocalKeyFilename(keyName string) (string, error) { + cfg, err := config.Get() + if err != nil { + return "", locale.WrapError(err, "config_get_err") + } + return filepath.Join(cfg.ConfigPath(), keyName+".key"), nil } func loadAndParseKeypair(keyFilename string) (Keypair, error) { diff --git a/internal/locale/locale.go b/internal/locale/locale.go index 30bf15e6a2..2a2b275e43 100644 --- a/internal/locale/locale.go +++ b/internal/locale/locale.go @@ -18,6 +18,7 @@ import ( "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/environment" + "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/logging" ) @@ -32,7 +33,14 @@ var exit = os.Exit func init() { logging.Debug("Init") - config.Get().SetDefault("Locale", "en-US") + locale := getLocaleFlag() + cfg, err := config.Get() + if err == nil { + cfg.SetDefault("Locale", "en-US") + if locale == "" { + locale = cfg.GetString("Locale") + } + } path := getLocalePath() box := packr.NewBox("../../locale") @@ -46,11 +54,6 @@ func init() { } }) - locale := getLocaleFlag() - if locale == "" { - locale = config.Get().GetString("Locale") - } - Set(locale) } @@ -88,17 +91,21 @@ func getLocaleFlag() string { } // Set the active language to the given locale -func Set(localeName string) { +func Set(localeName string) error { if !funk.Contains(Supported, localeName) { - fmt.Printf("Locale does not exist: %s\n", localeName) - exit(1) - return + return errs.New("Locale does not exist: %s", localeName) } translateFunction, _ = i18n.Tfunc(localeName) _ = translateFunction - config.Get().Set("Locale", localeName) + cfg, err := config.Get() + if err != nil { + return errs.Wrap(err, "Could not get configuration to store updated locale") + } + cfg.Set("Locale", localeName) + + return nil } // T aliases to i18n.Tfunc() diff --git a/internal/logging/defaults.go b/internal/logging/defaults.go index e023e4fe9f..d4aaaa375c 100644 --- a/internal/logging/defaults.go +++ b/internal/logging/defaults.go @@ -19,6 +19,9 @@ import ( "github.com/ActiveState/cli/internal/rtutils" ) +// datadir is the base directory at which the log is saved +var datadir string + // Logger describes a logging function, like Debug, Error, Warning, etc. type Logger func(msg string, args ...interface{}) @@ -66,17 +69,16 @@ func FileNameFor(pid int) string { } func FilePath() string { - return filepath.Join(config.Get().ConfigPath(), FileName()) + return filepath.Join(datadir, FileName()) } func FilePathFor(filename string) string { - return filepath.Join(config.Get().ConfigPath(), filename) + return filepath.Join(datadir, filename) } const FileNameSuffix = ".log" func (l *fileHandler) Emit(ctx *MessageContext, message string, args ...interface{}) error { - datadir := config.Get().ConfigPath() filename := filepath.Join(datadir, FileName()) // only log to rollbar when on release, beta or unstable branch and when built via CI (ie., non-local build) @@ -132,8 +134,17 @@ func init() { handler := &fileHandler{DefaultFormatter, nil, safeBool{}} SetHandler(handler) + cfg, err := config.Get() + if err != nil { + Error("Could not load configuration: %v", err) + } + if cfg == nil { + Error("Could not proceed setting up logging due to missing configuration.") + return + } + // Clean up old log files - datadir := config.Get().ConfigPath() + datadir = cfg.ConfigPath() files, err := ioutil.ReadDir(datadir) if err != nil { Error("Could not scan config dir to clean up stale logs: %v", err) diff --git a/internal/logging/rollbar.go b/internal/logging/rollbar.go index c1467a0e22..864ef5da04 100644 --- a/internal/logging/rollbar.go +++ b/internal/logging/rollbar.go @@ -47,8 +47,16 @@ func SetupRollbar() { data["platform_os"] = runtime.GOOS }) + cfg, err := config.Get() + var installSource string + if err != nil { + // we will not log this to prevent recursion + installSource = "config-error" + } else { + installSource = cfg.InstallSource() + } rollbar.SetCustom(map[string]interface{}{ - "install_source": config.Get().InstallSource(), + "install_source": installSource, }) log.SetOutput(CurrentHandler().Output()) diff --git a/internal/machineid/machineid.go b/internal/machineid/machineid.go index e7368276d4..eca7644268 100644 --- a/internal/machineid/machineid.go +++ b/internal/machineid/machineid.go @@ -17,12 +17,18 @@ func uniqID(machineIDGetter func() (string, error), uuidGetter func() string) st return machID } - machineID := config.Get().GetString("machineID") + cfg, err := config.Get() + if err != nil { + // We do not log here, as it may create a recursion + return "11111111-1111-1111-1111-111111111111" + } + + machineID := cfg.GetString("machineID") if machineID != "" { return machineID } machineID = uuidGetter() - config.Get().Set("machineID", machineID) + cfg.Set("machineID", machineID) return machineID } diff --git a/internal/primer/primer.go b/internal/primer/primer.go index 87c5712bf6..3b911cf881 100644 --- a/internal/primer/primer.go +++ b/internal/primer/primer.go @@ -1,6 +1,7 @@ package primer import ( + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constraints" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/prompt" @@ -18,15 +19,17 @@ type Values struct { prompt prompt.Prompter subshell subshell.SubShell conditional *constraints.Conditional + config *config.Instance } -func New(project *project.Project, output output.Outputer, auth *authentication.Auth, prompt prompt.Prompter, subshell subshell.SubShell, conditional *constraints.Conditional) *Values { +func New(project *project.Project, output output.Outputer, auth *authentication.Auth, prompt prompt.Prompter, subshell subshell.SubShell, conditional *constraints.Conditional, config *config.Instance) *Values { v := &Values{ output: output, auth: auth, prompt: prompt, subshell: subshell, conditional: conditional, + config: config, } if project != nil { v.project = project @@ -55,6 +58,10 @@ type Prompter interface { Prompt() prompt.Prompter } +type Configurer interface { + Config() *config.Instance +} + type Subsheller interface { Subshell() subshell.SubShell } @@ -90,3 +97,7 @@ func (v *Values) Subshell() subshell.SubShell { func (v *Values) Conditional() *constraints.Conditional { return v.conditional } + +func (v *Values) Config() *config.Instance { + return v.config +} diff --git a/internal/process/process.go b/internal/process/process.go index 03349a1c3e..75839253fb 100644 --- a/internal/process/process.go +++ b/internal/process/process.go @@ -8,7 +8,6 @@ import ( "github.com/shirou/gopsutil/process" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" @@ -16,15 +15,19 @@ import ( "github.com/ActiveState/cli/internal/osutils" ) +type Configurable interface { + ConfigPath() string +} + // ActivationPID returns the process ID of the activated state; if any -func ActivationPID() int32 { +func ActivationPID(cfg Configurable) int32 { pid := int32(os.Getpid()) ppid := int32(os.Getppid()) procInfoErrMsgFmt := "Could not detect process information: %v" for pid != 0 && pid != ppid { - pidFileName := ActivationPIDFileName(int(pid)) + pidFileName := ActivationPIDFileName(cfg.ConfigPath(), int(pid)) if fileutils.FileExists(pidFileName) { return pid } @@ -71,9 +74,9 @@ func isActivateCmdlineArgs(args []string) bool { // ActivationPIDFileName returns a consistent file path based on the given // process id. -func ActivationPIDFileName(n int) string { +func ActivationPIDFileName(configpath string, n int) string { fileName := fmt.Sprintf("activation.%d", n) - return filepath.Join(config.Get().ConfigPath(), fileName) + return filepath.Join(configpath, fileName) } // Activation eases the use of a PidLock for the purpose of "marking" a process @@ -83,8 +86,8 @@ type Activation struct { } // NewActivation creates an instance of Activation. -func NewActivation(pid int) (*Activation, error) { - pidFileName := ActivationPIDFileName(pid) +func NewActivation(cfg Configurable, pid int) (*Activation, error) { + pidFileName := ActivationPIDFileName(cfg.ConfigPath(), pid) pidLock, err := osutils.NewPidLock(pidFileName) if err != nil { return nil, errs.Wrap(err, "cannot create new pid lock file") @@ -113,6 +116,6 @@ func (a *Activation) Close() error { // IsActivated returns whether or not this process is being run in an activated // state. This can be this specific process, or one of it's parents. -func IsActivated() bool { - return ActivationPID() != -1 +func IsActivated(cfg Configurable) bool { + return ActivationPID(cfg) != -1 } diff --git a/internal/runners/activate/activate.go b/internal/runners/activate/activate.go index dbfaa1b03a..ffa459511a 100644 --- a/internal/runners/activate/activate.go +++ b/internal/runners/activate/activate.go @@ -5,7 +5,6 @@ import ( "path/filepath" "github.com/ActiveState/cli/internal/analytics" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/globaldefault" @@ -31,7 +30,7 @@ type Activate struct { namespaceSelect *NamespaceSelect activateCheckout *Checkout out output.Outputer - config configAble + config configurable proj *project.Project subshell subshell.SubShell prompt prompt.Prompter @@ -50,14 +49,15 @@ type primeable interface { primer.Projecter primer.Subsheller primer.Prompter + primer.Configurer } func NewActivate(prime primeable) *Activate { return &Activate{ - NewNamespaceSelect(config.Get(), prime), + NewNamespaceSelect(prime.Config(), prime), NewCheckout(git.NewRepo(), prime), prime.Output(), - config.Get(), + prime.Config(), prime.Project(), prime.Subshell(), prime.Prompt(), @@ -73,7 +73,7 @@ func (r *Activate) run(params *ActivateParams) error { r.out.Notice(txtstyle.NewTitle(locale.T("info_activating_state"))) - alreadyActivated := process.IsActivated() + alreadyActivated := process.IsActivated(r.config) if alreadyActivated { if !params.Default { err := locale.NewInputError("err_already_activated", diff --git a/internal/runners/activate/activation.go b/internal/runners/activate/activation.go index 34166d1616..ccb30b5bb6 100644 --- a/internal/runners/activate/activation.go +++ b/internal/runners/activate/activation.go @@ -57,11 +57,11 @@ func (r *Activate) activateAndWait(proj *project.Project, venv *virtualenvironme } r.subshell.SetEnv(ve) - if err := r.subshell.Activate(r.out); err != nil { + if err := r.subshell.Activate(r.config, r.out); err != nil { return locale.WrapError(err, "error_could_not_activate_subshell", "Could not activate a new subshell.") } - a, err := process.NewActivation(os.Getpid()) + a, err := process.NewActivation(r.config, os.Getpid()) if err != nil { return locale.WrapError(err, "error_could_not_mark_process", "Could not mark process as activated.") } diff --git a/internal/runners/activate/namespace.go b/internal/runners/activate/namespace.go index 48fead2735..350cf8bd84 100644 --- a/internal/runners/activate/namespace.go +++ b/internal/runners/activate/namespace.go @@ -18,23 +18,26 @@ import ( "github.com/ActiveState/cli/internal/locale" ) -type configAble interface { - Set(key string, value interface{}) - GetBool(key string) bool +type configurable interface { + Set(string, interface{}) + GetBool(string) bool + GetStringMap(string) map[string]interface{} + Save() error + CachePath() string + ConfigPath() string GetString(key string) string - GetStringMapStringSlice(key string) map[string][]string GetStringSlice(key string) []string + GetStringMapStringSlice(key string) map[string][]string AllKeys() []string - Save() error } // NamespaceSelect will select the right directory associated with a namespace, and chdir into it type NamespaceSelect struct { - config configAble + config configurable prompter prompt.Prompter } -func NewNamespaceSelect(config configAble, prime primeable) *NamespaceSelect { +func NewNamespaceSelect(config configurable, prime primeable) *NamespaceSelect { return &NamespaceSelect{config, prime.Prompt()} } diff --git a/internal/runners/clean/cache.go b/internal/runners/clean/cache.go index accbb0c89b..c81f5fd8da 100644 --- a/internal/runners/clean/cache.go +++ b/internal/runners/clean/cache.go @@ -19,6 +19,7 @@ type Cache struct { config project.ConfigAble confirm confirmAble path string + cfg *config.Instance } type CacheParams struct { @@ -27,15 +28,15 @@ type CacheParams struct { } func NewCache(prime primeable) *Cache { - return newCache(prime.Output(), config.Get(), prime.Prompt()) + return newCache(prime.Output(), prime.Config(), prime.Prompt()) } -func newCache(output output.Outputer, cfg project.ConfigAble, confirm confirmAble) *Cache { +func newCache(output output.Outputer, cfg *config.Instance, confirm confirmAble) *Cache { return &Cache{ output: output, config: cfg, confirm: confirm, - path: config.Get().CachePath(), + path: cfg.CachePath(), } } diff --git a/internal/runners/clean/config.go b/internal/runners/clean/config.go index cca272d9fc..d74d2d38a1 100644 --- a/internal/runners/clean/config.go +++ b/internal/runners/clean/config.go @@ -4,17 +4,22 @@ import ( "errors" "os" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/logging" "github.com/ActiveState/cli/internal/output" ) +type configurable interface { + ConfigPath() string + CachePath() string + SkipSave(bool) +} + type Config struct { output output.Outputer confirm confirmAble - path string + cfg configurable } type ConfigParams struct { @@ -22,14 +27,14 @@ type ConfigParams struct { } func NewConfig(prime primeable) *Config { - return newConfig(prime.Output(), prime.Prompt()) + return newConfig(prime.Output(), prime.Prompt(), prime.Config()) } -func newConfig(out output.Outputer, confirm confirmAble) *Config { +func newConfig(out output.Outputer, confirm confirmAble, cfg configurable) *Config { return &Config{ output: out, confirm: confirm, - path: config.Get().ConfigPath(), + cfg: cfg, } } @@ -48,6 +53,6 @@ func (c *Config) Run(params *ConfigParams) error { } } - logging.Debug("Removing config directory: %s", c.path) - return removeConfig(c.path) + logging.Debug("Removing config directory: %s", c.cfg.ConfigPath()) + return removeConfig(c.cfg) } diff --git a/internal/runners/clean/run.go b/internal/runners/clean/run.go index eaefc4963e..f617e6d8f6 100644 --- a/internal/runners/clean/run.go +++ b/internal/runners/clean/run.go @@ -7,7 +7,7 @@ import ( ) func (u *Uninstall) runUninstall() error { - err := removeCache(u.cachePath) + err := removeCache(u.cfg.ConfigPath()) if err != nil { return err } @@ -17,7 +17,7 @@ func (u *Uninstall) runUninstall() error { return err } - err = removeConfig(u.configPath) + err = removeConfig(u.cfg) if err != nil { return err } diff --git a/internal/runners/clean/run_lin_mac.go b/internal/runners/clean/run_lin_mac.go index e0070da01a..f5f431b005 100644 --- a/internal/runners/clean/run_lin_mac.go +++ b/internal/runners/clean/run_lin_mac.go @@ -5,12 +5,11 @@ package clean import ( "os" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/logging" ) -func removeConfig(configPath string) error { - config.Get().SkipSave(true) +func removeConfig(cfg configurable) error { + cfg.SkipSave(true) file, err := os.Open(logging.FilePath()) if err != nil { @@ -25,7 +24,7 @@ func removeConfig(configPath string) error { return err } - return os.RemoveAll(configPath) + return os.RemoveAll(cfg.ConfigPath()) } func removeInstall(installPath string) error { diff --git a/internal/runners/clean/run_win.go b/internal/runners/clean/run_win.go index d336b84655..e6b8f46708 100644 --- a/internal/runners/clean/run_win.go +++ b/internal/runners/clean/run_win.go @@ -8,14 +8,13 @@ import ( "github.com/gobuffalo/packr" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/language" "github.com/ActiveState/cli/internal/scriptfile" ) -func removeConfig(configPath string) error { - config.Get().SkipSave(true) - return runScript("removeConfig", configPath) +func removeConfig(cfg configurable) error { + cfg.SkipSave(true) + return runScript("removeConfig", cfg.ConfigPath()) } func removeInstall(installPath string) error { diff --git a/internal/runners/clean/uninstall.go b/internal/runners/clean/uninstall.go index b3ed2c54f9..fb9da9f349 100644 --- a/internal/runners/clean/uninstall.go +++ b/internal/runners/clean/uninstall.go @@ -4,7 +4,6 @@ import ( "errors" "os" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/output" @@ -18,8 +17,7 @@ type confirmAble interface { type Uninstall struct { out output.Outputer confirm confirmAble - configPath string - cachePath string + cfg configurable installPath string } @@ -30,26 +28,24 @@ type UninstallParams struct { type primeable interface { primer.Outputer primer.Prompter + primer.Configurer } func NewUninstall(prime primeable) (*Uninstall, error) { - return newUninstall(prime.Output(), prime.Prompt()) + return newUninstall(prime.Output(), prime.Prompt(), prime.Config()) } -func newUninstall(out output.Outputer, confirm confirmAble) (*Uninstall, error) { +func newUninstall(out output.Outputer, confirm confirmAble, cfg configurable) (*Uninstall, error) { installPath, err := os.Executable() if err != nil { return nil, err } - cfg := config.Get() - return &Uninstall{ out: out, confirm: confirm, installPath: installPath, - configPath: cfg.ConfigPath(), - cachePath: cfg.CachePath(), + cfg: cfg, }, nil } diff --git a/internal/runners/deploy/deploy.go b/internal/runners/deploy/deploy.go index b4c5dbec4e..225a3f42b5 100644 --- a/internal/runners/deploy/deploy.go +++ b/internal/runners/deploy/deploy.go @@ -9,6 +9,7 @@ import ( "github.com/gobuffalo/packr" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/exeutils" "github.com/ActiveState/cli/internal/fileutils" @@ -45,6 +46,7 @@ type Deploy struct { output output.Outputer subshell subshell.SubShell step Step + cfg *config.Instance DefaultBranchForProjectName defaultBranchForProjectNameFunc NewRuntimeInstaller newInstallerFunc @@ -53,6 +55,7 @@ type Deploy struct { type primeable interface { primer.Outputer primer.Subsheller + primer.Configurer } func NewDeploy(step Step, prime primeable) *Deploy { @@ -60,6 +63,7 @@ func NewDeploy(step Step, prime primeable) *Deploy { prime.Output(), prime.Subshell(), step, + prime.Config(), model.DefaultBranchForProjectName, newInstaller, } @@ -84,7 +88,7 @@ func (d *Deploy) Run(params *Params) error { "Could not initialize an installer for {{.V0}}.", params.Namespace.String()) } - return runSteps(targetPath, params.Force, params.UserScope, params.Namespace, d.step, runtime, installer, d.output, d.subshell) + return runSteps(targetPath, params.Force, params.UserScope, params.Namespace, d.step, runtime, installer, d.output, d.cfg, d.subshell) } func (d *Deploy) createRuntimeInstaller(namespace project.Namespaced, targetPath string) (*runtime.Runtime, installable, error) { @@ -112,13 +116,13 @@ func (d *Deploy) createRuntimeInstaller(namespace project.Namespaced, targetPath return runtime, d.NewRuntimeInstaller(runtime), nil } -func runSteps(targetPath string, force bool, userScope bool, namespace project.Namespaced, step Step, runtime *runtime.Runtime, installer installable, out output.Outputer, subshell subshell.SubShell) error { +func runSteps(targetPath string, force bool, userScope bool, namespace project.Namespaced, step Step, runtime *runtime.Runtime, installer installable, out output.Outputer, cfg sscommon.Configurable, subshell subshell.SubShell) error { return runStepsWithFuncs( - targetPath, force, userScope, namespace, step, runtime, installer, out, subshell, + targetPath, force, userScope, namespace, step, runtime, installer, out, cfg, subshell, install, configure, symlink, report) } -func runStepsWithFuncs(targetPath string, force, userScope bool, namespace project.Namespaced, step Step, rt *runtime.Runtime, installer installable, out output.Outputer, subshell subshell.SubShell, installf installFunc, configuref configureFunc, symlinkf symlinkFunc, reportf reportFunc) error { +func runStepsWithFuncs(targetPath string, force, userScope bool, namespace project.Namespaced, step Step, rt *runtime.Runtime, installer installable, out output.Outputer, cfg sscommon.Configurable, subshell subshell.SubShell, installf installFunc, configuref configureFunc, symlinkf symlinkFunc, reportf reportFunc) error { logging.Debug("runSteps: %s", step.String()) var err error @@ -140,7 +144,7 @@ func runStepsWithFuncs(targetPath string, force, userScope bool, namespace proje } if step == UnsetStep || step == ConfigureStep { logging.Debug("Running configure step") - if err := configuref(targetPath, rt, out, subshell, namespace, userScope); err != nil { + if err := configuref(targetPath, rt, cfg, out, subshell, namespace, userScope); err != nil { return err } } @@ -185,9 +189,9 @@ func install(path string, installer installable, out output.Outputer) error { return nil } -type configureFunc func(installpath string, runtime *runtime.Runtime, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error +type configureFunc func(installpath string, runtime *runtime.Runtime, cfg sscommon.Configurable, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error -func configure(installpath string, runtime *runtime.Runtime, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error { +func configure(installpath string, runtime *runtime.Runtime, cfg sscommon.Configurable, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error { venv := virtualenvironment.New(runtime) env, err := venv.GetEnv(false, "") if err != nil { @@ -196,7 +200,7 @@ func configure(installpath string, runtime *runtime.Runtime, out output.Outputer out.Notice(output.Heading(locale.Tr("deploy_configure_shell", sshell.Shell()))) - err = sshell.WriteUserEnv(env, sscommon.Deploy, userScope) + err = sshell.WriteUserEnv(cfg, env, sscommon.Deploy, userScope) if err != nil { return locale.WrapError(err, "err_deploy_subshell_write", "Could not write environment information to your shell configuration.") } @@ -361,7 +365,7 @@ func report(path string, runtime *runtime.Runtime, out output.Outputer) error { }) out.Notice(output.Heading(locale.T("deploy_restart"))) - + if rt.GOOS == "windows" { out.Notice(locale.Tr("deploy_restart_cmd", filepath.Join(path, "setenv.bat"))) } else { diff --git a/internal/runners/events/events.go b/internal/runners/events/events.go index 1e1196f0f4..179215677d 100644 --- a/internal/runners/events/events.go +++ b/internal/runners/events/events.go @@ -15,6 +15,7 @@ type Events struct { type primeable interface { primer.Projecter primer.Outputer + primer.Configurer } func New(prime primeable) *Events { diff --git a/internal/runners/events/log.go b/internal/runners/events/log.go index e7f33a2cb6..2a54469bd2 100644 --- a/internal/runners/events/log.go +++ b/internal/runners/events/log.go @@ -13,6 +13,7 @@ import ( type EventLog struct { out output.Outputer + cfg process.Configurable } type EventLogParams struct { @@ -22,11 +23,12 @@ type EventLogParams struct { func NewLog(prime primeable) *EventLog { return &EventLog{ prime.Output(), + prime.Config(), } } func (e *EventLog) Run(params *EventLogParams) error { - pid := process.ActivationPID() + pid := process.ActivationPID(e.cfg) if pid == -1 { return locale.NewInputError("err_eventlog_pid", "Could not find parent process ID, make sure you're running this command from inside an activated state (run `state activate` first).") } diff --git a/internal/runners/export/config/config.go b/internal/runners/export/config/config.go index dbddfafa79..c785d89f5e 100644 --- a/internal/runners/export/config/config.go +++ b/internal/runners/export/config/config.go @@ -2,13 +2,17 @@ package config import ( "github.com/ActiveState/cli/internal/captain" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/primer" ) +type configurable interface { + ConfigPath() string +} + type Config struct { out output.Outputer + cfg configurable } type ConfigParams struct { @@ -17,15 +21,16 @@ type ConfigParams struct { type primeable interface { primer.Outputer + primer.Configurer } func New(prime primeable) *Config { - return &Config{prime.Output()} + return &Config{prime.Output(), prime.Config()} } func (c *Config) Run(cmd *captain.Command, params *ConfigParams) error { output := map[string]string{ - Dir.String(): config.Get().ConfigPath(), + Dir.String(): c.cfg.ConfigPath(), } filteredOutput := output diff --git a/internal/runners/export/privkey.go b/internal/runners/export/privkey.go index 3eb0575306..fc65227ba7 100644 --- a/internal/runners/export/privkey.go +++ b/internal/runners/export/privkey.go @@ -2,6 +2,7 @@ package export import ( "github.com/ActiveState/cli/internal/constants" + "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" "github.com/ActiveState/cli/internal/keypairs" "github.com/ActiveState/cli/internal/locale" @@ -30,7 +31,10 @@ func (p *PrivateKey) Run(params *PrivateKeyParams) error { return locale.NewError("User") } - filepath := keypairs.LocalKeyFilename(constants.KeypairLocalFileName) + filepath, err := keypairs.LocalKeyFilename(constants.KeypairLocalFileName) + if err != nil { + return errs.Wrap(err, "Failed to get local key file name") + } contents, err := fileutils.ReadFile(filepath) if err != nil { return err diff --git a/internal/runners/prepare/prepare.go b/internal/runners/prepare/prepare.go index 21dd4ab9db..bb7709e80d 100644 --- a/internal/runners/prepare/prepare.go +++ b/internal/runners/prepare/prepare.go @@ -18,12 +18,14 @@ import ( type primeable interface { primer.Outputer primer.Subsheller + primer.Configurer } // Prepare manages the prepare execution context. type Prepare struct { out output.Outputer subshell subshell.SubShell + cfg globaldefault.DefaultConfigurer } // New prepares a prepare execution context for use. @@ -31,6 +33,7 @@ func New(prime primeable) *Prepare { return &Prepare{ out: prime.Output(), subshell: prime.Subshell(), + cfg: prime.Config(), } } @@ -46,14 +49,14 @@ func (r *Prepare) Run() error { } } - if err := globaldefault.Prepare(r.subshell); err != nil { + if err := globaldefault.Prepare(r.cfg, r.subshell); err != nil { msgLocale := fmt.Sprintf("prepare_instructions_%s", runtime.GOOS) if runtime.GOOS != "linux" { - return locale.WrapError(err, msgLocale, globaldefault.BinDir()) + return locale.WrapError(err, msgLocale, globaldefault.BinDir(r.cfg)) } logging.Debug("Encountered failure attempting to update user environment: %s", err) r.out.Notice(output.Heading(locale.Tl("warning", "Warning"))) - r.out.Notice(locale.Tr(msgLocale, globaldefault.BinDir())) + r.out.Notice(locale.Tr(msgLocale, globaldefault.BinDir(r.cfg))) } return nil diff --git a/internal/runners/projects/projects.go b/internal/runners/projects/projects.go index b6a0d47ed7..d856a0ff2c 100644 --- a/internal/runners/projects/projects.go +++ b/internal/runners/projects/projects.go @@ -62,14 +62,15 @@ type Projects struct { type primeable interface { primer.Auther primer.Outputer + primer.Configurer } func NewParams() *Params { return &Params{Local: false} } -func NewProjects(prime primeable, config configGetter) *Projects { - return newProjects(prime.Auth(), prime.Output(), config) +func NewProjects(prime primeable) *Projects { + return newProjects(prime.Auth(), prime.Output(), prime.Config()) } func newProjects(auth *authentication.Auth, out output.Outputer, config configGetter) *Projects { diff --git a/internal/runners/projects/remote.go b/internal/runners/projects/remote.go index 3413dd55ea..3e4b5edec7 100644 --- a/internal/runners/projects/remote.go +++ b/internal/runners/projects/remote.go @@ -16,7 +16,7 @@ import ( // RunRemote runs the remote projects logic. func (r *Projects) RunRemote(params *Params) error { - projectfile.CleanProjectMapping() + projectfile.CleanProjectMapping(r.config) projectsList, err := r.fetchProjects(params.Local) if err != nil { diff --git a/internal/runners/pull/pull.go b/internal/runners/pull/pull.go index 9822ae394a..341cf96b73 100644 --- a/internal/runners/pull/pull.go +++ b/internal/runners/pull/pull.go @@ -22,6 +22,7 @@ type Pull struct { prompt prompt.Prompter project *project.Project out output.Outputer + cfg *config.Instance } type PullParams struct { @@ -33,6 +34,7 @@ type primeable interface { primer.Prompter primer.Projecter primer.Outputer + primer.Configurer } func New(prime primeable) *Pull { @@ -40,6 +42,7 @@ func New(prime primeable) *Pull { prime.Prompt(), prime.Project(), prime.Output(), + prime.Config(), } } @@ -117,7 +120,7 @@ func (p *Pull) Run(params *PullParams) error { return nil } - fname := path.Join(config.Get().ConfigPath(), constants.UpdateHailFileName) + fname := path.Join(p.cfg.ConfigPath(), constants.UpdateHailFileName) // must happen last in this function scope (defer if needed) if err := hail.Send(fname, []byte(actID)); err != nil { logging.Error("failed to send hail via %q: %s", fname, err) diff --git a/internal/runners/push/push.go b/internal/runners/push/push.go index 4240f22ea6..f0c8864eea 100644 --- a/internal/runners/push/push.go +++ b/internal/runners/push/push.go @@ -32,10 +32,11 @@ type PushParams struct { type primeable interface { primer.Outputer primer.Projecter + primer.Configurer } -func NewPush(config configGetter, prime primeable) *Push { - return &Push{config, prime.Output(), prime.Project()} +func NewPush(prime primeable) *Push { + return &Push{prime.Config(), prime.Output(), prime.Project()} } func (r *Push) Run(params PushParams) error { diff --git a/internal/runners/run/run.go b/internal/runners/run/run.go index 0de32a635a..b9db999b05 100644 --- a/internal/runners/run/run.go +++ b/internal/runners/run/run.go @@ -9,6 +9,7 @@ import ( "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/output/txtstyle" "github.com/ActiveState/cli/internal/primer" + "github.com/ActiveState/cli/internal/process" "github.com/ActiveState/cli/internal/scriptrun" "github.com/ActiveState/cli/internal/subshell" "github.com/ActiveState/cli/pkg/cmdlets/checker" @@ -21,12 +22,14 @@ type Run struct { out output.Outputer proj *project.Project subshell subshell.SubShell + cfg process.Configurable } type primeable interface { primer.Outputer primer.Projecter primer.Subsheller + primer.Configurer } // New constructs a new instance of Run. @@ -35,15 +38,16 @@ func New(prime primeable) *Run { prime.Output(), prime.Project(), prime.Subshell(), + prime.Config(), } } // Run runs the Run run runner. func (r *Run) Run(name string, args []string) error { - return run(r.out, r.subshell, r.proj, name, args) + return run(r.out, r.subshell, r.proj, r.cfg, name, args) } -func run(out output.Outputer, subs subshell.SubShell, proj *project.Project, name string, args []string) error { +func run(out output.Outputer, subs subshell.SubShell, proj *project.Project, cfg process.Configurable, name string, args []string) error { logging.Debug("Execute") if proj == nil { @@ -65,7 +69,7 @@ func run(out output.Outputer, subs subshell.SubShell, proj *project.Project, nam return locale.NewInputError("error_state_run_unknown_name", "Script does not exist: {{.V0}}", name) } - scriptrunner := scriptrun.New(out, subs, proj) + scriptrunner := scriptrun.New(out, subs, proj, cfg) if !script.Standalone() && scriptrunner.NeedsActivation() { out.Notice(output.Heading(locale.Tl("notice", "Notice"))) out.Notice(locale.T("info_state_run_activating_state")) diff --git a/internal/runners/tutorial/tutorial.go b/internal/runners/tutorial/tutorial.go index af6d0eb46a..3face3b416 100644 --- a/internal/runners/tutorial/tutorial.go +++ b/internal/runners/tutorial/tutorial.go @@ -7,7 +7,6 @@ import ( "github.com/skratchdot/open-golang/open" "github.com/ActiveState/cli/internal/analytics" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/fileutils" "github.com/ActiveState/cli/internal/language" @@ -19,20 +18,26 @@ import ( "github.com/ActiveState/cli/pkg/platform/authentication" ) +type configurable interface { + Reload() error +} + type Tutorial struct { outputer output.Outputer auth *authentication.Auth prompt prompt.Prompter + cfg configurable } type primeable interface { primer.Outputer primer.Prompter primer.Auther + primer.Configurer } func New(primer primeable) *Tutorial { - return &Tutorial{primer.Output(), primer.Auth(), primer.Prompt()} + return &Tutorial{primer.Output(), primer.Auth(), primer.Prompt(), primer.Config()} } type NewProjectParams struct { @@ -164,7 +169,10 @@ func (t *Tutorial) authFlow() error { } // Reload authentication info - config.Get().Reload() + err = t.cfg.Reload() + if err != nil { + return locale.WrapError(err, "err_tutorial_cfg_reload", "Failed to reload configuration.") + } if err := t.auth.Authenticate(); err != nil { return locale.WrapError(err, "err_tutorial_auth", "Could not authenticate after invoking `state auth ..`.") diff --git a/internal/scriptrun/scriptrun.go b/internal/scriptrun/scriptrun.go index eeb3ec0a2c..24dc9b8dcd 100644 --- a/internal/scriptrun/scriptrun.go +++ b/internal/scriptrun/scriptrun.go @@ -25,17 +25,19 @@ type ScriptRun struct { out output.Outputer sub subshell.SubShell project *project.Project + cfg process.Configurable venvPrepared bool venvExePath string } // New returns a pointer to a prepared instance of ScriptRun. -func New(out output.Outputer, subs subshell.SubShell, proj *project.Project) *ScriptRun { +func New(out output.Outputer, subs subshell.SubShell, proj *project.Project, cfg process.Configurable) *ScriptRun { return &ScriptRun{ out, subs, proj, + cfg, false, @@ -48,7 +50,7 @@ func New(out output.Outputer, subs subshell.SubShell, proj *project.Project) *Sc // NeedsActivation indicates whether the underlying environment has been // prepared and activated. func (s *ScriptRun) NeedsActivation() bool { - return !process.IsActivated() && !s.venvPrepared + return !process.IsActivated(s.cfg) && !s.venvPrepared } // PrepareVirtualEnv sets up the relevant runtime and prepares the environment. diff --git a/internal/subshell/bash/bash.go b/internal/subshell/bash/bash.go index aa4ff0fa91..9a54269b40 100644 --- a/internal/subshell/bash/bash.go +++ b/internal/subshell/bash/bash.go @@ -45,7 +45,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "HomeDir failed") @@ -77,10 +77,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(out output.Outputer) error { +func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("bashrc.sh", "", env, out); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("bashrc.sh", "", env, out, cfg); err != nil { return err } diff --git a/internal/subshell/cmd/cmd.go b/internal/subshell/cmd/cmd.go index 70d0bae727..7f3489ad3b 100644 --- a/internal/subshell/cmd/cmd.go +++ b/internal/subshell/cmd/cmd.go @@ -5,7 +5,6 @@ import ( "os/exec" "path/filepath" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/fileutils" "github.com/ActiveState/cli/internal/osutils" "github.com/ActiveState/cli/internal/output" @@ -45,11 +44,11 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, userScope bool) error { +func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, userScope bool) error { cmdEnv := NewCmdEnv(userScope) // Clean up old entries - oldEnv := config.Get().GetStringMap(envType.Key) + oldEnv := cfg.GetStringMap(envType.Key) for k, v := range oldEnv { if err := cmdEnv.unset(k, v.(string)); err != nil { return err @@ -57,7 +56,7 @@ func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, } // Store new entries - config.Get().Set(envType.Key, env) + cfg.Set(envType.Key, env) for k, v := range env { value := v @@ -106,10 +105,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(out output.Outputer) error { +func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("config.bat", ".bat", env, out); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("config.bat", ".bat", env, out, cfg); err != nil { return err } diff --git a/internal/subshell/fish/fish.go b/internal/subshell/fish/fish.go index fba65d9cca..b7620be5ab 100644 --- a/internal/subshell/fish/fish.go +++ b/internal/subshell/fish/fish.go @@ -46,7 +46,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "HomeDir failed") @@ -78,10 +78,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(out output.Outputer) error { +func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("fishrc.fish", "", env, out); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("fishrc.fish", "", env, out, cfg); err != nil { return err } diff --git a/internal/subshell/sscommon/rcfile.go b/internal/subshell/sscommon/rcfile.go index 28424c6c0c..f2ad8e5e1d 100644 --- a/internal/subshell/sscommon/rcfile.go +++ b/internal/subshell/sscommon/rcfile.go @@ -14,7 +14,6 @@ import ( "github.com/mash/go-tempfile-suffix" "github.com/ActiveState/cli/internal/colorize" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" @@ -39,6 +38,13 @@ var ( } ) +// Configurable defines an interface to store and get configuration data +type Configurable interface { + Set(string, interface{}) + GetBool(string) bool + GetStringMap(string) map[string]interface{} +} + type EnvData struct { Start string Stop string @@ -156,7 +162,7 @@ func SetupShellRcFile(rcFileName, templateName string, env map[string]string, na // SetupProjectRcFile creates a temporary RC file that our shell is initiated from, this allows us to template the logic // used for initialising the subshell -func SetupProjectRcFile(templateName, ext string, env map[string]string, out output.Outputer) (*os.File, error) { +func SetupProjectRcFile(templateName, ext string, env map[string]string, out output.Outputer, cfg Configurable) (*os.File, error) { box := packr.NewBox("../../../assets/shells") tpl := box.String(templateName) prj := project.Get() @@ -171,14 +177,14 @@ func SetupProjectRcFile(templateName, ext string, env map[string]string, out out return nil, errs.Wrap(err, "Misc failure") } - if strings.ToLower(event.Name()) == "first-activate" && !config.Get().GetBool(activatedKey) { + if strings.ToLower(event.Name()) == "first-activate" && !cfg.GetBool(activatedKey) { userScripts = v + "\n" + userScripts } if strings.ToLower(event.Name()) == "activate" { userScripts = userScripts + "\n" + v } } - config.Get().Set(activatedKey, true) + cfg.Set(activatedKey, true) inuse := []string{} scripts := map[string]string{} diff --git a/internal/subshell/subshell.go b/internal/subshell/subshell.go index b2ca5d0f1e..b0135efcdb 100644 --- a/internal/subshell/subshell.go +++ b/internal/subshell/subshell.go @@ -25,7 +25,7 @@ import ( // under the same directory as this file type SubShell interface { // Activate the given subshell - Activate(out output.Outputer) error + Activate(cfg sscommon.Configurable, out output.Outputer) error // Errors returns a channel to receive errors Errors() <-chan error @@ -46,7 +46,7 @@ type SubShell interface { SetBinary(string) // WriteUserEnv writes the given env map to the users environment - WriteUserEnv(map[string]string, sscommon.EnvData, bool) error + WriteUserEnv(sscommon.Configurable, map[string]string, sscommon.EnvData, bool) error // SetupShellRcFile writes a script or source-able file that updates the environment variables and sets the prompt SetupShellRcFile(string, map[string]string, project.Namespaced) error @@ -64,7 +64,7 @@ type SubShell interface { Quote(value string) string } -// Get returns the subshell relevant to the current process, but does not activate it +// New returns the subshell relevant to the current process, but does not activate it func New() SubShell { binary := os.Getenv("SHELL") if binary == "" { diff --git a/internal/subshell/tcsh/tcsh.go b/internal/subshell/tcsh/tcsh.go index 3dc003276e..8a3267bacd 100644 --- a/internal/subshell/tcsh/tcsh.go +++ b/internal/subshell/tcsh/tcsh.go @@ -45,7 +45,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "IO failure") @@ -77,7 +77,7 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(out output.Outputer) error { +func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { // This is horrible but it works. tcsh doesn't offer a way to override the rc file and // doesn't let us run a script and then drop to interactive mode. So we source the // state rc file and then chain an exec which inherits the environment we just set up. @@ -88,7 +88,7 @@ func (v *SubShell) Activate(out output.Outputer) error { // hack to make it work. env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("tcsh.sh", "", env, out); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("tcsh.sh", "", env, out, cfg); err != nil { return err } diff --git a/internal/subshell/zsh/zsh.go b/internal/subshell/zsh/zsh.go index 273aa3f6c5..0fd66aebe1 100644 --- a/internal/subshell/zsh/zsh.go +++ b/internal/subshell/zsh/zsh.go @@ -50,7 +50,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "IO failure") @@ -82,10 +82,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(out output.Outputer) error { +func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("zshrc.sh", "", env, out); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("zshrc.sh", "", env, out, cfg); err != nil { return err } diff --git a/locale/en-us.yaml b/locale/en-us.yaml index 732f8fc5f7..5210226ba2 100644 --- a/locale/en-us.yaml +++ b/locale/en-us.yaml @@ -1629,3 +1629,5 @@ bundle_ingredient_alternatives_more: other: " - .. (to see more results run `state bundles search {{.V0}}`)" err_lock_version_invalid: other: "The locked version '{{.V0}}' could not be verified, are you sure it's valid?" +config_get_error: + other: Failed to read configuration. diff --git a/pkg/cmdlets/auth/signup.go b/pkg/cmdlets/auth/signup.go index 4ea9094aa2..615600dcc9 100644 --- a/pkg/cmdlets/auth/signup.go +++ b/pkg/cmdlets/auth/signup.go @@ -88,7 +88,12 @@ func downloadTOS() (string, error) { } defer resp.Body.Close() - tosPath := filepath.Join(config.Get().ConfigPath(), "platform_tos.txt") + cfg, err := config.Get() + if err != nil { + return "", errs.Wrap(err, "Could not get configuration required to store ToS document.") + } + + tosPath := filepath.Join(cfg.ConfigPath(), "platform_tos.txt") tosFile, err := os.Create(tosPath) if err != nil { return "", errs.Wrap(err, "Could not create Terms Of Service file in configuration directory.") diff --git a/pkg/platform/authentication/auth.go b/pkg/platform/authentication/auth.go index b6dc33c16a..0f7db05cd3 100644 --- a/pkg/platform/authentication/auth.go +++ b/pkg/platform/authentication/auth.go @@ -38,19 +38,32 @@ type Auth struct { clientAuth *runtime.ClientAuthInfoWriter bearerToken string user *mono_models.User + cfg Configurable +} + +type Configurable interface { + Set(string, interface{}) + GetString(string) string } // Get returns a cached version of Auth func Get() *Auth { if persist == nil { - persist = New() + cfg, err := config.Get() + if err != nil { + // TODO: We need to get rid of this Get() function altogether... + logging.Error("Could not get configuration required by auth: %v", err) + os.Exit(1) + } + persist = New(cfg) } return persist } // Client is a shortcut for calling Client() on the persisted auth func Client() *mono_client.Mono { - return Get().Client() + a := Get() + return a.Client() } // ClientAuth is a shortcut for calling ClientAuth() on the persisted auth @@ -70,10 +83,12 @@ func Logout() { } // New creates a new version of Auth -func New() *Auth { - auth := &Auth{} +func New(cfg Configurable) *Auth { + auth := &Auth{ + cfg: cfg, + } - if availableAPIToken() != "" { + if availableAPIToken(cfg) != "" { logging.Debug("Authenticating with stored API token") auth.Authenticate() } @@ -114,7 +129,7 @@ func (s *Auth) Authenticate() error { return nil } - apiToken := availableAPIToken() + apiToken := availableAPIToken(s.cfg) if apiToken == "" { return locale.NewInputError("err_no_credentials") } @@ -149,7 +164,7 @@ func (s *Auth) AuthenticateWithModel(credentials *mono_models.Credentials) error s.clientAuth = &clientAuth if credentials.Token != "" { - config.Get().Set("apiToken", credentials.Token) + s.cfg.Set("apiToken", credentials.Token) } else { if err := s.CreateToken(); err != nil { return errs.Wrap(err, "CreateToken failed") @@ -201,7 +216,7 @@ func (s *Auth) UserID() *strfmt.UUID { // Logout will destroy any session tokens and reset the current Auth instance func (s *Auth) Logout() { - config.Get().Set("apiToken", "") + s.cfg.Set("apiToken", "") s.client = nil s.clientAuth = nil s.bearerToken = "" @@ -263,7 +278,7 @@ func (s *Auth) CreateToken() error { return err } - config.Get().Set("apiToken", token) + s.cfg.Set("apiToken", token) return nil } @@ -286,7 +301,7 @@ func (s *Auth) NewAPIKey(name string) (string, error) { return tokenOK.Payload.Token, nil } -func availableAPIToken() string { +func availableAPIToken(cfg Configurable) string { tkn, err := gcloud.GetSecret(constants.APIKeyEnvVarName) if err != nil && !errors.Is(err, gcloud.ErrNotAvailable{}) { logging.Error("Could not retrieve gcloud secret: %v", err) @@ -300,5 +315,5 @@ func availableAPIToken() string { logging.Debug("Using API token passed via env var") return tkn } - return config.Get().GetString("apiToken") + return cfg.GetString("apiToken") } diff --git a/pkg/platform/runtime/runtime.go b/pkg/platform/runtime/runtime.go index 7c7d8410ae..b9e53cd96c 100644 --- a/pkg/platform/runtime/runtime.go +++ b/pkg/platform/runtime/runtime.go @@ -35,7 +35,11 @@ func NewRuntime(projectDir string, commitID strfmt.UUID, owner string, projectNa logging.Debug("In NewRuntime: resolved project dir is: %s", resolvedProjectDir) } - installPath := filepath.Join(config.Get().CachePath(), hash.ShortHash(resolvedProjectDir)) + cfg, err := config.Get() + if err != nil { + return nil, locale.WrapError(err, "config_get_err") + } + installPath := filepath.Join(cfg.CachePath(), hash.ShortHash(resolvedProjectDir)) return &Runtime{ runtimeDir: installPath, commitID: commitID, diff --git a/pkg/projectfile/projectfile.go b/pkg/projectfile/projectfile.go index 5c89a9f7e1..fa12df1211 100644 --- a/pkg/projectfile/projectfile.go +++ b/pkg/projectfile/projectfile.go @@ -482,8 +482,13 @@ func Parse(configFilepath string) (*Project, error) { return nil, errs.Wrap(err, "project.Init failed") } + cfg, err := config.Get() + if err != nil { + return nil, errs.Wrap(err, "Could not read configuration required by projectfile parser.") + } + namespace := fmt.Sprintf("%s/%s", project.parsedURL.Owner, project.parsedURL.Name) - storeProjectMapping(namespace, filepath.Dir(project.Path())) + storeProjectMapping(cfg, namespace, filepath.Dir(project.Path())) return project, nil } @@ -709,7 +714,12 @@ func (p *Project) save(path string) error { return errs.Wrap(err, "f.Write %s failed", path) } - storeProjectMapping(fmt.Sprintf("%s/%s", p.parsedURL.Owner, p.parsedURL.Name), filepath.Dir(p.Path())) + cfg, err := config.Get() + if err != nil { + return errs.Wrap(err, "Could not read configuration required to save project file") + } + + storeProjectMapping(cfg, fmt.Sprintf("%s/%s", p.parsedURL.Owner, p.parsedURL.Name), filepath.Dir(p.Path())) return nil } @@ -852,7 +862,11 @@ func getProjectFilePathFromWd() (string, error) { } func getProjectFilePathFromDefault() (string, error) { - defaultProjectPath := config.Get().GetString(constants.GlobalDefaultPrefname) + cfg, err := config.Get() + if err != nil { + return "", errs.Wrap(err, "Could not read configuration required to determine default project") + } + defaultProjectPath := cfg.GetString(constants.GlobalDefaultPrefname) if defaultProjectPath == "" { return "", nil } @@ -1197,7 +1211,7 @@ type ConfigGetter interface { func GetProjectMapping(config ConfigGetter) map[string][]string { addDeprecatedProjectMappings(config) - CleanProjectMapping() + CleanProjectMapping(config) projects := config.GetStringMapStringSlice(LocalProjectsConfigKey) if projects == nil { return map[string][]string{} @@ -1262,13 +1276,13 @@ func GetProjectPaths(config ConfigGetter, namespace string) []string { // storeProjectMapping associates the namespace with the project // path in the config -func storeProjectMapping(namespace, projectPath string) { +func storeProjectMapping(cfg ConfigGetter, namespace, projectPath string) { projectMapMutex.Lock() defer projectMapMutex.Unlock() projectPath = filepath.Clean(projectPath) - projects := config.Get().GetStringMapStringSlice(LocalProjectsConfigKey) + projects := cfg.GetStringMapStringSlice(LocalProjectsConfigKey) if projects == nil { projects = make(map[string][]string) } @@ -1283,13 +1297,13 @@ func storeProjectMapping(namespace, projectPath string) { } projects[namespace] = paths - config.Get().Set(LocalProjectsConfigKey, projects) + cfg.Set(LocalProjectsConfigKey, projects) } // CleanProjectMapping removes projects that no longer exist // on a user's filesystem from the projects config entry -func CleanProjectMapping() { - projects := config.Get().GetStringMapStringSlice(LocalProjectsConfigKey) +func CleanProjectMapping(cfg ConfigGetter) { + projects := cfg.GetStringMapStringSlice(LocalProjectsConfigKey) seen := map[string]bool{} for namespace, paths := range projects { @@ -1305,5 +1319,5 @@ func CleanProjectMapping() { seen[strings.ToLower(namespace)] = true } - config.Get().Set("projects", projects) + cfg.Set("projects", projects) } From 81c137cbad00c4c0534ed95bedc7ed7d190e7644 Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Fri, 8 Jan 2021 11:24:57 -0800 Subject: [PATCH 5/8] remove incorrectly updating namespace --- internal/runners/pull/pull.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/runners/pull/pull.go b/internal/runners/pull/pull.go index 341cf96b73..db7265a747 100644 --- a/internal/runners/pull/pull.go +++ b/internal/runners/pull/pull.go @@ -97,7 +97,6 @@ func (p *Pull) Run(params *PullParams) error { // Update the commit ID in the activestate.yaml if p.project.CommitID() != target.CommitID.String() { - p.project.Source().SetNamespace(target.Owner, target.Project) err := p.project.Source().SetCommit(target.CommitID.String(), false) if err != nil { return locale.WrapError(err, "err_pull_update", "Cannot update the commit in your project file.") From 9fb32110f15c5f8ceccb4772ef1130f52a00598b Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Fri, 8 Jan 2021 11:27:19 -0800 Subject: [PATCH 6/8] add question to confirmation prompt --- internal/runners/pull/pull.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/runners/pull/pull.go b/internal/runners/pull/pull.go index db7265a747..df419c09aa 100644 --- a/internal/runners/pull/pull.go +++ b/internal/runners/pull/pull.go @@ -80,7 +80,7 @@ func (p *Pull) Run(params *PullParams) error { if params.SetProject != "" { related, err := areCommitsRelated(*target.CommitID, p.project.CommitUUID()) if !related && !params.Force { - confirmed, err := p.prompt.Confirm(locale.T("confirm"), locale.Tl("confirm_unrelated_pull_set_project", "If you switch to {{.V0}}, you may lose changes to your project.", target.String()), false) + confirmed, err := p.prompt.Confirm(locale.T("confirm"), locale.Tl("confirm_unrelated_pull_set_project", "If you switch to {{.V0}}, you may lose changes to your project. Are you sure you want to do this?", target.String()), false) if err != nil { return locale.WrapError(err, "err_pull_confirm", "Failed to get user confirmation to update project") } From cbdce8f1d1a532e312722e04e7dc1b2e3723492d Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Fri, 8 Jan 2021 14:01:48 -0800 Subject: [PATCH 7/8] update confirm argument to bool pointer --- internal/runners/pull/pull.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/runners/pull/pull.go b/internal/runners/pull/pull.go index df419c09aa..3963d164d0 100644 --- a/internal/runners/pull/pull.go +++ b/internal/runners/pull/pull.go @@ -80,7 +80,7 @@ func (p *Pull) Run(params *PullParams) error { if params.SetProject != "" { related, err := areCommitsRelated(*target.CommitID, p.project.CommitUUID()) if !related && !params.Force { - confirmed, err := p.prompt.Confirm(locale.T("confirm"), locale.Tl("confirm_unrelated_pull_set_project", "If you switch to {{.V0}}, you may lose changes to your project. Are you sure you want to do this?", target.String()), false) + confirmed, err := p.prompt.Confirm(locale.T("confirm"), locale.Tl("confirm_unrelated_pull_set_project", "If you switch to {{.V0}}, you may lose changes to your project. Are you sure you want to do this?", target.String()), new(bool)) if err != nil { return locale.WrapError(err, "err_pull_confirm", "Failed to get user confirmation to update project") } From 3e52ad3ba649fdc371ffb46e1ae3ae5be89ea753 Mon Sep 17 00:00:00 2001 From: Martin C Drohmann Date: Fri, 8 Jan 2021 14:10:15 -0800 Subject: [PATCH 8/8] Revert "remove os.Exit from config" This reverts commit fca00b1703218d21bb6a4759836fe21912bb4a5b. --- cmd/state/forward.go | 15 +++-- cmd/state/internal/cmdtree/activate.go | 1 - cmd/state/internal/cmdtree/auth.go | 3 - cmd/state/internal/cmdtree/bundles.go | 4 -- cmd/state/internal/cmdtree/clean.go | 4 -- cmd/state/internal/cmdtree/cmdtree.go | 2 - cmd/state/internal/cmdtree/deploy.go | 5 -- cmd/state/internal/cmdtree/events.go | 2 - cmd/state/internal/cmdtree/export.go | 7 -- cmd/state/internal/cmdtree/fork.go | 1 - cmd/state/internal/cmdtree/history.go | 1 - cmd/state/internal/cmdtree/init.go | 1 - cmd/state/internal/cmdtree/invite.go | 1 - cmd/state/internal/cmdtree/languages.go | 2 - cmd/state/internal/cmdtree/organizations.go | 1 - cmd/state/internal/cmdtree/packages.go | 6 -- cmd/state/internal/cmdtree/platforms.go | 4 -- cmd/state/internal/cmdtree/prepare.go | 1 - cmd/state/internal/cmdtree/projects.go | 7 +- cmd/state/internal/cmdtree/protocol.go | 1 - cmd/state/internal/cmdtree/pull.go | 1 - cmd/state/internal/cmdtree/push.go | 4 +- cmd/state/internal/cmdtree/revert.go | 1 - cmd/state/internal/cmdtree/run.go | 1 - cmd/state/internal/cmdtree/scripts.go | 2 - cmd/state/internal/cmdtree/secrets.go | 4 -- cmd/state/internal/cmdtree/shim.go | 1 - cmd/state/internal/cmdtree/show.go | 1 - cmd/state/internal/cmdtree/tutorial.go | 2 - cmd/state/internal/cmdtree/update.go | 2 - cmd/state/main.go | 9 +-- internal/analytics/analytics.go | 18 ++--- internal/analytics/deferred.go | 33 ++++----- internal/captain/command.go | 6 +- internal/config/instance.go | 74 +++++++++------------ internal/deprecation/deprecation.go | 9 +-- internal/events/cmdcall/cmdcall.go | 3 +- internal/globaldefault/default.go | 32 ++++----- internal/keypairs/local.go | 24 ++----- internal/locale/locale.go | 29 +++----- internal/logging/defaults.go | 19 ++---- internal/logging/rollbar.go | 10 +-- internal/machineid/machineid.go | 10 +-- internal/primer/primer.go | 13 +--- internal/process/process.go | 21 +++--- internal/runners/activate/activate.go | 10 +-- internal/runners/activate/activation.go | 4 +- internal/runners/activate/namespace.go | 17 ++--- internal/runners/clean/cache.go | 7 +- internal/runners/clean/config.go | 19 ++---- internal/runners/clean/run.go | 4 +- internal/runners/clean/run_lin_mac.go | 7 +- internal/runners/clean/run_win.go | 7 +- internal/runners/clean/uninstall.go | 14 ++-- internal/runners/deploy/deploy.go | 22 +++--- internal/runners/events/events.go | 1 - internal/runners/events/log.go | 4 +- internal/runners/export/config/config.go | 11 +-- internal/runners/export/privkey.go | 6 +- internal/runners/prepare/prepare.go | 9 +-- internal/runners/projects/projects.go | 5 +- internal/runners/projects/remote.go | 2 +- internal/runners/pull/pull.go | 5 +- internal/runners/push/push.go | 5 +- internal/runners/run/run.go | 10 +-- internal/runners/tutorial/tutorial.go | 14 +--- internal/scriptrun/scriptrun.go | 6 +- internal/subshell/bash/bash.go | 6 +- internal/subshell/cmd/cmd.go | 11 +-- internal/subshell/fish/fish.go | 6 +- internal/subshell/sscommon/rcfile.go | 14 ++-- internal/subshell/subshell.go | 6 +- internal/subshell/tcsh/tcsh.go | 6 +- internal/subshell/zsh/zsh.go | 6 +- locale/en-us.yaml | 2 - pkg/cmdlets/auth/signup.go | 7 +- pkg/platform/authentication/auth.go | 37 +++-------- pkg/platform/runtime/runtime.go | 6 +- pkg/projectfile/projectfile.go | 34 +++------- 79 files changed, 243 insertions(+), 485 deletions(-) diff --git a/cmd/state/forward.go b/cmd/state/forward.go index 5e8dced37b..1f6d0c1ae3 100644 --- a/cmd/state/forward.go +++ b/cmd/state/forward.go @@ -8,6 +8,7 @@ import ( "github.com/phayes/permbits" "github.com/thoas/go-funk" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" @@ -27,7 +28,7 @@ const LatestVersion = "latest" type forwardFunc func() (int, error) -func forwardFn(bindir string, args []string, out output.Outputer, pj *project.Project) (forwardFunc, error) { +func forwardFn(args []string, out output.Outputer, pj *project.Project) (forwardFunc, error) { if pj == nil { return nil, nil } @@ -57,7 +58,7 @@ func forwardFn(bindir string, args []string, out output.Outputer, pj *project.Pr // Perform the forward out.Notice(output.Heading(locale.Tl("forward_title", "Version Locked"))) out.Notice(locale.Tr("forward_version", versionInfo.Version)) - code, err := forward(bindir, args, versionInfo, out) + code, err := forward(args, versionInfo, out) if err != nil { if code == 0 { code = 1 @@ -76,9 +77,9 @@ func forwardFn(bindir string, args []string, out output.Outputer, pj *project.Pr } // forward will forward the call to the appropriate State Tool version if necessary -func forward(bindir string, args []string, versionInfo *projectfile.VersionInfo, out output.Outputer) (int, error) { +func forward(args []string, versionInfo *projectfile.VersionInfo, out output.Outputer) (int, error) { logging.Debug("Forwarding to version %s/%s, arguments: %v", versionInfo.Branch, versionInfo.Version, args[1:]) - binary := forwardBin(bindir, versionInfo) + binary := forwardBin(versionInfo) err := ensureForwardExists(binary, versionInfo, out) if err != nil { return 1, err @@ -97,14 +98,15 @@ func execForward(binary string, args []string) (int, error) { return code, nil } -func forwardBin(bindir string, versionInfo *projectfile.VersionInfo) string { +func forwardBin(versionInfo *projectfile.VersionInfo) string { filename := fmt.Sprintf("%s-%s-%s", constants.CommandName, versionInfo.Branch, versionInfo.Version) if forceFileExt != "" { filename += forceFileExt } else if runtime.GOOS == "windows" { filename += ".exe" } - return filepath.Join(bindir, "version-cache", filename) + datadir := config.Get().ConfigPath() + return filepath.Join(datadir, "version-cache", filename) } func ensureForwardExists(binary string, versionInfo *projectfile.VersionInfo, out output.Outputer) error { @@ -149,3 +151,4 @@ func ensureForwardExists(binary string, versionInfo *projectfile.VersionInfo, ou return nil } + diff --git a/cmd/state/internal/cmdtree/activate.go b/cmd/state/internal/cmdtree/activate.go index 12e68dcc8f..b9ddbeb9e8 100644 --- a/cmd/state/internal/cmdtree/activate.go +++ b/cmd/state/internal/cmdtree/activate.go @@ -27,7 +27,6 @@ func newActivateCommand(prime *primer.Values) *captain.Command { "", locale.T("activate_project"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/auth.go b/cmd/state/internal/cmdtree/auth.go index bce3d7f678..bf9bb57d70 100644 --- a/cmd/state/internal/cmdtree/auth.go +++ b/cmd/state/internal/cmdtree/auth.go @@ -17,7 +17,6 @@ func newAuthCommand(prime *primer.Values) *captain.Command { locale.Tl("auth_title", "Signing In To The ActiveState Platform"), locale.T("auth_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "token", @@ -58,7 +57,6 @@ func newSignupCommand(prime *primer.Values) *captain.Command { locale.Tl("signup_title", "Signing Up With The ActiveState Platform"), locale.T("signup_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -74,7 +72,6 @@ func newLogoutCommand(prime *primer.Values) *captain.Command { locale.Tl("logout_title", "Logging Out Of The ActiveState Platform"), locale.T("logout_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { diff --git a/cmd/state/internal/cmdtree/bundles.go b/cmd/state/internal/cmdtree/bundles.go index 755e4e5fb4..9ef7c7af01 100644 --- a/cmd/state/internal/cmdtree/bundles.go +++ b/cmd/state/internal/cmdtree/bundles.go @@ -18,7 +18,6 @@ func newBundlesCommand(prime *primer.Values) *captain.Command { locale.Tl("bundles_title", "Listing Bundles"), locale.Tl("bundles_cmd_description", "Manage bundles used in your project"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "commit", @@ -57,7 +56,6 @@ func newBundleInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("bundle_install_title", "Installing Bundle"), locale.Tl("bundle_install_cmd_description", "Add a new bundle to your project"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -83,7 +81,6 @@ func newBundleUninstallCommand(prime *primer.Values) *captain.Command { locale.Tl("bundle_uninstall_title", "Uninstalling Bundle"), locale.Tl("bundle_uninstall_cmd_description", "Remove bundle from your project"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -109,7 +106,6 @@ func newBundlesSearchCommand(prime *primer.Values) *captain.Command { locale.Tl("bundle_search_title", "Searching Bundles"), locale.Tl("bundle_search_cmd_description", "Search for all available bundles that can be added to your project"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "language", diff --git a/cmd/state/internal/cmdtree/clean.go b/cmd/state/internal/cmdtree/clean.go index 58db767abb..81b67d60b7 100644 --- a/cmd/state/internal/cmdtree/clean.go +++ b/cmd/state/internal/cmdtree/clean.go @@ -13,7 +13,6 @@ func newCleanCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_title", "Cleaning Resources"), locale.T("clean_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { @@ -30,7 +29,6 @@ func newCleanUninstallCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_uninstall_title", "Uninstalling"), locale.T("uninstall_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "force", @@ -59,7 +57,6 @@ func newCleanCacheCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_cache_title", "Cleaning Cached Runtimes"), locale.T("cache_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "force", @@ -90,7 +87,6 @@ func newCleanConfigCommand(prime *primer.Values) *captain.Command { locale.Tl("clean_config_title", "Cleaning Configuration"), locale.T("config_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "force", diff --git a/cmd/state/internal/cmdtree/cmdtree.go b/cmd/state/internal/cmdtree/cmdtree.go index 767d9f2641..67821bfdfb 100644 --- a/cmd/state/internal/cmdtree/cmdtree.go +++ b/cmd/state/internal/cmdtree/cmdtree.go @@ -183,7 +183,6 @@ func newStateCommand(globals *globalOptions, prime *primer.Values) *captain.Comm "", locale.T("state_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "locale", @@ -275,7 +274,6 @@ func (a *addCmdAs) deprecatedAlias(aliased *captain.Command, name string) { aliased.Title(), aliased.Description(), a.prime.Output(), - a.prime.Config(), aliased.Flags(), aliased.Arguments(), func(c *captain.Command, args []string) error { diff --git a/cmd/state/internal/cmdtree/deploy.go b/cmd/state/internal/cmdtree/deploy.go index 9d8b6928da..583e5c70e2 100644 --- a/cmd/state/internal/cmdtree/deploy.go +++ b/cmd/state/internal/cmdtree/deploy.go @@ -39,7 +39,6 @@ func newDeployCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_title", "Deploying Runtime"), locale.T("deploy_cmd_description"), prime.Output(), - prime.Config(), flags, []*captain.Argument{ { @@ -64,7 +63,6 @@ func newDeployInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_install_title", "Installing Runtime (Unconfigured)"), locale.T("deploy_install_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "path", @@ -110,7 +108,6 @@ func newDeployConfigureCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_configure_title", "Configuring Runtime For Your Shell"), locale.T("deploy_configure_cmd_description"), prime.Output(), - prime.Config(), flags, []*captain.Argument{ { @@ -135,7 +132,6 @@ func newDeploySymlinkCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_symlink_title", "Symlinking Executables"), locale.T("deploy_symlink_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "path", @@ -171,7 +167,6 @@ func newDeployReportCommand(prime *primer.Values) *captain.Command { locale.Tl("deploy_report_title", "Reporting Deployment Information"), locale.T("deploy_report_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/events.go b/cmd/state/internal/cmdtree/events.go index af0e1061ca..ef480f3747 100644 --- a/cmd/state/internal/cmdtree/events.go +++ b/cmd/state/internal/cmdtree/events.go @@ -15,7 +15,6 @@ func newEventsCommand(prime *primer.Values) *captain.Command { locale.Tl("events_title", "Listing Events"), locale.Tl("events_description", "Manage project events"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(cmd *captain.Command, args []string) error { @@ -32,7 +31,6 @@ func newEventsLogCommand(prime *primer.Values) *captain.Command { locale.Tl("events_log_title", "Showing Events Log"), locale.Tl("events_log_description", "View a log of events"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "follow", diff --git a/cmd/state/internal/cmdtree/export.go b/cmd/state/internal/cmdtree/export.go index 2baa51a448..acb2efb0dd 100644 --- a/cmd/state/internal/cmdtree/export.go +++ b/cmd/state/internal/cmdtree/export.go @@ -19,7 +19,6 @@ func newExportCommand(prime *primer.Values) *captain.Command { locale.Tl("export_title", "Exporting Information"), locale.T("export_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -37,7 +36,6 @@ func newRecipeCommand(prime *primer.Values) *captain.Command { locale.Tl("export_recipe_title", "Exporting Recipe Data"), locale.T("export_recipe_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "pretty", @@ -73,7 +71,6 @@ func newJWTCommand(prime *primer.Values) *captain.Command { locale.Tl("export_jwt_title", "Exporting Credentials"), locale.T("export_jwt_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -91,7 +88,6 @@ func newPrivateKeyCommand(prime *primer.Values) *captain.Command { locale.Tl("export_privkey_title", "Exporting Private Key"), locale.T("export_privkey_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -108,7 +104,6 @@ func newAPIKeyCommand(prime *primer.Values) *captain.Command { locale.Tl("export_new_api_key_title", "Exporting New API Key"), locale.T("export_new_api_key_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -133,7 +128,6 @@ func newExportConfigCommand(prime *primer.Values) *captain.Command { locale.Tl("export_config_title", "Exporting Configuration Data"), locale.T("export_config_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "filter", @@ -159,7 +153,6 @@ func newExportGithubActionCommand(prime *primer.Values) *captain.Command { locale.Tl("export_ghactions_title", "Exporting Github Action Workflow"), locale.Tl("export_ghactions_description", "Create a github action workflow for your project"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/fork.go b/cmd/state/internal/cmdtree/fork.go index a102ae66f8..8c7de4de57 100644 --- a/cmd/state/internal/cmdtree/fork.go +++ b/cmd/state/internal/cmdtree/fork.go @@ -16,7 +16,6 @@ func newForkCommand(prime *primer.Values) *captain.Command { locale.Tl("fork_title", "Forking Project"), locale.Tl("fork_description", "Fork an existing ActiveState Platform project"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "org", diff --git a/cmd/state/internal/cmdtree/history.go b/cmd/state/internal/cmdtree/history.go index c0ac150c9d..1a52df1e45 100644 --- a/cmd/state/internal/cmdtree/history.go +++ b/cmd/state/internal/cmdtree/history.go @@ -20,7 +20,6 @@ func newHistoryCommand(prime *primer.Values) *captain.Command { locale.Tl("history_title", "Viewing Project History"), locale.T("history_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "namespace", diff --git a/cmd/state/internal/cmdtree/init.go b/cmd/state/internal/cmdtree/init.go index 2365462e8a..d1f4335a67 100644 --- a/cmd/state/internal/cmdtree/init.go +++ b/cmd/state/internal/cmdtree/init.go @@ -20,7 +20,6 @@ func newInitCommand(prime *primer.Values) *captain.Command { locale.Tl("init_title", "Initializing Project"), locale.T("init_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/invite.go b/cmd/state/internal/cmdtree/invite.go index 1156278d31..22b0eae911 100644 --- a/cmd/state/internal/cmdtree/invite.go +++ b/cmd/state/internal/cmdtree/invite.go @@ -17,7 +17,6 @@ func newInviteCommand(prime *primer.Values) *captain.Command { locale.Tl("invite_title", "Inviting New Members"), locale.Tl("invite_description", "Invite new members to an organization"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "organization", diff --git a/cmd/state/internal/cmdtree/languages.go b/cmd/state/internal/cmdtree/languages.go index 5e68aea833..36e5baca65 100644 --- a/cmd/state/internal/cmdtree/languages.go +++ b/cmd/state/internal/cmdtree/languages.go @@ -15,7 +15,6 @@ func newLanguagesCommand(prime *primer.Values) *captain.Command { locale.Tl("languages_title", "Listing Languages"), locale.T("languages_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { @@ -34,7 +33,6 @@ func newLanguageInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("languages_install_title", "Installing Language"), locale.T("languages_install_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/organizations.go b/cmd/state/internal/cmdtree/organizations.go index e8918b1321..ccff0588bb 100644 --- a/cmd/state/internal/cmdtree/organizations.go +++ b/cmd/state/internal/cmdtree/organizations.go @@ -17,7 +17,6 @@ func newOrganizationsCommand(prime *primer.Values) *captain.Command { locale.Tl("organizations_title", "Listing Organizations"), locale.T("organizations_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/packages.go b/cmd/state/internal/cmdtree/packages.go index 44316d64cc..e81303a1d3 100644 --- a/cmd/state/internal/cmdtree/packages.go +++ b/cmd/state/internal/cmdtree/packages.go @@ -18,7 +18,6 @@ func newPackagesCommand(prime *primer.Values) *captain.Command { locale.Tl("package_title", "Listing Packages"), locale.T("package_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "commit", @@ -58,7 +57,6 @@ func newInstallCommand(prime *primer.Values) *captain.Command { locale.Tl("package_install_title", "Installing Package"), locale.T("package_install_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -84,7 +82,6 @@ func newUninstallCommand(prime *primer.Values) *captain.Command { locale.Tl("package_uninstall_title", "Uninstalling Package"), locale.T("package_uninstall_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { @@ -110,7 +107,6 @@ func newImportCommand(prime *primer.Values) *captain.Command { locale.Tl("package_import_title", "Importing Packages"), locale.T("package_import_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "force", @@ -142,7 +138,6 @@ func newSearchCommand(prime *primer.Values) *captain.Command { locale.Tl("package_search_title", "Searching Packages"), locale.T("package_search_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "language", @@ -179,7 +174,6 @@ func newInfoCommand(prime *primer.Values) *captain.Command { locale.Tl("package_info_title", "Displaying Package Information"), locale.T("package_info_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "language", diff --git a/cmd/state/internal/cmdtree/platforms.go b/cmd/state/internal/cmdtree/platforms.go index 13e34bb86d..f224647ee0 100644 --- a/cmd/state/internal/cmdtree/platforms.go +++ b/cmd/state/internal/cmdtree/platforms.go @@ -18,7 +18,6 @@ func newPlatformsCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_title", "Listing Platforms"), locale.T("platforms_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(_ *captain.Command, _ []string) error { @@ -41,7 +40,6 @@ func newPlatformsSearchCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_search_title", "Searching Platforms"), locale.T("platforms_search_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(_ *captain.Command, _ []string) error { @@ -60,7 +58,6 @@ func newPlatformsAddCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_add_title", "Adding Platform"), locale.T("platforms_add_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: locale.T("flag_platforms_shared_bitwidth"), @@ -98,7 +95,6 @@ func newPlatformsRemoveCommand(prime *primer.Values) *captain.Command { locale.Tl("platforms_remove_title", "Removing Platform"), locale.T("platforms_remove_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: locale.T("flag_platforms_shared_bitwidth"), diff --git a/cmd/state/internal/cmdtree/prepare.go b/cmd/state/internal/cmdtree/prepare.go index 557fea1bab..17690ed39d 100644 --- a/cmd/state/internal/cmdtree/prepare.go +++ b/cmd/state/internal/cmdtree/prepare.go @@ -15,7 +15,6 @@ func newPrepareCommand(prime *primer.Values) *captain.Command { "", locale.Tl("prepare_description", "Prepare environment for use with the State Tool."), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(_ *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/projects.go b/cmd/state/internal/cmdtree/projects.go index 34f28867bd..c3c25d0826 100644 --- a/cmd/state/internal/cmdtree/projects.go +++ b/cmd/state/internal/cmdtree/projects.go @@ -2,13 +2,14 @@ package cmdtree import ( "github.com/ActiveState/cli/internal/captain" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/primer" "github.com/ActiveState/cli/internal/runners/projects" ) func newProjectsCommand(prime *primer.Values) *captain.Command { - runner := projects.NewProjects(prime) + runner := projects.NewProjects(prime, config.Get()) params := projects.NewParams() return captain.NewCommand( @@ -16,7 +17,6 @@ func newProjectsCommand(prime *primer.Values) *captain.Command { locale.Tl("projects_title", "Listing Projects"), locale.T("projects_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -26,7 +26,7 @@ func newProjectsCommand(prime *primer.Values) *captain.Command { } func newRemoteProjectsCommand(prime *primer.Values) *captain.Command { - runner := projects.NewProjects(prime) + runner := projects.NewProjects(prime, config.Get()) params := projects.NewParams() return captain.NewCommand( @@ -34,7 +34,6 @@ func newRemoteProjectsCommand(prime *primer.Values) *captain.Command { locale.Tl("projects_remote_title", "Listing Remote Projects"), locale.Tl("projects_remote_description", "Manage all projects, including ones you have not checked out locally"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { diff --git a/cmd/state/internal/cmdtree/protocol.go b/cmd/state/internal/cmdtree/protocol.go index b860758d3c..129d1799b9 100644 --- a/cmd/state/internal/cmdtree/protocol.go +++ b/cmd/state/internal/cmdtree/protocol.go @@ -16,7 +16,6 @@ func newProtocolCommand(prime *primer.Values) *captain.Command { "", locale.Tl("protocol_description", "Process URLs that use the state protocol"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/pull.go b/cmd/state/internal/cmdtree/pull.go index 1acedeea54..75584db654 100644 --- a/cmd/state/internal/cmdtree/pull.go +++ b/cmd/state/internal/cmdtree/pull.go @@ -17,7 +17,6 @@ func newPullCommand(prime *primer.Values) *captain.Command { locale.Tl("pull_title", "Pulling Remote Project"), locale.Tl("pull_description", "Pull in the latest version of your project from the ActiveState Platform"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "force", diff --git a/cmd/state/internal/cmdtree/push.go b/cmd/state/internal/cmdtree/push.go index 3c3ff44f03..6febc3a77e 100644 --- a/cmd/state/internal/cmdtree/push.go +++ b/cmd/state/internal/cmdtree/push.go @@ -2,6 +2,7 @@ package cmdtree import ( "github.com/ActiveState/cli/internal/captain" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/primer" "github.com/ActiveState/cli/internal/runners/push" @@ -9,7 +10,7 @@ import ( ) func newPushCommand(prime *primer.Values) *captain.Command { - pushRunner := push.NewPush(prime) + pushRunner := push.NewPush(config.Get(), prime) params := push.PushParams{ Namespace: &project.Namespaced{}, @@ -20,7 +21,6 @@ func newPushCommand(prime *primer.Values) *captain.Command { locale.Tl("push_title", "Pushing Local Project"), locale.T("push_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/revert.go b/cmd/state/internal/cmdtree/revert.go index 570d22bbc6..a49192f643 100644 --- a/cmd/state/internal/cmdtree/revert.go +++ b/cmd/state/internal/cmdtree/revert.go @@ -16,7 +16,6 @@ func newRevertCommand(prime *primer.Values) *captain.Command { locale.Tl("revert_title", "Reverting Commit"), locale.Tl("revert_description", "Revert a commit"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/run.go b/cmd/state/internal/cmdtree/run.go index 17e20fd36f..3a45b0a628 100644 --- a/cmd/state/internal/cmdtree/run.go +++ b/cmd/state/internal/cmdtree/run.go @@ -17,7 +17,6 @@ func newRunCommand(prime *primer.Values) *captain.Command { "", locale.T("run_description"), prime.Output(), - prime.Config(), nil, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/scripts.go b/cmd/state/internal/cmdtree/scripts.go index 2849edf4b7..413639d99f 100644 --- a/cmd/state/internal/cmdtree/scripts.go +++ b/cmd/state/internal/cmdtree/scripts.go @@ -15,7 +15,6 @@ func newScriptsCommand(prime *primer.Values) *captain.Command { locale.Tl("scripts_title", "Listing Scripts"), locale.T("scripts_description"), prime.Output(), - prime.Config(), []*captain.Flag{}, []*captain.Argument{}, func(ccmd *captain.Command, args []string) error { @@ -32,7 +31,6 @@ func newScriptsEditCommand(prime *primer.Values) *captain.Command { locale.Tl("scripts_edit_title", "Editing Script"), locale.T("edit_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "expand", diff --git a/cmd/state/internal/cmdtree/secrets.go b/cmd/state/internal/cmdtree/secrets.go index a1e5f04a0b..8cad1a4783 100644 --- a/cmd/state/internal/cmdtree/secrets.go +++ b/cmd/state/internal/cmdtree/secrets.go @@ -20,7 +20,6 @@ func newSecretsCommand(secretsClient *secretsapi.Client, prime *primer.Values) * locale.Tl("secrets_title", "Secrets"), locale.T("secrets_cmd_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "filter-usedby", @@ -55,7 +54,6 @@ func newSecretsGetCommand(prime *primer.Values) *captain.Command { locale.Tl("secrets_get_title", "Getting Secret"), locale.T("secrets_get_cmd_description"), prime.Output(), - prime.Config(), nil, []*captain.Argument{ { @@ -81,7 +79,6 @@ func newSecretsSetCommand(prime *primer.Values) *captain.Command { locale.Tl("secrets_set_title", "Setting Secret"), locale.T("secrets_set_cmd_description"), prime.Output(), - prime.Config(), nil, []*captain.Argument{ { @@ -111,7 +108,6 @@ func newSecretsSyncCommand(secretsClient *secretsapi.Client, prime *primer.Value locale.Tl("secrets_sync_title", "Synchronizing Secrets"), locale.T("secrets_sync_cmd_description"), prime.Output(), - prime.Config(), nil, nil, func(_ *captain.Command, _ []string) error { diff --git a/cmd/state/internal/cmdtree/shim.go b/cmd/state/internal/cmdtree/shim.go index fed5927677..c91b1a0cc3 100644 --- a/cmd/state/internal/cmdtree/shim.go +++ b/cmd/state/internal/cmdtree/shim.go @@ -19,7 +19,6 @@ func newShimCommand(prime *primer.Values, args ...string) *captain.Command { "", locale.T("shim_description"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "path", diff --git a/cmd/state/internal/cmdtree/show.go b/cmd/state/internal/cmdtree/show.go index 464ca65ed4..458a6fc556 100644 --- a/cmd/state/internal/cmdtree/show.go +++ b/cmd/state/internal/cmdtree/show.go @@ -17,7 +17,6 @@ func newShowCommand(prime *primer.Values) *captain.Command { locale.Tl("show_title", "Showing Project Details"), locale.T("show_project"), prime.Output(), - prime.Config(), nil, []*captain.Argument{ { diff --git a/cmd/state/internal/cmdtree/tutorial.go b/cmd/state/internal/cmdtree/tutorial.go index 9359d73242..d100c28c20 100644 --- a/cmd/state/internal/cmdtree/tutorial.go +++ b/cmd/state/internal/cmdtree/tutorial.go @@ -15,7 +15,6 @@ func newTutorialCommand(prime *primer.Values) *captain.Command { locale.Tl("tutorial_title", "Running Tutorial"), locale.Tl("tutorial_description", "Learn how to use the State Tool"), prime.Output(), - prime.Config(), nil, nil, func(ccmd *captain.Command, args []string) error { @@ -38,7 +37,6 @@ func newTutorialProjectCommand(prime *primer.Values) *captain.Command { locale.Tl("tutorial_new_project", `Running "New Project" Tutorial`), locale.Tl("tutorial_description", "Learn how to create new projects. (ie. virtual environments)"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "skip-intro", diff --git a/cmd/state/internal/cmdtree/update.go b/cmd/state/internal/cmdtree/update.go index 31a13d0ada..b0e05c6356 100644 --- a/cmd/state/internal/cmdtree/update.go +++ b/cmd/state/internal/cmdtree/update.go @@ -17,7 +17,6 @@ func newUpdateCommand(prime *primer.Values) *captain.Command { locale.Tl("update_title", "Updating The State Tool"), locale.Tl("update_description", "Updates the State Tool to the latest available version"), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "set-channel", @@ -44,7 +43,6 @@ func newUpdateLockCommand(prime *primer.Values) *captain.Command { locale.Tl("lock_title", "Lock the State Tool version"), locale.Tl("lock_description", "Lock the State Tool at the current version, this disables automatic updates."), prime.Output(), - prime.Config(), []*captain.Flag{ { Name: "set-channel", diff --git a/cmd/state/main.go b/cmd/state/main.go index 2f148f911d..aca65b6ff1 100644 --- a/cmd/state/main.go +++ b/cmd/state/main.go @@ -100,10 +100,7 @@ func run(args []string, isInteractive bool, out output.Outputer) (int, error) { verbose := os.Getenv("VERBOSE") != "" || argsHaveVerbose(args) logging.CurrentHandler().SetVerbose(verbose) - cfg, err := config.Get() - if err != nil { - return 1, locale.WrapError(err, "config_get_error", "Failed to load configuration.") - } + cfg := config.Get() logging.Debug("ConfigPath: %s", cfg.ConfigPath()) logging.Debug("CachePath: %s", cfg.CachePath()) @@ -134,7 +131,7 @@ func run(args []string, isInteractive bool, out output.Outputer) (int, error) { } // Forward call to specific state tool version, if warranted - forward, err := forwardFn(cfg.ConfigPath(), args, out, pj) + forward, err := forwardFn(args, out, pj) if err != nil { return 1, err } @@ -159,7 +156,7 @@ func run(args []string, isInteractive bool, out output.Outputer) (int, error) { project.RegisterExpander("secrets", project.NewSecretPromptingExpander(secretsapi.Get(), prompter)) // Run the actual command - cmds := cmdtree.New(primer.New(pj, out, auth, prompter, sshell, conditional, cfg), args...) + cmds := cmdtree.New(primer.New(pj, out, auth, prompter, sshell, conditional), args...) childCmd, err := cmds.Command().Find(args[1:]) if err != nil { diff --git a/internal/analytics/analytics.go b/internal/analytics/analytics.go index 126abeb4ad..aa17e534ce 100644 --- a/internal/analytics/analytics.go +++ b/internal/analytics/analytics.go @@ -150,19 +150,13 @@ func setup() { logging.SendToRollbarWhenReady("warning", fmt.Sprintf("Cannot detect the OS version: %v", err)) } - installSource := "unknown-due-to-config-error" - cfg, err := config.Get() - if err != nil { - installSource = cfg.InstallSource() - } - CustomDimensions = &customDimensions{ version: constants.Version, branchName: constants.BranchName, userID: userIDString, osName: osName, osVersion: osVersion, - installSource: installSource, + installSource: config.Get().InstallSource(), machineID: machineid.UniqID(), output: string(output.PlainFormatName), } @@ -208,15 +202,11 @@ func sendEventAndLog(category, action, label string, dimensions map[string]strin func sendEvent(category, action, label string, dimensions map[string]string) error { if deferAnalytics { - // TODO: figure out a way to pass configuration - cfg, err := config.Get() - if err != nil { - return locale.WrapError(err, "config_get_error") - } - if err := deferEvent(cfg, category, action, label, dimensions); err != nil { + if err := deferEvent(category, action, label, dimensions); err != nil { return locale.WrapError(err, "err_analytics_defer", "Could not defer event") } - if err := cfg.Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 + // TODO: figure out a way to pass configuration + if err := config.Get().Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 return locale.WrapError(err, "err_viper_write_defer", "Could not save configuration on defer") } } diff --git a/internal/analytics/deferred.go b/internal/analytics/deferred.go index 7545e4b05b..990a318f23 100644 --- a/internal/analytics/deferred.go +++ b/internal/analytics/deferred.go @@ -3,6 +3,7 @@ package analytics import ( "encoding/json" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/logging" @@ -19,7 +20,7 @@ type deferredData struct { const deferredCfgKey = "deferrer_analytics" -func SetDeferred(cfg Configurable, da bool) { +func SetDeferred(da bool) { deferAnalytics = da if deferAnalytics { return @@ -27,34 +28,28 @@ func SetDeferred(cfg Configurable, da bool) { eventWaitGroup.Add(1) go func() { defer eventWaitGroup.Done() - if err := sendDeferred(cfg, sendEvent); err != nil { + if err := sendDeferred(sendEvent); err != nil { logging.Errorf("Could not send deferred events: %v", err) } }() } -type Configurable interface { - Set(string, interface{}) - Save() error - GetString(string) string -} - -func deferEvent(cfg Configurable, category, action, label string, dimensions map[string]string) error { +func deferEvent(category, action, label string, dimensions map[string]string) error { logging.Debug("Deferring: %s, %s, %s", category, action, label) - deferred, err := loadDeferred(cfg) + deferred, err := loadDeferred() if err != nil { return errs.Wrap(err, "Could not load events on defer") } deferred = append(deferred, deferredData{category, action, label, dimensions}) - if err := saveDeferred(cfg, deferred); err != nil { + if err := saveDeferred(deferred); err != nil { return errs.Wrap(err, "Could not save event on defer") } return nil } -func sendDeferred(cfg Configurable, sender func(string, string, string, map[string]string) error) error { - deferred, err := loadDeferred(cfg) +func sendDeferred(sender func(string, string, string, map[string]string) error) error { + deferred, err := loadDeferred() if err != nil { return errs.Wrap(err, "Could not load events on send") } @@ -62,27 +57,27 @@ func sendDeferred(cfg Configurable, sender func(string, string, string, map[stri if err := sender(event.Category, event.Action, event.Label, event.Dimensions); err != nil { return errs.Wrap(err, "Could not send deferred event") } - if err := saveDeferred(cfg, deferred[n+1:]); err != nil { + if err := saveDeferred(deferred[n+1:]); err != nil { return errs.Wrap(err, "Could not save deferred event on send") } } - if err := cfg.Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 + if err := config.Get().Save(); err != nil { // the global viper instance is bugged, need to work around it for now -- https://www.pivotaltracker.com/story/show/175624789 return locale.WrapError(err, "err_viper_write_send_defer", "Could not save configuration on send deferred") } return nil } -func saveDeferred(cfg Configurable, v []deferredData) error { +func saveDeferred(v []deferredData) error { s, err := json.Marshal(v) if err != nil { return errs.New("Could not serialize deferred analytics: %v, error: %v", v, err) } - cfg.Set(deferredCfgKey, string(s)) + config.Get().Set(deferredCfgKey, string(s)) return nil } -func loadDeferred(cfg Configurable) ([]deferredData, error) { - v := cfg.GetString(deferredCfgKey) +func loadDeferred() ([]deferredData, error) { + v := config.Get().GetString(deferredCfgKey) d := []deferredData{} if v != "" { err := json.Unmarshal([]byte(v), &d) diff --git a/internal/captain/command.go b/internal/captain/command.go index 623f582264..01ac8f9be3 100644 --- a/internal/captain/command.go +++ b/internal/captain/command.go @@ -75,10 +75,9 @@ type Command struct { skipChecks bool out output.Outputer - cfg analytics.Configurable } -func NewCommand(name, title, description string, out output.Outputer, cfg analytics.Configurable, flags []*Flag, args []*Argument, execute ExecuteFunc) *Command { +func NewCommand(name, title, description string, out output.Outputer, flags []*Flag, args []*Argument, execute ExecuteFunc) *Command { // Validate args for idx, arg := range args { if idx > 0 && arg.Required && !args[idx-1].Required { @@ -97,7 +96,6 @@ func NewCommand(name, title, description string, out output.Outputer, cfg analyt flags: flags, commands: make([]*Command, 0), out: out, - cfg: cfg, } short := description @@ -401,7 +399,7 @@ func (c *Command) subCommandNames() []string { } func (c *Command) runner(cobraCmd *cobra.Command, args []string) error { - analytics.SetDeferred(c.cfg, c.deferAnalytics) + analytics.SetDeferred(c.deferAnalytics) outputFlag := cobraCmd.Flag("output") if outputFlag != nil && outputFlag.Changed { diff --git a/internal/config/instance.go b/internal/config/instance.go index 791d0f5933..aac763ade7 100644 --- a/internal/config/instance.go +++ b/internal/config/instance.go @@ -13,10 +13,11 @@ import ( "github.com/google/uuid" "github.com/shibukawa/configdir" "github.com/spf13/viper" + "github.com/thoas/go-funk" "github.com/ActiveState/cli/internal/condition" C "github.com/ActiveState/cli/internal/constants" - "github.com/ActiveState/cli/internal/errs" + "github.com/ActiveState/cli/internal/osutils/stacktrace" ) var defaultConfig *Instance @@ -29,39 +30,27 @@ type Instance struct { localPath string installSource string noSave bool + Exit func(code int) } -func new(localPath string) (*Instance, error) { +func new(localPath string) *Instance { instance := &Instance{ viper: viper.New(), localPath: localPath, + Exit: os.Exit, } - err := instance.Reload() - if err != nil { - return instance, errs.Wrap(err, "Failed to load configuration.") - } + instance.Reload() - return instance, nil + return instance } // Reload reloads the configuration data from the config file -func (i *Instance) Reload() error { - err := i.ensureConfigExists() - if err != nil { - return err - } - err = i.ensureCacheExists() - if err != nil { - return err - } - err = i.ReadInConfig() - if err != nil { - return err - } +func (i *Instance) Reload() { + i.ensureConfigExists() + i.ensureCacheExists() + i.ReadInConfig() i.readInstallSource() - - return nil } func configPathInTest() (string, error) { @@ -77,7 +66,7 @@ func configPathInTest() (string, error) { } // New creates a new config instance -func New() (*Instance, error) { +func New() *Instance { localPath := os.Getenv(C.ConfigEnvVarName) if condition.InTest() { @@ -93,20 +82,16 @@ func New() (*Instance, error) { } // NewWithDir creates a new instance at the given directory -func NewWithDir(dir string) (*Instance, error) { +func NewWithDir(dir string) *Instance { return new(dir) } // Get returns the default configuration instance -func Get() (*Instance, error) { +func Get() *Instance { if defaultConfig == nil { - var err error - defaultConfig, err = New() - if err != nil { - return defaultConfig, err - } + defaultConfig = New() } - return defaultConfig, nil + return defaultConfig } // Set sets a value at the given key @@ -194,7 +179,7 @@ func (i *Instance) InstallSource() string { } // ReadInConfig reads in config from the config file -func (i *Instance) ReadInConfig() error { +func (i *Instance) ReadInConfig() { // Prepare viper, which is a library that automates configuration // management between files, env vars and the CLI i.viper.SetConfigName(i.Name()) @@ -203,9 +188,8 @@ func (i *Instance) ReadInConfig() error { i.viper.AddConfigPath(".") if err := i.viper.ReadInConfig(); err != nil { - return errs.Wrap(err, "Cannot read config.") + i.exit("Can't read config: %s", err) } - return nil } // Save saves the config file @@ -226,7 +210,7 @@ func (i *Instance) SkipSave(b bool) { i.noSave = b } -func (i *Instance) ensureConfigExists() error { +func (i *Instance) ensureConfigExists() { // Prepare our config dir, eg. ~/.config/activestate/cli configDirs := configdir.New(i.Namespace(), i.AppName()) @@ -241,7 +225,7 @@ func (i *Instance) ensureConfigExists() error { i.localPath, err = ioutil.TempDir("", "cli-config-test") } if err != nil { - return errs.Wrap(err, "Cannot establish a config directory, HOME environment variable is not set and fallbacks have failed") + i.exit("Cannot establish a config directory, HOME environment variable is not set and fallbacks have failed") } } @@ -255,18 +239,17 @@ func (i *Instance) ensureConfigExists() error { if !i.configDir.Exists(i.Filename()) { configFile, err := i.configDir.Create(i.Filename()) if err != nil { - return errs.Wrap(err, "Cannot create config") + i.exit("Can't create config: %s", err) } err = configFile.Close() if err != nil { - return errs.Wrap(err, "Cannot close config file") + i.exit("Can't close config file: %s", err) } } - return nil } -func (i *Instance) ensureCacheExists() error { +func (i *Instance) ensureCacheExists() { // When running tests we use a unique cache dir that's located in a temp folder, to avoid collisions if condition.InTest() { path, err := tempDir("state-cache-tests") @@ -286,9 +269,16 @@ func (i *Instance) ensureCacheExists() error { i.cacheDir = configdir.New(i.Namespace(), "").QueryCacheFolder() } if err := i.cacheDir.MkdirAll(); err != nil { - return errs.Wrap(err, "Cannot create cache directory") + i.exit("Can't create cache directory: %s", err) + } +} + +func (i *Instance) exit(message string, a ...interface{}) { + fmt.Fprintf(os.Stderr, message, a...) + if funk.Contains(os.Args, "-v") || condition.InTest() { + fmt.Fprint(os.Stderr, stacktrace.Get().String()) } - return nil + i.Exit(1) } // tempDir returns a temp directory path at the topmost directory possible diff --git a/internal/deprecation/deprecation.go b/internal/deprecation/deprecation.go index 94e3594da9..095a78e6d4 100644 --- a/internal/deprecation/deprecation.go +++ b/internal/deprecation/deprecation.go @@ -50,7 +50,6 @@ type Checker struct { } type configable interface { - ConfigPath() string GetTime(key string) time.Time Set(key string, value interface{}) } @@ -60,7 +59,7 @@ func NewChecker(timeout time.Duration, configuration configable) *Checker { return &Checker{ timeout, configuration, - filepath.Join(configuration.ConfigPath(), "deprecation.json"), + filepath.Join(config.Get().ConfigPath(), "deprecation.json"), } } @@ -71,11 +70,7 @@ func Check() (*Info, error) { // CheckVersionNumber will run a Checker.Check with defaults func CheckVersionNumber(versionNumber string) (*Info, error) { - cfg, err := config.Get() - if err != nil { - return nil, errs.Wrap(err, "Could not load configuration required to check version number") - } - checker := NewChecker(DefaultTimeout, cfg) + checker := NewChecker(DefaultTimeout, config.Get()) return checker.check(versionNumber) } diff --git a/internal/events/cmdcall/cmdcall.go b/internal/events/cmdcall/cmdcall.go index 7d5a90c860..2eae2fb81e 100644 --- a/internal/events/cmdcall/cmdcall.go +++ b/internal/events/cmdcall/cmdcall.go @@ -16,7 +16,6 @@ type primeable interface { primer.Outputer primer.Projecter primer.Subsheller - primer.Configurer } // CmdCall manages dependencies for the handling of events triggered by command @@ -38,7 +37,7 @@ func New(p primeable, cmdList string) *CmdCall { subshell: p.Subshell(), cmdList: cmdList, p: p, - scriptrun: scriptrun.New(p.Output(), p.Subshell(), p.Project(), p.Config()), + scriptrun: scriptrun.New(p.Output(), p.Subshell(), p.Project()), } } diff --git a/internal/globaldefault/default.go b/internal/globaldefault/default.go index 9d701c0954..1237f201d4 100644 --- a/internal/globaldefault/default.go +++ b/internal/globaldefault/default.go @@ -11,6 +11,7 @@ import ( "github.com/gobuffalo/packr" "github.com/thoas/go-funk" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/exeutils" @@ -29,14 +30,13 @@ import ( const shimDenoter = "!DO NOT EDIT! State Tool Shim !DO NOT EDIT!" type DefaultConfigurer interface { - sscommon.Configurable + Set(key string, value interface{}) Save() error - CachePath() string } // BinDir returns the global binary directory -func BinDir(cfg DefaultConfigurer) string { - return filepath.Join(cfg.CachePath(), "bin") +func BinDir() string { + return filepath.Join(config.Get().CachePath(), "bin") } func isBinDirOnWindowsUserPath(binDir string) bool { @@ -57,9 +57,9 @@ func isBinDirOnWindowsUserPath(binDir string) bool { ) } -func Prepare(cfg DefaultConfigurer, subshell subshell.SubShell) error { +func Prepare(subshell subshell.SubShell) error { logging.Debug("Preparing globaldefault") - binDir := BinDir(cfg) + binDir := BinDir() // Don't run prepare if we're already on PATH path := strings.Split(os.Getenv("PATH"), string(os.PathListSeparator)) @@ -90,7 +90,7 @@ func Prepare(cfg DefaultConfigurer, subshell subshell.SubShell) error { "PATH": binDir, } - if err := subshell.WriteUserEnv(cfg, envUpdates, sscommon.Default, true); err != nil { + if err := subshell.WriteUserEnv(envUpdates, sscommon.Default, true); err != nil { return locale.WrapError(err, "err_globaldefault_update_env", "Could not write to user environment.") } @@ -125,7 +125,7 @@ func WarningForAdministrator(out output.Outputer) { // SetupDefaultActivation sets symlinks in the global bin directory to the currently activated runtime func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, runtime *runtime.Runtime, projectPath string) error { logging.Debug("Setting up globaldefault") - if err := Prepare(cfg, subshell); err != nil { + if err := Prepare(subshell); err != nil { return locale.WrapError(err, "err_globaldefault_prepare", "Could not prepare environment.") } @@ -140,7 +140,7 @@ func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, r } // roll back old symlinks - if err := cleanup(cfg); err != nil { + if err := cleanup(); err != nil { return locale.WrapError(err, "err_rollback_shim", "Could not clean up previous default installation.") } @@ -161,7 +161,7 @@ func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, r return locale.WrapError(err, "err_unique_exes", "Could not detect unique executables, make sure your PATH and PATHEXT environment variables are properly configured.") } - if err := createShims(exes, projectPath, cfg); err != nil { + if err := createShims(exes, projectPath); err != nil { return locale.WrapError(err, "err_createshims", "Could not create shim files to set up the default runtime environment.") } @@ -170,8 +170,8 @@ func SetupDefaultActivation(subshell subshell.SubShell, cfg DefaultConfigurer, r return nil } -func cleanup(cfg DefaultConfigurer) error { - binDir := BinDir(cfg) +func cleanup() error { + binDir := BinDir() if err := fileutils.MkdirUnlessExists(binDir); err != nil { return locale.WrapError(err, "err_globaldefault_mkdir", "Could not create bin directory: {{.V0}}.", binDir) } @@ -197,9 +197,9 @@ func cleanup(cfg DefaultConfigurer) error { return nil } -func createShims(exePaths []string, projectPath string, cfg DefaultConfigurer) error { +func createShims(exePaths []string, projectPath string) error { for _, exePath := range exePaths { - if err := createShim(exePath, projectPath, cfg); err != nil { + if err := createShim(exePath, projectPath); err != nil { return locale.WrapError(err, "err_createshim", "Could not create shim for {{.V0}}.", exePath) } } @@ -207,8 +207,8 @@ func createShims(exePaths []string, projectPath string, cfg DefaultConfigurer) e return nil } -func createShim(exePath, projectPath string, cfg DefaultConfigurer) error { - target := filepath.Clean(filepath.Join(BinDir(cfg), filepath.Base(exePath))) +func createShim(exePath, projectPath string) error { + target := filepath.Clean(filepath.Join(BinDir(), filepath.Base(exePath))) if rt.GOOS == "windows" { oldExt := filepath.Ext(target) target = target[0:len(target)-len(oldExt)] + ".bat" diff --git a/internal/keypairs/local.go b/internal/keypairs/local.go index f03f7d5494..2e31699a49 100644 --- a/internal/keypairs/local.go +++ b/internal/keypairs/local.go @@ -19,10 +19,7 @@ import ( // the user's file system; specifically from the config dir. It is assumed that // this keypair file has no passphrase, even if it is encrypted. func Load(keyName string) (Keypair, error) { - keyFilename, err := LocalKeyFilename(keyName) - if err != nil { - return nil, errs.Wrap(err, "Failed to get key file name to load.") - } + keyFilename := LocalKeyFilename(keyName) if err := validateKeyFile(keyFilename); err != nil { return nil, err } @@ -32,11 +29,7 @@ func Load(keyName string) (Keypair, error) { // Save will save the unencrypted and encoded private key to a local config // file. The filename will be the value of `keyName` and suffixed with `.key`. func Save(kp Keypair, keyName string) error { - keyFileName, err := LocalKeyFilename(keyName) - if err != nil { - return errs.Wrap(err, "Failed to get key file name to save.") - } - err = ioutil.WriteFile(keyFileName, []byte(kp.EncodePrivateKey()), 0600) + err := ioutil.WriteFile(LocalKeyFilename(keyName), []byte(kp.EncodePrivateKey()), 0600) if err != nil { return errs.Wrap(err, "WriteFile failed") } @@ -46,10 +39,7 @@ func Save(kp Keypair, keyName string) error { // Delete will delete an unencrypted and encoded private key from the local // config directory. The base filename (sans suffix) must be provided. func Delete(keyName string) error { - filename, err := LocalKeyFilename(keyName) - if err != nil { - return errs.Wrap(err, "Failed to get key file name to delete.") - } + filename := LocalKeyFilename(keyName) if fileutils.FileExists(filename) { if err := os.Remove(filename); err != nil { return errs.Wrap(err, "os.Remove %s failed", filename) @@ -102,12 +92,8 @@ func DeleteWithDefaults() error { } // LocalKeyFilename returns the full filepath for the given key name -func LocalKeyFilename(keyName string) (string, error) { - cfg, err := config.Get() - if err != nil { - return "", locale.WrapError(err, "config_get_err") - } - return filepath.Join(cfg.ConfigPath(), keyName+".key"), nil +func LocalKeyFilename(keyName string) string { + return filepath.Join(config.Get().ConfigPath(), keyName+".key") } func loadAndParseKeypair(keyFilename string) (Keypair, error) { diff --git a/internal/locale/locale.go b/internal/locale/locale.go index 2a2b275e43..30bf15e6a2 100644 --- a/internal/locale/locale.go +++ b/internal/locale/locale.go @@ -18,7 +18,6 @@ import ( "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/environment" - "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/logging" ) @@ -33,14 +32,7 @@ var exit = os.Exit func init() { logging.Debug("Init") - locale := getLocaleFlag() - cfg, err := config.Get() - if err == nil { - cfg.SetDefault("Locale", "en-US") - if locale == "" { - locale = cfg.GetString("Locale") - } - } + config.Get().SetDefault("Locale", "en-US") path := getLocalePath() box := packr.NewBox("../../locale") @@ -54,6 +46,11 @@ func init() { } }) + locale := getLocaleFlag() + if locale == "" { + locale = config.Get().GetString("Locale") + } + Set(locale) } @@ -91,21 +88,17 @@ func getLocaleFlag() string { } // Set the active language to the given locale -func Set(localeName string) error { +func Set(localeName string) { if !funk.Contains(Supported, localeName) { - return errs.New("Locale does not exist: %s", localeName) + fmt.Printf("Locale does not exist: %s\n", localeName) + exit(1) + return } translateFunction, _ = i18n.Tfunc(localeName) _ = translateFunction - cfg, err := config.Get() - if err != nil { - return errs.Wrap(err, "Could not get configuration to store updated locale") - } - cfg.Set("Locale", localeName) - - return nil + config.Get().Set("Locale", localeName) } // T aliases to i18n.Tfunc() diff --git a/internal/logging/defaults.go b/internal/logging/defaults.go index d4aaaa375c..e023e4fe9f 100644 --- a/internal/logging/defaults.go +++ b/internal/logging/defaults.go @@ -19,9 +19,6 @@ import ( "github.com/ActiveState/cli/internal/rtutils" ) -// datadir is the base directory at which the log is saved -var datadir string - // Logger describes a logging function, like Debug, Error, Warning, etc. type Logger func(msg string, args ...interface{}) @@ -69,16 +66,17 @@ func FileNameFor(pid int) string { } func FilePath() string { - return filepath.Join(datadir, FileName()) + return filepath.Join(config.Get().ConfigPath(), FileName()) } func FilePathFor(filename string) string { - return filepath.Join(datadir, filename) + return filepath.Join(config.Get().ConfigPath(), filename) } const FileNameSuffix = ".log" func (l *fileHandler) Emit(ctx *MessageContext, message string, args ...interface{}) error { + datadir := config.Get().ConfigPath() filename := filepath.Join(datadir, FileName()) // only log to rollbar when on release, beta or unstable branch and when built via CI (ie., non-local build) @@ -134,17 +132,8 @@ func init() { handler := &fileHandler{DefaultFormatter, nil, safeBool{}} SetHandler(handler) - cfg, err := config.Get() - if err != nil { - Error("Could not load configuration: %v", err) - } - if cfg == nil { - Error("Could not proceed setting up logging due to missing configuration.") - return - } - // Clean up old log files - datadir = cfg.ConfigPath() + datadir := config.Get().ConfigPath() files, err := ioutil.ReadDir(datadir) if err != nil { Error("Could not scan config dir to clean up stale logs: %v", err) diff --git a/internal/logging/rollbar.go b/internal/logging/rollbar.go index 864ef5da04..c1467a0e22 100644 --- a/internal/logging/rollbar.go +++ b/internal/logging/rollbar.go @@ -47,16 +47,8 @@ func SetupRollbar() { data["platform_os"] = runtime.GOOS }) - cfg, err := config.Get() - var installSource string - if err != nil { - // we will not log this to prevent recursion - installSource = "config-error" - } else { - installSource = cfg.InstallSource() - } rollbar.SetCustom(map[string]interface{}{ - "install_source": installSource, + "install_source": config.Get().InstallSource(), }) log.SetOutput(CurrentHandler().Output()) diff --git a/internal/machineid/machineid.go b/internal/machineid/machineid.go index eca7644268..e7368276d4 100644 --- a/internal/machineid/machineid.go +++ b/internal/machineid/machineid.go @@ -17,18 +17,12 @@ func uniqID(machineIDGetter func() (string, error), uuidGetter func() string) st return machID } - cfg, err := config.Get() - if err != nil { - // We do not log here, as it may create a recursion - return "11111111-1111-1111-1111-111111111111" - } - - machineID := cfg.GetString("machineID") + machineID := config.Get().GetString("machineID") if machineID != "" { return machineID } machineID = uuidGetter() - cfg.Set("machineID", machineID) + config.Get().Set("machineID", machineID) return machineID } diff --git a/internal/primer/primer.go b/internal/primer/primer.go index 3b911cf881..87c5712bf6 100644 --- a/internal/primer/primer.go +++ b/internal/primer/primer.go @@ -1,7 +1,6 @@ package primer import ( - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constraints" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/prompt" @@ -19,17 +18,15 @@ type Values struct { prompt prompt.Prompter subshell subshell.SubShell conditional *constraints.Conditional - config *config.Instance } -func New(project *project.Project, output output.Outputer, auth *authentication.Auth, prompt prompt.Prompter, subshell subshell.SubShell, conditional *constraints.Conditional, config *config.Instance) *Values { +func New(project *project.Project, output output.Outputer, auth *authentication.Auth, prompt prompt.Prompter, subshell subshell.SubShell, conditional *constraints.Conditional) *Values { v := &Values{ output: output, auth: auth, prompt: prompt, subshell: subshell, conditional: conditional, - config: config, } if project != nil { v.project = project @@ -58,10 +55,6 @@ type Prompter interface { Prompt() prompt.Prompter } -type Configurer interface { - Config() *config.Instance -} - type Subsheller interface { Subshell() subshell.SubShell } @@ -97,7 +90,3 @@ func (v *Values) Subshell() subshell.SubShell { func (v *Values) Conditional() *constraints.Conditional { return v.conditional } - -func (v *Values) Config() *config.Instance { - return v.config -} diff --git a/internal/process/process.go b/internal/process/process.go index 75839253fb..03349a1c3e 100644 --- a/internal/process/process.go +++ b/internal/process/process.go @@ -8,6 +8,7 @@ import ( "github.com/shirou/gopsutil/process" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" @@ -15,19 +16,15 @@ import ( "github.com/ActiveState/cli/internal/osutils" ) -type Configurable interface { - ConfigPath() string -} - // ActivationPID returns the process ID of the activated state; if any -func ActivationPID(cfg Configurable) int32 { +func ActivationPID() int32 { pid := int32(os.Getpid()) ppid := int32(os.Getppid()) procInfoErrMsgFmt := "Could not detect process information: %v" for pid != 0 && pid != ppid { - pidFileName := ActivationPIDFileName(cfg.ConfigPath(), int(pid)) + pidFileName := ActivationPIDFileName(int(pid)) if fileutils.FileExists(pidFileName) { return pid } @@ -74,9 +71,9 @@ func isActivateCmdlineArgs(args []string) bool { // ActivationPIDFileName returns a consistent file path based on the given // process id. -func ActivationPIDFileName(configpath string, n int) string { +func ActivationPIDFileName(n int) string { fileName := fmt.Sprintf("activation.%d", n) - return filepath.Join(configpath, fileName) + return filepath.Join(config.Get().ConfigPath(), fileName) } // Activation eases the use of a PidLock for the purpose of "marking" a process @@ -86,8 +83,8 @@ type Activation struct { } // NewActivation creates an instance of Activation. -func NewActivation(cfg Configurable, pid int) (*Activation, error) { - pidFileName := ActivationPIDFileName(cfg.ConfigPath(), pid) +func NewActivation(pid int) (*Activation, error) { + pidFileName := ActivationPIDFileName(pid) pidLock, err := osutils.NewPidLock(pidFileName) if err != nil { return nil, errs.Wrap(err, "cannot create new pid lock file") @@ -116,6 +113,6 @@ func (a *Activation) Close() error { // IsActivated returns whether or not this process is being run in an activated // state. This can be this specific process, or one of it's parents. -func IsActivated(cfg Configurable) bool { - return ActivationPID(cfg) != -1 +func IsActivated() bool { + return ActivationPID() != -1 } diff --git a/internal/runners/activate/activate.go b/internal/runners/activate/activate.go index 79629cb5b6..a6980aad6c 100644 --- a/internal/runners/activate/activate.go +++ b/internal/runners/activate/activate.go @@ -5,6 +5,7 @@ import ( "path/filepath" "github.com/ActiveState/cli/internal/analytics" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/globaldefault" @@ -30,7 +31,7 @@ type Activate struct { namespaceSelect *NamespaceSelect activateCheckout *Checkout out output.Outputer - config configurable + config configAble proj *project.Project subshell subshell.SubShell prompt prompt.Prompter @@ -49,15 +50,14 @@ type primeable interface { primer.Projecter primer.Subsheller primer.Prompter - primer.Configurer } func NewActivate(prime primeable) *Activate { return &Activate{ - NewNamespaceSelect(prime.Config(), prime), + NewNamespaceSelect(config.Get(), prime), NewCheckout(git.NewRepo(), prime), prime.Output(), - prime.Config(), + config.Get(), prime.Project(), prime.Subshell(), prime.Prompt(), @@ -73,7 +73,7 @@ func (r *Activate) run(params *ActivateParams) error { r.out.Notice(txtstyle.NewTitle(locale.T("info_activating_state"))) - alreadyActivated := process.IsActivated(r.config) + alreadyActivated := process.IsActivated() if alreadyActivated { if !params.Default { err := locale.NewInputError("err_already_activated", diff --git a/internal/runners/activate/activation.go b/internal/runners/activate/activation.go index ccb30b5bb6..34166d1616 100644 --- a/internal/runners/activate/activation.go +++ b/internal/runners/activate/activation.go @@ -57,11 +57,11 @@ func (r *Activate) activateAndWait(proj *project.Project, venv *virtualenvironme } r.subshell.SetEnv(ve) - if err := r.subshell.Activate(r.config, r.out); err != nil { + if err := r.subshell.Activate(r.out); err != nil { return locale.WrapError(err, "error_could_not_activate_subshell", "Could not activate a new subshell.") } - a, err := process.NewActivation(r.config, os.Getpid()) + a, err := process.NewActivation(os.Getpid()) if err != nil { return locale.WrapError(err, "error_could_not_mark_process", "Could not mark process as activated.") } diff --git a/internal/runners/activate/namespace.go b/internal/runners/activate/namespace.go index d539e7c44d..315e5f737c 100644 --- a/internal/runners/activate/namespace.go +++ b/internal/runners/activate/namespace.go @@ -18,26 +18,23 @@ import ( "github.com/ActiveState/cli/internal/locale" ) -type configurable interface { - Set(string, interface{}) - GetBool(string) bool - GetStringMap(string) map[string]interface{} - Save() error - CachePath() string - ConfigPath() string +type configAble interface { + Set(key string, value interface{}) + GetBool(key string) bool GetString(key string) string - GetStringSlice(key string) []string GetStringMapStringSlice(key string) map[string][]string + GetStringSlice(key string) []string AllKeys() []string + Save() error } // NamespaceSelect will select the right directory associated with a namespace, and chdir into it type NamespaceSelect struct { - config configurable + config configAble prompter prompt.Prompter } -func NewNamespaceSelect(config configurable, prime primeable) *NamespaceSelect { +func NewNamespaceSelect(config configAble, prime primeable) *NamespaceSelect { return &NamespaceSelect{config, prime.Prompt()} } diff --git a/internal/runners/clean/cache.go b/internal/runners/clean/cache.go index 56a746ae9a..90dcfaf733 100644 --- a/internal/runners/clean/cache.go +++ b/internal/runners/clean/cache.go @@ -19,7 +19,6 @@ type Cache struct { config project.ConfigAble confirm confirmAble path string - cfg *config.Instance } type CacheParams struct { @@ -28,15 +27,15 @@ type CacheParams struct { } func NewCache(prime primeable) *Cache { - return newCache(prime.Output(), prime.Config(), prime.Prompt()) + return newCache(prime.Output(), config.Get(), prime.Prompt()) } -func newCache(output output.Outputer, cfg *config.Instance, confirm confirmAble) *Cache { +func newCache(output output.Outputer, cfg project.ConfigAble, confirm confirmAble) *Cache { return &Cache{ output: output, config: cfg, confirm: confirm, - path: cfg.CachePath(), + path: config.Get().CachePath(), } } diff --git a/internal/runners/clean/config.go b/internal/runners/clean/config.go index 87fe7be030..31d10b993b 100644 --- a/internal/runners/clean/config.go +++ b/internal/runners/clean/config.go @@ -4,22 +4,17 @@ import ( "errors" "os" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/logging" "github.com/ActiveState/cli/internal/output" ) -type configurable interface { - ConfigPath() string - CachePath() string - SkipSave(bool) -} - type Config struct { output output.Outputer confirm confirmAble - cfg configurable + path string } type ConfigParams struct { @@ -27,14 +22,14 @@ type ConfigParams struct { } func NewConfig(prime primeable) *Config { - return newConfig(prime.Output(), prime.Prompt(), prime.Config()) + return newConfig(prime.Output(), prime.Prompt()) } -func newConfig(out output.Outputer, confirm confirmAble, cfg configurable) *Config { +func newConfig(out output.Outputer, confirm confirmAble) *Config { return &Config{ output: out, confirm: confirm, - cfg: cfg, + path: config.Get().ConfigPath(), } } @@ -53,6 +48,6 @@ func (c *Config) Run(params *ConfigParams) error { } } - logging.Debug("Removing config directory: %s", c.cfg.ConfigPath()) - return removeConfig(c.cfg) + logging.Debug("Removing config directory: %s", c.path) + return removeConfig(c.path) } diff --git a/internal/runners/clean/run.go b/internal/runners/clean/run.go index f617e6d8f6..eaefc4963e 100644 --- a/internal/runners/clean/run.go +++ b/internal/runners/clean/run.go @@ -7,7 +7,7 @@ import ( ) func (u *Uninstall) runUninstall() error { - err := removeCache(u.cfg.ConfigPath()) + err := removeCache(u.cachePath) if err != nil { return err } @@ -17,7 +17,7 @@ func (u *Uninstall) runUninstall() error { return err } - err = removeConfig(u.cfg) + err = removeConfig(u.configPath) if err != nil { return err } diff --git a/internal/runners/clean/run_lin_mac.go b/internal/runners/clean/run_lin_mac.go index f5f431b005..e0070da01a 100644 --- a/internal/runners/clean/run_lin_mac.go +++ b/internal/runners/clean/run_lin_mac.go @@ -5,11 +5,12 @@ package clean import ( "os" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/logging" ) -func removeConfig(cfg configurable) error { - cfg.SkipSave(true) +func removeConfig(configPath string) error { + config.Get().SkipSave(true) file, err := os.Open(logging.FilePath()) if err != nil { @@ -24,7 +25,7 @@ func removeConfig(cfg configurable) error { return err } - return os.RemoveAll(cfg.ConfigPath()) + return os.RemoveAll(configPath) } func removeInstall(installPath string) error { diff --git a/internal/runners/clean/run_win.go b/internal/runners/clean/run_win.go index e6b8f46708..d336b84655 100644 --- a/internal/runners/clean/run_win.go +++ b/internal/runners/clean/run_win.go @@ -8,13 +8,14 @@ import ( "github.com/gobuffalo/packr" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/language" "github.com/ActiveState/cli/internal/scriptfile" ) -func removeConfig(cfg configurable) error { - cfg.SkipSave(true) - return runScript("removeConfig", cfg.ConfigPath()) +func removeConfig(configPath string) error { + config.Get().SkipSave(true) + return runScript("removeConfig", configPath) } func removeInstall(installPath string) error { diff --git a/internal/runners/clean/uninstall.go b/internal/runners/clean/uninstall.go index 9dede2e17a..d6ab4380c9 100644 --- a/internal/runners/clean/uninstall.go +++ b/internal/runners/clean/uninstall.go @@ -4,6 +4,7 @@ import ( "errors" "os" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/output" @@ -17,7 +18,8 @@ type confirmAble interface { type Uninstall struct { out output.Outputer confirm confirmAble - cfg configurable + configPath string + cachePath string installPath string } @@ -28,24 +30,26 @@ type UninstallParams struct { type primeable interface { primer.Outputer primer.Prompter - primer.Configurer } func NewUninstall(prime primeable) (*Uninstall, error) { - return newUninstall(prime.Output(), prime.Prompt(), prime.Config()) + return newUninstall(prime.Output(), prime.Prompt()) } -func newUninstall(out output.Outputer, confirm confirmAble, cfg configurable) (*Uninstall, error) { +func newUninstall(out output.Outputer, confirm confirmAble) (*Uninstall, error) { installPath, err := os.Executable() if err != nil { return nil, err } + cfg := config.Get() + return &Uninstall{ out: out, confirm: confirm, installPath: installPath, - cfg: cfg, + configPath: cfg.ConfigPath(), + cachePath: cfg.CachePath(), }, nil } diff --git a/internal/runners/deploy/deploy.go b/internal/runners/deploy/deploy.go index 225a3f42b5..b4c5dbec4e 100644 --- a/internal/runners/deploy/deploy.go +++ b/internal/runners/deploy/deploy.go @@ -9,7 +9,6 @@ import ( "github.com/gobuffalo/packr" - "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/exeutils" "github.com/ActiveState/cli/internal/fileutils" @@ -46,7 +45,6 @@ type Deploy struct { output output.Outputer subshell subshell.SubShell step Step - cfg *config.Instance DefaultBranchForProjectName defaultBranchForProjectNameFunc NewRuntimeInstaller newInstallerFunc @@ -55,7 +53,6 @@ type Deploy struct { type primeable interface { primer.Outputer primer.Subsheller - primer.Configurer } func NewDeploy(step Step, prime primeable) *Deploy { @@ -63,7 +60,6 @@ func NewDeploy(step Step, prime primeable) *Deploy { prime.Output(), prime.Subshell(), step, - prime.Config(), model.DefaultBranchForProjectName, newInstaller, } @@ -88,7 +84,7 @@ func (d *Deploy) Run(params *Params) error { "Could not initialize an installer for {{.V0}}.", params.Namespace.String()) } - return runSteps(targetPath, params.Force, params.UserScope, params.Namespace, d.step, runtime, installer, d.output, d.cfg, d.subshell) + return runSteps(targetPath, params.Force, params.UserScope, params.Namespace, d.step, runtime, installer, d.output, d.subshell) } func (d *Deploy) createRuntimeInstaller(namespace project.Namespaced, targetPath string) (*runtime.Runtime, installable, error) { @@ -116,13 +112,13 @@ func (d *Deploy) createRuntimeInstaller(namespace project.Namespaced, targetPath return runtime, d.NewRuntimeInstaller(runtime), nil } -func runSteps(targetPath string, force bool, userScope bool, namespace project.Namespaced, step Step, runtime *runtime.Runtime, installer installable, out output.Outputer, cfg sscommon.Configurable, subshell subshell.SubShell) error { +func runSteps(targetPath string, force bool, userScope bool, namespace project.Namespaced, step Step, runtime *runtime.Runtime, installer installable, out output.Outputer, subshell subshell.SubShell) error { return runStepsWithFuncs( - targetPath, force, userScope, namespace, step, runtime, installer, out, cfg, subshell, + targetPath, force, userScope, namespace, step, runtime, installer, out, subshell, install, configure, symlink, report) } -func runStepsWithFuncs(targetPath string, force, userScope bool, namespace project.Namespaced, step Step, rt *runtime.Runtime, installer installable, out output.Outputer, cfg sscommon.Configurable, subshell subshell.SubShell, installf installFunc, configuref configureFunc, symlinkf symlinkFunc, reportf reportFunc) error { +func runStepsWithFuncs(targetPath string, force, userScope bool, namespace project.Namespaced, step Step, rt *runtime.Runtime, installer installable, out output.Outputer, subshell subshell.SubShell, installf installFunc, configuref configureFunc, symlinkf symlinkFunc, reportf reportFunc) error { logging.Debug("runSteps: %s", step.String()) var err error @@ -144,7 +140,7 @@ func runStepsWithFuncs(targetPath string, force, userScope bool, namespace proje } if step == UnsetStep || step == ConfigureStep { logging.Debug("Running configure step") - if err := configuref(targetPath, rt, cfg, out, subshell, namespace, userScope); err != nil { + if err := configuref(targetPath, rt, out, subshell, namespace, userScope); err != nil { return err } } @@ -189,9 +185,9 @@ func install(path string, installer installable, out output.Outputer) error { return nil } -type configureFunc func(installpath string, runtime *runtime.Runtime, cfg sscommon.Configurable, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error +type configureFunc func(installpath string, runtime *runtime.Runtime, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error -func configure(installpath string, runtime *runtime.Runtime, cfg sscommon.Configurable, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error { +func configure(installpath string, runtime *runtime.Runtime, out output.Outputer, sshell subshell.SubShell, namespace project.Namespaced, userScope bool) error { venv := virtualenvironment.New(runtime) env, err := venv.GetEnv(false, "") if err != nil { @@ -200,7 +196,7 @@ func configure(installpath string, runtime *runtime.Runtime, cfg sscommon.Config out.Notice(output.Heading(locale.Tr("deploy_configure_shell", sshell.Shell()))) - err = sshell.WriteUserEnv(cfg, env, sscommon.Deploy, userScope) + err = sshell.WriteUserEnv(env, sscommon.Deploy, userScope) if err != nil { return locale.WrapError(err, "err_deploy_subshell_write", "Could not write environment information to your shell configuration.") } @@ -365,7 +361,7 @@ func report(path string, runtime *runtime.Runtime, out output.Outputer) error { }) out.Notice(output.Heading(locale.T("deploy_restart"))) - + if rt.GOOS == "windows" { out.Notice(locale.Tr("deploy_restart_cmd", filepath.Join(path, "setenv.bat"))) } else { diff --git a/internal/runners/events/events.go b/internal/runners/events/events.go index 179215677d..1e1196f0f4 100644 --- a/internal/runners/events/events.go +++ b/internal/runners/events/events.go @@ -15,7 +15,6 @@ type Events struct { type primeable interface { primer.Projecter primer.Outputer - primer.Configurer } func New(prime primeable) *Events { diff --git a/internal/runners/events/log.go b/internal/runners/events/log.go index 2a54469bd2..e7f33a2cb6 100644 --- a/internal/runners/events/log.go +++ b/internal/runners/events/log.go @@ -13,7 +13,6 @@ import ( type EventLog struct { out output.Outputer - cfg process.Configurable } type EventLogParams struct { @@ -23,12 +22,11 @@ type EventLogParams struct { func NewLog(prime primeable) *EventLog { return &EventLog{ prime.Output(), - prime.Config(), } } func (e *EventLog) Run(params *EventLogParams) error { - pid := process.ActivationPID(e.cfg) + pid := process.ActivationPID() if pid == -1 { return locale.NewInputError("err_eventlog_pid", "Could not find parent process ID, make sure you're running this command from inside an activated state (run `state activate` first).") } diff --git a/internal/runners/export/config/config.go b/internal/runners/export/config/config.go index c785d89f5e..dbddfafa79 100644 --- a/internal/runners/export/config/config.go +++ b/internal/runners/export/config/config.go @@ -2,17 +2,13 @@ package config import ( "github.com/ActiveState/cli/internal/captain" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/primer" ) -type configurable interface { - ConfigPath() string -} - type Config struct { out output.Outputer - cfg configurable } type ConfigParams struct { @@ -21,16 +17,15 @@ type ConfigParams struct { type primeable interface { primer.Outputer - primer.Configurer } func New(prime primeable) *Config { - return &Config{prime.Output(), prime.Config()} + return &Config{prime.Output()} } func (c *Config) Run(cmd *captain.Command, params *ConfigParams) error { output := map[string]string{ - Dir.String(): c.cfg.ConfigPath(), + Dir.String(): config.Get().ConfigPath(), } filteredOutput := output diff --git a/internal/runners/export/privkey.go b/internal/runners/export/privkey.go index fc65227ba7..3eb0575306 100644 --- a/internal/runners/export/privkey.go +++ b/internal/runners/export/privkey.go @@ -2,7 +2,6 @@ package export import ( "github.com/ActiveState/cli/internal/constants" - "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" "github.com/ActiveState/cli/internal/keypairs" "github.com/ActiveState/cli/internal/locale" @@ -31,10 +30,7 @@ func (p *PrivateKey) Run(params *PrivateKeyParams) error { return locale.NewError("User") } - filepath, err := keypairs.LocalKeyFilename(constants.KeypairLocalFileName) - if err != nil { - return errs.Wrap(err, "Failed to get local key file name") - } + filepath := keypairs.LocalKeyFilename(constants.KeypairLocalFileName) contents, err := fileutils.ReadFile(filepath) if err != nil { return err diff --git a/internal/runners/prepare/prepare.go b/internal/runners/prepare/prepare.go index bb7709e80d..21dd4ab9db 100644 --- a/internal/runners/prepare/prepare.go +++ b/internal/runners/prepare/prepare.go @@ -18,14 +18,12 @@ import ( type primeable interface { primer.Outputer primer.Subsheller - primer.Configurer } // Prepare manages the prepare execution context. type Prepare struct { out output.Outputer subshell subshell.SubShell - cfg globaldefault.DefaultConfigurer } // New prepares a prepare execution context for use. @@ -33,7 +31,6 @@ func New(prime primeable) *Prepare { return &Prepare{ out: prime.Output(), subshell: prime.Subshell(), - cfg: prime.Config(), } } @@ -49,14 +46,14 @@ func (r *Prepare) Run() error { } } - if err := globaldefault.Prepare(r.cfg, r.subshell); err != nil { + if err := globaldefault.Prepare(r.subshell); err != nil { msgLocale := fmt.Sprintf("prepare_instructions_%s", runtime.GOOS) if runtime.GOOS != "linux" { - return locale.WrapError(err, msgLocale, globaldefault.BinDir(r.cfg)) + return locale.WrapError(err, msgLocale, globaldefault.BinDir()) } logging.Debug("Encountered failure attempting to update user environment: %s", err) r.out.Notice(output.Heading(locale.Tl("warning", "Warning"))) - r.out.Notice(locale.Tr(msgLocale, globaldefault.BinDir(r.cfg))) + r.out.Notice(locale.Tr(msgLocale, globaldefault.BinDir())) } return nil diff --git a/internal/runners/projects/projects.go b/internal/runners/projects/projects.go index d856a0ff2c..b6a0d47ed7 100644 --- a/internal/runners/projects/projects.go +++ b/internal/runners/projects/projects.go @@ -62,15 +62,14 @@ type Projects struct { type primeable interface { primer.Auther primer.Outputer - primer.Configurer } func NewParams() *Params { return &Params{Local: false} } -func NewProjects(prime primeable) *Projects { - return newProjects(prime.Auth(), prime.Output(), prime.Config()) +func NewProjects(prime primeable, config configGetter) *Projects { + return newProjects(prime.Auth(), prime.Output(), config) } func newProjects(auth *authentication.Auth, out output.Outputer, config configGetter) *Projects { diff --git a/internal/runners/projects/remote.go b/internal/runners/projects/remote.go index 3e4b5edec7..3413dd55ea 100644 --- a/internal/runners/projects/remote.go +++ b/internal/runners/projects/remote.go @@ -16,7 +16,7 @@ import ( // RunRemote runs the remote projects logic. func (r *Projects) RunRemote(params *Params) error { - projectfile.CleanProjectMapping(r.config) + projectfile.CleanProjectMapping() projectsList, err := r.fetchProjects(params.Local) if err != nil { diff --git a/internal/runners/pull/pull.go b/internal/runners/pull/pull.go index 3963d164d0..8e66d7aa95 100644 --- a/internal/runners/pull/pull.go +++ b/internal/runners/pull/pull.go @@ -22,7 +22,6 @@ type Pull struct { prompt prompt.Prompter project *project.Project out output.Outputer - cfg *config.Instance } type PullParams struct { @@ -34,7 +33,6 @@ type primeable interface { primer.Prompter primer.Projecter primer.Outputer - primer.Configurer } func New(prime primeable) *Pull { @@ -42,7 +40,6 @@ func New(prime primeable) *Pull { prime.Prompt(), prime.Project(), prime.Output(), - prime.Config(), } } @@ -119,7 +116,7 @@ func (p *Pull) Run(params *PullParams) error { return nil } - fname := path.Join(p.cfg.ConfigPath(), constants.UpdateHailFileName) + fname := path.Join(config.Get().ConfigPath(), constants.UpdateHailFileName) // must happen last in this function scope (defer if needed) if err := hail.Send(fname, []byte(actID)); err != nil { logging.Error("failed to send hail via %q: %s", fname, err) diff --git a/internal/runners/push/push.go b/internal/runners/push/push.go index f0c8864eea..4240f22ea6 100644 --- a/internal/runners/push/push.go +++ b/internal/runners/push/push.go @@ -32,11 +32,10 @@ type PushParams struct { type primeable interface { primer.Outputer primer.Projecter - primer.Configurer } -func NewPush(prime primeable) *Push { - return &Push{prime.Config(), prime.Output(), prime.Project()} +func NewPush(config configGetter, prime primeable) *Push { + return &Push{config, prime.Output(), prime.Project()} } func (r *Push) Run(params PushParams) error { diff --git a/internal/runners/run/run.go b/internal/runners/run/run.go index b9db999b05..0de32a635a 100644 --- a/internal/runners/run/run.go +++ b/internal/runners/run/run.go @@ -9,7 +9,6 @@ import ( "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/output/txtstyle" "github.com/ActiveState/cli/internal/primer" - "github.com/ActiveState/cli/internal/process" "github.com/ActiveState/cli/internal/scriptrun" "github.com/ActiveState/cli/internal/subshell" "github.com/ActiveState/cli/pkg/cmdlets/checker" @@ -22,14 +21,12 @@ type Run struct { out output.Outputer proj *project.Project subshell subshell.SubShell - cfg process.Configurable } type primeable interface { primer.Outputer primer.Projecter primer.Subsheller - primer.Configurer } // New constructs a new instance of Run. @@ -38,16 +35,15 @@ func New(prime primeable) *Run { prime.Output(), prime.Project(), prime.Subshell(), - prime.Config(), } } // Run runs the Run run runner. func (r *Run) Run(name string, args []string) error { - return run(r.out, r.subshell, r.proj, r.cfg, name, args) + return run(r.out, r.subshell, r.proj, name, args) } -func run(out output.Outputer, subs subshell.SubShell, proj *project.Project, cfg process.Configurable, name string, args []string) error { +func run(out output.Outputer, subs subshell.SubShell, proj *project.Project, name string, args []string) error { logging.Debug("Execute") if proj == nil { @@ -69,7 +65,7 @@ func run(out output.Outputer, subs subshell.SubShell, proj *project.Project, cfg return locale.NewInputError("error_state_run_unknown_name", "Script does not exist: {{.V0}}", name) } - scriptrunner := scriptrun.New(out, subs, proj, cfg) + scriptrunner := scriptrun.New(out, subs, proj) if !script.Standalone() && scriptrunner.NeedsActivation() { out.Notice(output.Heading(locale.Tl("notice", "Notice"))) out.Notice(locale.T("info_state_run_activating_state")) diff --git a/internal/runners/tutorial/tutorial.go b/internal/runners/tutorial/tutorial.go index 4374b85854..2ca2eced77 100644 --- a/internal/runners/tutorial/tutorial.go +++ b/internal/runners/tutorial/tutorial.go @@ -7,6 +7,7 @@ import ( "github.com/skratchdot/open-golang/open" "github.com/ActiveState/cli/internal/analytics" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/fileutils" "github.com/ActiveState/cli/internal/language" @@ -18,26 +19,20 @@ import ( "github.com/ActiveState/cli/pkg/platform/authentication" ) -type configurable interface { - Reload() error -} - type Tutorial struct { outputer output.Outputer auth *authentication.Auth prompt prompt.Prompter - cfg configurable } type primeable interface { primer.Outputer primer.Prompter primer.Auther - primer.Configurer } func New(primer primeable) *Tutorial { - return &Tutorial{primer.Output(), primer.Auth(), primer.Prompt(), primer.Config()} + return &Tutorial{primer.Output(), primer.Auth(), primer.Prompt()} } type NewProjectParams struct { @@ -170,10 +165,7 @@ func (t *Tutorial) authFlow() error { } // Reload authentication info - err = t.cfg.Reload() - if err != nil { - return locale.WrapError(err, "err_tutorial_cfg_reload", "Failed to reload configuration.") - } + config.Get().Reload() if err := t.auth.Authenticate(); err != nil { return locale.WrapError(err, "err_tutorial_auth", "Could not authenticate after invoking `state auth ..`.") diff --git a/internal/scriptrun/scriptrun.go b/internal/scriptrun/scriptrun.go index 24dc9b8dcd..eeb3ec0a2c 100644 --- a/internal/scriptrun/scriptrun.go +++ b/internal/scriptrun/scriptrun.go @@ -25,19 +25,17 @@ type ScriptRun struct { out output.Outputer sub subshell.SubShell project *project.Project - cfg process.Configurable venvPrepared bool venvExePath string } // New returns a pointer to a prepared instance of ScriptRun. -func New(out output.Outputer, subs subshell.SubShell, proj *project.Project, cfg process.Configurable) *ScriptRun { +func New(out output.Outputer, subs subshell.SubShell, proj *project.Project) *ScriptRun { return &ScriptRun{ out, subs, proj, - cfg, false, @@ -50,7 +48,7 @@ func New(out output.Outputer, subs subshell.SubShell, proj *project.Project, cfg // NeedsActivation indicates whether the underlying environment has been // prepared and activated. func (s *ScriptRun) NeedsActivation() bool { - return !process.IsActivated(s.cfg) && !s.venvPrepared + return !process.IsActivated() && !s.venvPrepared } // PrepareVirtualEnv sets up the relevant runtime and prepares the environment. diff --git a/internal/subshell/bash/bash.go b/internal/subshell/bash/bash.go index 9a54269b40..aa4ff0fa91 100644 --- a/internal/subshell/bash/bash.go +++ b/internal/subshell/bash/bash.go @@ -45,7 +45,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "HomeDir failed") @@ -77,10 +77,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { +func (v *SubShell) Activate(out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("bashrc.sh", "", env, out, cfg); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("bashrc.sh", "", env, out); err != nil { return err } diff --git a/internal/subshell/cmd/cmd.go b/internal/subshell/cmd/cmd.go index 7f3489ad3b..70d0bae727 100644 --- a/internal/subshell/cmd/cmd.go +++ b/internal/subshell/cmd/cmd.go @@ -5,6 +5,7 @@ import ( "os/exec" "path/filepath" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/fileutils" "github.com/ActiveState/cli/internal/osutils" "github.com/ActiveState/cli/internal/output" @@ -44,11 +45,11 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, userScope bool) error { +func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, userScope bool) error { cmdEnv := NewCmdEnv(userScope) // Clean up old entries - oldEnv := cfg.GetStringMap(envType.Key) + oldEnv := config.Get().GetStringMap(envType.Key) for k, v := range oldEnv { if err := cmdEnv.unset(k, v.(string)); err != nil { return err @@ -56,7 +57,7 @@ func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string } // Store new entries - cfg.Set(envType.Key, env) + config.Get().Set(envType.Key, env) for k, v := range env { value := v @@ -105,10 +106,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { +func (v *SubShell) Activate(out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("config.bat", ".bat", env, out, cfg); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("config.bat", ".bat", env, out); err != nil { return err } diff --git a/internal/subshell/fish/fish.go b/internal/subshell/fish/fish.go index b7620be5ab..fba65d9cca 100644 --- a/internal/subshell/fish/fish.go +++ b/internal/subshell/fish/fish.go @@ -46,7 +46,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "HomeDir failed") @@ -78,10 +78,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { +func (v *SubShell) Activate(out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("fishrc.fish", "", env, out, cfg); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("fishrc.fish", "", env, out); err != nil { return err } diff --git a/internal/subshell/sscommon/rcfile.go b/internal/subshell/sscommon/rcfile.go index f2ad8e5e1d..28424c6c0c 100644 --- a/internal/subshell/sscommon/rcfile.go +++ b/internal/subshell/sscommon/rcfile.go @@ -14,6 +14,7 @@ import ( "github.com/mash/go-tempfile-suffix" "github.com/ActiveState/cli/internal/colorize" + "github.com/ActiveState/cli/internal/config" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" @@ -38,13 +39,6 @@ var ( } ) -// Configurable defines an interface to store and get configuration data -type Configurable interface { - Set(string, interface{}) - GetBool(string) bool - GetStringMap(string) map[string]interface{} -} - type EnvData struct { Start string Stop string @@ -162,7 +156,7 @@ func SetupShellRcFile(rcFileName, templateName string, env map[string]string, na // SetupProjectRcFile creates a temporary RC file that our shell is initiated from, this allows us to template the logic // used for initialising the subshell -func SetupProjectRcFile(templateName, ext string, env map[string]string, out output.Outputer, cfg Configurable) (*os.File, error) { +func SetupProjectRcFile(templateName, ext string, env map[string]string, out output.Outputer) (*os.File, error) { box := packr.NewBox("../../../assets/shells") tpl := box.String(templateName) prj := project.Get() @@ -177,14 +171,14 @@ func SetupProjectRcFile(templateName, ext string, env map[string]string, out out return nil, errs.Wrap(err, "Misc failure") } - if strings.ToLower(event.Name()) == "first-activate" && !cfg.GetBool(activatedKey) { + if strings.ToLower(event.Name()) == "first-activate" && !config.Get().GetBool(activatedKey) { userScripts = v + "\n" + userScripts } if strings.ToLower(event.Name()) == "activate" { userScripts = userScripts + "\n" + v } } - cfg.Set(activatedKey, true) + config.Get().Set(activatedKey, true) inuse := []string{} scripts := map[string]string{} diff --git a/internal/subshell/subshell.go b/internal/subshell/subshell.go index b0135efcdb..b2ca5d0f1e 100644 --- a/internal/subshell/subshell.go +++ b/internal/subshell/subshell.go @@ -25,7 +25,7 @@ import ( // under the same directory as this file type SubShell interface { // Activate the given subshell - Activate(cfg sscommon.Configurable, out output.Outputer) error + Activate(out output.Outputer) error // Errors returns a channel to receive errors Errors() <-chan error @@ -46,7 +46,7 @@ type SubShell interface { SetBinary(string) // WriteUserEnv writes the given env map to the users environment - WriteUserEnv(sscommon.Configurable, map[string]string, sscommon.EnvData, bool) error + WriteUserEnv(map[string]string, sscommon.EnvData, bool) error // SetupShellRcFile writes a script or source-able file that updates the environment variables and sets the prompt SetupShellRcFile(string, map[string]string, project.Namespaced) error @@ -64,7 +64,7 @@ type SubShell interface { Quote(value string) string } -// New returns the subshell relevant to the current process, but does not activate it +// Get returns the subshell relevant to the current process, but does not activate it func New() SubShell { binary := os.Getenv("SHELL") if binary == "" { diff --git a/internal/subshell/tcsh/tcsh.go b/internal/subshell/tcsh/tcsh.go index 8a3267bacd..3dc003276e 100644 --- a/internal/subshell/tcsh/tcsh.go +++ b/internal/subshell/tcsh/tcsh.go @@ -45,7 +45,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "IO failure") @@ -77,7 +77,7 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { +func (v *SubShell) Activate(out output.Outputer) error { // This is horrible but it works. tcsh doesn't offer a way to override the rc file and // doesn't let us run a script and then drop to interactive mode. So we source the // state rc file and then chain an exec which inherits the environment we just set up. @@ -88,7 +88,7 @@ func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) erro // hack to make it work. env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("tcsh.sh", "", env, out, cfg); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("tcsh.sh", "", env, out); err != nil { return err } diff --git a/internal/subshell/zsh/zsh.go b/internal/subshell/zsh/zsh.go index 0fd66aebe1..273aa3f6c5 100644 --- a/internal/subshell/zsh/zsh.go +++ b/internal/subshell/zsh/zsh.go @@ -50,7 +50,7 @@ func (v *SubShell) SetBinary(binary string) { } // WriteUserEnv - see subshell.SubShell -func (v *SubShell) WriteUserEnv(cfg sscommon.Configurable, env map[string]string, envType sscommon.EnvData, _ bool) error { +func (v *SubShell) WriteUserEnv(env map[string]string, envType sscommon.EnvData, _ bool) error { homeDir, err := fileutils.HomeDir() if err != nil { return errs.Wrap(err, "IO failure") @@ -82,10 +82,10 @@ func (v *SubShell) Quote(value string) string { } // Activate - see subshell.SubShell -func (v *SubShell) Activate(cfg sscommon.Configurable, out output.Outputer) error { +func (v *SubShell) Activate(out output.Outputer) error { env := sscommon.EscapeEnv(v.env) var err error - if v.rcFile, err = sscommon.SetupProjectRcFile("zshrc.sh", "", env, out, cfg); err != nil { + if v.rcFile, err = sscommon.SetupProjectRcFile("zshrc.sh", "", env, out); err != nil { return err } diff --git a/locale/en-us.yaml b/locale/en-us.yaml index 40a72b6291..eac7707e67 100644 --- a/locale/en-us.yaml +++ b/locale/en-us.yaml @@ -1631,5 +1631,3 @@ bundle_ingredient_alternatives_more: other: " - .. (to see more results run `state bundles search {{.V0}}`)" err_lock_version_invalid: other: "The locked version '{{.V0}}' could not be verified, are you sure it's valid?" -config_get_error: - other: Failed to read configuration. diff --git a/pkg/cmdlets/auth/signup.go b/pkg/cmdlets/auth/signup.go index 78de098fdd..54c4ebd2a2 100644 --- a/pkg/cmdlets/auth/signup.go +++ b/pkg/cmdlets/auth/signup.go @@ -88,12 +88,7 @@ func downloadTOS() (string, error) { } defer resp.Body.Close() - cfg, err := config.Get() - if err != nil { - return "", errs.Wrap(err, "Could not get configuration required to store ToS document.") - } - - tosPath := filepath.Join(cfg.ConfigPath(), "platform_tos.txt") + tosPath := filepath.Join(config.Get().ConfigPath(), "platform_tos.txt") tosFile, err := os.Create(tosPath) if err != nil { return "", errs.Wrap(err, "Could not create Terms Of Service file in configuration directory.") diff --git a/pkg/platform/authentication/auth.go b/pkg/platform/authentication/auth.go index 0f7db05cd3..b6dc33c16a 100644 --- a/pkg/platform/authentication/auth.go +++ b/pkg/platform/authentication/auth.go @@ -38,32 +38,19 @@ type Auth struct { clientAuth *runtime.ClientAuthInfoWriter bearerToken string user *mono_models.User - cfg Configurable -} - -type Configurable interface { - Set(string, interface{}) - GetString(string) string } // Get returns a cached version of Auth func Get() *Auth { if persist == nil { - cfg, err := config.Get() - if err != nil { - // TODO: We need to get rid of this Get() function altogether... - logging.Error("Could not get configuration required by auth: %v", err) - os.Exit(1) - } - persist = New(cfg) + persist = New() } return persist } // Client is a shortcut for calling Client() on the persisted auth func Client() *mono_client.Mono { - a := Get() - return a.Client() + return Get().Client() } // ClientAuth is a shortcut for calling ClientAuth() on the persisted auth @@ -83,12 +70,10 @@ func Logout() { } // New creates a new version of Auth -func New(cfg Configurable) *Auth { - auth := &Auth{ - cfg: cfg, - } +func New() *Auth { + auth := &Auth{} - if availableAPIToken(cfg) != "" { + if availableAPIToken() != "" { logging.Debug("Authenticating with stored API token") auth.Authenticate() } @@ -129,7 +114,7 @@ func (s *Auth) Authenticate() error { return nil } - apiToken := availableAPIToken(s.cfg) + apiToken := availableAPIToken() if apiToken == "" { return locale.NewInputError("err_no_credentials") } @@ -164,7 +149,7 @@ func (s *Auth) AuthenticateWithModel(credentials *mono_models.Credentials) error s.clientAuth = &clientAuth if credentials.Token != "" { - s.cfg.Set("apiToken", credentials.Token) + config.Get().Set("apiToken", credentials.Token) } else { if err := s.CreateToken(); err != nil { return errs.Wrap(err, "CreateToken failed") @@ -216,7 +201,7 @@ func (s *Auth) UserID() *strfmt.UUID { // Logout will destroy any session tokens and reset the current Auth instance func (s *Auth) Logout() { - s.cfg.Set("apiToken", "") + config.Get().Set("apiToken", "") s.client = nil s.clientAuth = nil s.bearerToken = "" @@ -278,7 +263,7 @@ func (s *Auth) CreateToken() error { return err } - s.cfg.Set("apiToken", token) + config.Get().Set("apiToken", token) return nil } @@ -301,7 +286,7 @@ func (s *Auth) NewAPIKey(name string) (string, error) { return tokenOK.Payload.Token, nil } -func availableAPIToken(cfg Configurable) string { +func availableAPIToken() string { tkn, err := gcloud.GetSecret(constants.APIKeyEnvVarName) if err != nil && !errors.Is(err, gcloud.ErrNotAvailable{}) { logging.Error("Could not retrieve gcloud secret: %v", err) @@ -315,5 +300,5 @@ func availableAPIToken(cfg Configurable) string { logging.Debug("Using API token passed via env var") return tkn } - return cfg.GetString("apiToken") + return config.Get().GetString("apiToken") } diff --git a/pkg/platform/runtime/runtime.go b/pkg/platform/runtime/runtime.go index b9e53cd96c..7c7d8410ae 100644 --- a/pkg/platform/runtime/runtime.go +++ b/pkg/platform/runtime/runtime.go @@ -35,11 +35,7 @@ func NewRuntime(projectDir string, commitID strfmt.UUID, owner string, projectNa logging.Debug("In NewRuntime: resolved project dir is: %s", resolvedProjectDir) } - cfg, err := config.Get() - if err != nil { - return nil, locale.WrapError(err, "config_get_err") - } - installPath := filepath.Join(cfg.CachePath(), hash.ShortHash(resolvedProjectDir)) + installPath := filepath.Join(config.Get().CachePath(), hash.ShortHash(resolvedProjectDir)) return &Runtime{ runtimeDir: installPath, commitID: commitID, diff --git a/pkg/projectfile/projectfile.go b/pkg/projectfile/projectfile.go index fa12df1211..5c89a9f7e1 100644 --- a/pkg/projectfile/projectfile.go +++ b/pkg/projectfile/projectfile.go @@ -482,13 +482,8 @@ func Parse(configFilepath string) (*Project, error) { return nil, errs.Wrap(err, "project.Init failed") } - cfg, err := config.Get() - if err != nil { - return nil, errs.Wrap(err, "Could not read configuration required by projectfile parser.") - } - namespace := fmt.Sprintf("%s/%s", project.parsedURL.Owner, project.parsedURL.Name) - storeProjectMapping(cfg, namespace, filepath.Dir(project.Path())) + storeProjectMapping(namespace, filepath.Dir(project.Path())) return project, nil } @@ -714,12 +709,7 @@ func (p *Project) save(path string) error { return errs.Wrap(err, "f.Write %s failed", path) } - cfg, err := config.Get() - if err != nil { - return errs.Wrap(err, "Could not read configuration required to save project file") - } - - storeProjectMapping(cfg, fmt.Sprintf("%s/%s", p.parsedURL.Owner, p.parsedURL.Name), filepath.Dir(p.Path())) + storeProjectMapping(fmt.Sprintf("%s/%s", p.parsedURL.Owner, p.parsedURL.Name), filepath.Dir(p.Path())) return nil } @@ -862,11 +852,7 @@ func getProjectFilePathFromWd() (string, error) { } func getProjectFilePathFromDefault() (string, error) { - cfg, err := config.Get() - if err != nil { - return "", errs.Wrap(err, "Could not read configuration required to determine default project") - } - defaultProjectPath := cfg.GetString(constants.GlobalDefaultPrefname) + defaultProjectPath := config.Get().GetString(constants.GlobalDefaultPrefname) if defaultProjectPath == "" { return "", nil } @@ -1211,7 +1197,7 @@ type ConfigGetter interface { func GetProjectMapping(config ConfigGetter) map[string][]string { addDeprecatedProjectMappings(config) - CleanProjectMapping(config) + CleanProjectMapping() projects := config.GetStringMapStringSlice(LocalProjectsConfigKey) if projects == nil { return map[string][]string{} @@ -1276,13 +1262,13 @@ func GetProjectPaths(config ConfigGetter, namespace string) []string { // storeProjectMapping associates the namespace with the project // path in the config -func storeProjectMapping(cfg ConfigGetter, namespace, projectPath string) { +func storeProjectMapping(namespace, projectPath string) { projectMapMutex.Lock() defer projectMapMutex.Unlock() projectPath = filepath.Clean(projectPath) - projects := cfg.GetStringMapStringSlice(LocalProjectsConfigKey) + projects := config.Get().GetStringMapStringSlice(LocalProjectsConfigKey) if projects == nil { projects = make(map[string][]string) } @@ -1297,13 +1283,13 @@ func storeProjectMapping(cfg ConfigGetter, namespace, projectPath string) { } projects[namespace] = paths - cfg.Set(LocalProjectsConfigKey, projects) + config.Get().Set(LocalProjectsConfigKey, projects) } // CleanProjectMapping removes projects that no longer exist // on a user's filesystem from the projects config entry -func CleanProjectMapping(cfg ConfigGetter) { - projects := cfg.GetStringMapStringSlice(LocalProjectsConfigKey) +func CleanProjectMapping() { + projects := config.Get().GetStringMapStringSlice(LocalProjectsConfigKey) seen := map[string]bool{} for namespace, paths := range projects { @@ -1319,5 +1305,5 @@ func CleanProjectMapping(cfg ConfigGetter) { seen[strings.ToLower(namespace)] = true } - cfg.Set("projects", projects) + config.Get().Set("projects", projects) }