From b2d1358c50cf16d62b70c5d62a388bac75062a71 Mon Sep 17 00:00:00 2001 From: better0fdead Date: Mon, 30 Oct 2023 18:08:11 +0300 Subject: [PATCH] tt: add env module Added module that adds 'tt' and 'tarantool' (installed using 'tt') to the current environment. Closes #338 --- CHANGELOG.md | 4 ++++ README.md | 12 +++++++++++ cli/cmd/env.go | 34 ++++++++++++++++++++++++++++++++ cli/cmd/root.go | 1 + cli/env/env.go | 23 +++++++++++++++++++++ cli/env/env_test.go | 18 +++++++++++++++++ test/integration/env/test_env.py | 32 ++++++++++++++++++++++++++++++ 7 files changed, 124 insertions(+) create mode 100644 cli/cmd/env.go create mode 100644 cli/env/env.go create mode 100644 cli/env/env_test.go create mode 100644 test/integration/env/test_env.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e11224d6..c7f49f74b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Make cartridge app dependencies less strict. +### Added + +- `tt env`: add current environment binaries location to the PATH variable. + ## [2.0.0] - 2023-11-13 ### Changed diff --git a/README.md b/README.md index 26bf3410b..fa77bff03 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Tarantool-based applications. * [Working with application templates](#Working-with-application-templates) * [Working with tt daemon (experimental)](#working-with-tt-daemon-experimental) * [Setting Tarantool configuration parameters via environment variables](#setting-tarantool-configuration-parameters-via-environment-variables) + * [Add current environment binaries location to the PATH variable](#add-current-environment-binaries-location-to-the-path-variable) * [Migration from older TT versions](doc/migration_from_older_versions.md) * [Commands](#commands) @@ -578,6 +579,16 @@ support it. The name of a variable should have the following pattern: [box.cfg](https://www.tarantool.io/en/doc/latest/reference/configuration/#box-cfg-params-ref) parameter. +### Add current environment binaries location to the PATH variable. + +You can add current environment binaries location to the PATH variable: + +``` console +. <(tt env) +``` + +Also TARANTOOL_DIR variable is set. + ## Commands Common description. For a detailed description, use `tt help command` . @@ -611,6 +622,7 @@ Common description. For a detailed description, use `tt help command` . - `instances` - show enabled applications. - `binaries` - show a list of installed binaries and their versions. - `cluster` - manage cluster configuration. +- `env` - add current environment binaries location to the PATH variable. [godoc-badge]: https://pkg.go.dev/badge/github.com/tarantool/tt.svg [godoc-url]: https://pkg.go.dev/github.com/tarantool/tt diff --git a/cli/cmd/env.go b/cli/cmd/env.go new file mode 100644 index 000000000..b7a70da96 --- /dev/null +++ b/cli/cmd/env.go @@ -0,0 +1,34 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/tarantool/tt/cli/cmdcontext" + "github.com/tarantool/tt/cli/env" + "github.com/tarantool/tt/cli/modules" +) + +// NewEnvCmd creates env command. +func NewEnvCmd() *cobra.Command { + var envCmd = &cobra.Command{ + Use: "env", + Short: "Add current environment binaries location to the PATH variable", + Long: "Add current environment binaries location to the PATH variable.\n" + + "Also sets TARANTOOL_DIR variable.", + Run: func(cmd *cobra.Command, args []string) { + err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, + internalEnvModule, args) + handleCmdErr(cmd, err) + }, + } + + return envCmd +} + +// internalEnvModule is a default env module. +func internalEnvModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { + var err error + _, err = fmt.Print(env.CreateEnvString(cliOpts)) + return err +} diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 5ee4569e8..5cbdd9aca 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -163,6 +163,7 @@ func NewCmdRoot() *cobra.Command { NewCfgCmd(), NewInstancesCmd(), NewBinariesCmd(), + NewEnvCmd(), ) if err := injectCmds(rootCmd); err != nil { panic(err.Error()) diff --git a/cli/env/env.go b/cli/env/env.go new file mode 100644 index 000000000..e571047bd --- /dev/null +++ b/cli/env/env.go @@ -0,0 +1,23 @@ +package env + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/tarantool/tt/cli/config" +) + +// CreateEnvString generates environment variables for 'tarantool' and 'tt' installed using 'tt'. +func CreateEnvString(cliOpts *config.CliOpts) string { + binDir := cliOpts.Env.BinDir + path := os.Getenv("PATH") + if !strings.Contains(path, binDir) { + path = binDir + ":" + path + } + + tarantoolDir := filepath.Join(cliOpts.Env.IncludeDir, "include") + + return fmt.Sprintf("export %s=%s\nexport %s=%s\n", "PATH", path, "TARANTOOL_DIR", tarantoolDir) +} diff --git a/cli/env/env_test.go b/cli/env/env_test.go new file mode 100644 index 000000000..377640392 --- /dev/null +++ b/cli/env/env_test.go @@ -0,0 +1,18 @@ +package env + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tarantool/tt/cli/configure" +) + +func Test_CreateEnvString(t *testing.T) { + cliOpts := configure.GetDefaultCliOpts() + cliOpts.Env.BinDir = "foo/bin/" + cliOpts.Env.IncludeDir = "bar/include/" + assert.Contains(t, CreateEnvString(cliOpts), + "\nexport TARANTOOL_DIR=bar/include/include\n") + assert.Contains(t, CreateEnvString(cliOpts), + "export PATH=foo/bin/:") +} diff --git a/test/integration/env/test_env.py b/test/integration/env/test_env.py new file mode 100644 index 000000000..c2d579e6d --- /dev/null +++ b/test/integration/env/test_env.py @@ -0,0 +1,32 @@ +import os +import re +import subprocess + +from utils import config_name + + +def test_env_output(tt_cmd, tmpdir): + configPath = os.path.join(tmpdir, config_name) + # Create test config + with open(configPath, 'w') as f: + f.write('env:\n bin_dir:\n inc_dir:\n') + binDir = str(tmpdir + "/bin") + tarantoolDir = "TARANTOOL_DIR=" + str(tmpdir + "/include/include") + + env_cmd = [tt_cmd, "env"] + instance_process = subprocess.Popen( + env_cmd, + cwd=tmpdir, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + text=True + ) + + # Check that the process shutdowned correctly. + instance_process_rc = instance_process.wait() + assert instance_process_rc == 0 + + # Check output + output = instance_process.stdout.read() + assert re.search(tarantoolDir, output) + assert re.search(binDir, output)