Skip to content

Commit 12bf404

Browse files
psergeeLeonidVas
authored andcommitted
rocks: consider environment for some paths
Rocks local repository path and tarantool installation prefix path can be specified using environment variables. TT_CLI_REPO_ROCKS variable is used if it is set and there is no repo.rocks in tt config or repo.rocks directory does not include repository manifest. TT_CLI_TARANTOOL_PREFIX variable is used for build, rocks commands if it is set and tarantool executable is found in PATH. Closes #471
1 parent 38d61a5 commit 12bf404

File tree

8 files changed

+294
-163
lines changed

8 files changed

+294
-163
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2121

2222
- smart auto-completion for `tt start`, `tt stop`, `tt restart`, `tt connect`, `tt build`, `tt clean`, `tt logrotate`, `tt status`.
2323
It shows suitable apps, in case of the pattern doesn't contain delimiter `:`, and suitable instances otherwise.
24+
- support tt environment directories overriding using environment variables:
25+
* TT_CLI_REPO_ROCKS environment variable value is used as rocks repository path if it is set and
26+
there is no tt.repo.rocks in tt configuration file or tt.repo.rocks directory does not include
27+
repository manifest file.
28+
* TT_CLI_TARANTOOL_PREFIX environment variable value is used for as tarantool installation prefix
29+
directory for rocks commands if it is set and tarantool executable is found in PATH.
2430

2531
## [1.1.0] - 2023-05-02
2632

cli/cmdcontext/cmdcontext.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ type CliCtx struct {
3030
TarantoolExecutable string
3131
// Tarantool version.
3232
TarantoolVersion string
33-
// Tarantool install prefix path.
34-
TarantoolInstallPrefix string
35-
// Path to header files supplied with tarantool.
36-
TarantoolIncludeDir string
3733
// The flag determines if the tarantool binary is from the internal tt repository.
3834
IsTarantoolBinFromRepo bool
3935
// Verbose logging flag. Enables debug log output.

cli/rocks/rocks.go

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import (
44
"embed"
55
"fmt"
66
"os"
7+
"os/exec"
78
"path/filepath"
9+
"regexp"
810
"strings"
911

12+
"github.com/apex/log"
1013
"github.com/tarantool/tt/cli/cmdcontext"
1114
"github.com/tarantool/tt/cli/config"
1215
"github.com/tarantool/tt/cli/util"
@@ -17,6 +20,12 @@ import (
1720
//go:embed third_party/luarocks/src/*
1821
var luarocks embed.FS
1922

23+
const (
24+
rocksRepoManifestName = "manifest"
25+
repoRocksPathEnvVarName = "TT_CLI_REPO_ROCKS"
26+
tarantoolPrefixEnvVarName = "TT_CLI_TARANTOOL_PREFIX"
27+
)
28+
2029
// addLuarocksRepoOpts adds --server option to luarocks command line if rocks repository
2130
// info is specified in tt config. Return updated args slice.
2231
func addLuarocksRepoOpts(cliOpts *config.CliOpts, args []string) ([]string, error) {
@@ -35,6 +44,57 @@ func addLuarocksRepoOpts(cliOpts *config.CliOpts, args []string) ([]string, erro
3544
return args, nil
3645
}
3746

47+
// getRocksRepoPath returns actual rocks repo path: either from passed path argument or
48+
// from current environment.
49+
func getRocksRepoPath(rocksRepoPath string) string {
50+
rockRepoPathFromEnv := os.Getenv(repoRocksPathEnvVarName)
51+
if rocksRepoPath == "" || (rocksRepoPath != "" &&
52+
!util.IsRegularFile(filepath.Join(rocksRepoPath, rocksRepoManifestName))) {
53+
if rockRepoPathFromEnv != "" {
54+
rocksRepoPath = rockRepoPathFromEnv
55+
}
56+
}
57+
return rocksRepoPath
58+
}
59+
60+
// GetTarantoolPrefix returns tarantool installation prefix.
61+
func GetTarantoolPrefix(cli *cmdcontext.CliCtx, cliOpts *config.CliOpts) (string, error) {
62+
if cli.IsTarantoolBinFromRepo {
63+
prefixDir, err := util.JoinAbspath(cliOpts.App.IncludeDir)
64+
if err != nil {
65+
return "", err
66+
}
67+
68+
log.Debugf("Tarantool prefix path: %q", prefixDir)
69+
return prefixDir, nil
70+
}
71+
72+
if prefixPathFromEnv := os.Getenv(tarantoolPrefixEnvVarName); prefixPathFromEnv != "" {
73+
log.Debugf("Tarantool prefix path: %q", prefixPathFromEnv)
74+
return prefixPathFromEnv, nil
75+
}
76+
77+
output, err := exec.Command(cli.TarantoolExecutable, "--version").Output()
78+
if err != nil {
79+
return "", fmt.Errorf("failed to get tarantool version: %s", err)
80+
}
81+
82+
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
83+
if len(lines) < 3 {
84+
return "", fmt.Errorf("failed to get prefix path: expected more data")
85+
}
86+
87+
re := regexp.MustCompile(`^.*\s-DCMAKE_INSTALL_PREFIX=(?P<prefix>\/.*)\s.*$`)
88+
matches := util.FindNamedMatches(re, lines[2])
89+
if len(matches) == 0 {
90+
return "", fmt.Errorf("failed to get prefix path: regexp does not match")
91+
}
92+
93+
prefixDir := matches["prefix"]
94+
log.Debugf("Tarantool prefix path: %q", prefixDir)
95+
return prefixDir, nil
96+
}
97+
3898
// Execute LuaRocks command. All args will be processed by LuaRocks.
3999
func Exec(cmdCtx *cmdcontext.CmdCtx, cliOpts *config.CliOpts, args []string) error {
40100
var cmd string
@@ -44,6 +104,8 @@ func Exec(cmdCtx *cmdcontext.CmdCtx, cliOpts *config.CliOpts, args []string) err
44104
cmd = "help"
45105
}
46106

107+
cliOpts.Repo.Rocks = getRocksRepoPath(cliOpts.Repo.Rocks)
108+
47109
var err error
48110
if args, err = addLuarocksRepoOpts(cliOpts, args); err != nil {
49111
return err
@@ -61,16 +123,19 @@ func Exec(cmdCtx *cmdcontext.CmdCtx, cliOpts *config.CliOpts, args []string) err
61123
if err != nil {
62124
return err
63125
}
64-
65-
err = util.SetupTarantoolPrefix(&cmdCtx.Cli, cliOpts)
126+
tarantoolPrefixDir, err := GetTarantoolPrefix(&cmdCtx.Cli, cliOpts)
127+
if err != nil {
128+
return err
129+
}
130+
tarantoolIncludeDir, err := util.JoinAbspath(tarantoolPrefixDir, "include", "tarantool")
66131
if err != nil {
67132
return err
68133
}
69134

70135
os.Setenv("TT_CLI_TARANTOOL_VERSION", version)
71-
os.Setenv("TT_CLI_TARANTOOL_PREFIX", cmdCtx.Cli.TarantoolInstallPrefix)
72-
os.Setenv("TT_CLI_TARANTOOL_INCLUDE", cmdCtx.Cli.TarantoolIncludeDir)
73-
os.Setenv("TARANTOOL_DIR", filepath.Dir(cmdCtx.Cli.TarantoolIncludeDir))
136+
os.Setenv("TT_CLI_TARANTOOL_PREFIX", tarantoolPrefixDir)
137+
os.Setenv("TT_CLI_TARANTOOL_INCLUDE", tarantoolIncludeDir)
138+
os.Setenv("TARANTOOL_DIR", filepath.Dir(tarantoolIncludeDir))
74139
os.Setenv("TT_CLI_TARANTOOL_PATH", filepath.Dir(cmdCtx.Cli.TarantoolExecutable))
75140

76141
rocks_cmd := fmt.Sprintf("t=require('extra.wrapper').exec('%s', %s)",

cli/rocks/rocks_test.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package rocks
22

33
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
47
"testing"
58

9+
"github.com/stretchr/testify/assert"
610
"github.com/stretchr/testify/require"
11+
"github.com/tarantool/tt/cli/cmdcontext"
712
"github.com/tarantool/tt/cli/config"
813
)
914

@@ -82,3 +87,136 @@ func TestAddLuarocksRepoOpts(t *testing.T) {
8287
})
8388
}
8489
}
90+
91+
func TestGetRocksRepoPath(t *testing.T) {
92+
assert.EqualValues(t, "./testdata/repo", getRocksRepoPath("./testdata/repo"))
93+
assert.EqualValues(t, "./testdata/emptyrepo", getRocksRepoPath("./testdata/emptyrepo"))
94+
95+
os.Setenv(repoRocksPathEnvVarName, "./other_repo")
96+
// If env var is set, return it if manifets is missing in passed repo.
97+
assert.EqualValues(t, "./other_repo", getRocksRepoPath("./testdata/emptyrepo"))
98+
// Return passed repo path, since manifest exists. Env var is ignored.
99+
assert.EqualValues(t, "./testdata/repo", getRocksRepoPath("./testdata/repo"))
100+
os.Unsetenv(repoRocksPathEnvVarName)
101+
}
102+
103+
func TestSetupTarantoolPrefix(t *testing.T) {
104+
type prefixInput struct {
105+
cli cmdcontext.CliCtx
106+
cliOpts *config.CliOpts
107+
data *[]byte
108+
tntPrefixEnv string
109+
}
110+
111+
type prefixOutput struct {
112+
prefix string
113+
err error
114+
}
115+
116+
assert := assert.New(t)
117+
testDir, err := ioutil.TempDir("/tmp", "tt-unit")
118+
require.NoError(t, err)
119+
120+
defer os.RemoveAll(testDir)
121+
122+
err = os.Mkdir(testDir+"/bin", os.ModePerm)
123+
require.NoError(t, err)
124+
125+
tntBinPath := testDir + "/bin/tarantool"
126+
127+
cwd, err := os.Getwd()
128+
require.NoError(t, err)
129+
130+
testCases := make(map[prefixInput]prefixOutput)
131+
132+
tntOkData := []byte("#!/bin/sh\n" +
133+
"echo 'Tarantool 2.10.2-0-gb924f0b\n" +
134+
"Target: Linux-x86_64-RelWithDebInfo\n" +
135+
"Build options: cmake . -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_BACKTRACE=yes'")
136+
137+
testCases[prefixInput{cli: cmdcontext.CliCtx{
138+
IsTarantoolBinFromRepo: false,
139+
TarantoolExecutable: tntBinPath,
140+
}, data: &tntOkData}] =
141+
prefixOutput{
142+
prefix: "/usr",
143+
err: nil,
144+
}
145+
146+
testCases[prefixInput{cli: cmdcontext.CliCtx{
147+
IsTarantoolBinFromRepo: false,
148+
TarantoolExecutable: tntBinPath,
149+
},
150+
data: &tntOkData,
151+
tntPrefixEnv: "/tnt/prefix"}] =
152+
prefixOutput{
153+
prefix: "/tnt/prefix",
154+
err: nil,
155+
}
156+
157+
tntBadData0 := []byte("#!/bin/sh\n" +
158+
"echo 'Tarantool 2.10.2-0-gb924f0b\n" +
159+
"Target: Linux-x86_64-RelWithDebInfo\n" +
160+
"Build options: cmake . -D_FAIL_HERE_=/usr -DENABLE_BACKTRACE=yes'")
161+
162+
testCases[prefixInput{cli: cmdcontext.CliCtx{
163+
IsTarantoolBinFromRepo: false,
164+
TarantoolExecutable: tntBinPath,
165+
}, data: &tntBadData0}] =
166+
prefixOutput{
167+
err: fmt.Errorf("failed to get prefix path: regexp does not match"),
168+
}
169+
170+
tntBadData1 := []byte("#!/bin/sh\n" +
171+
"echo 'Tarantool 2.10.2-0-gb924f0b\n" +
172+
"Target: Linux-x86_64-RelWithDebInfo\n'")
173+
174+
testCases[prefixInput{cli: cmdcontext.CliCtx{
175+
IsTarantoolBinFromRepo: false,
176+
TarantoolExecutable: tntBinPath,
177+
}, data: &tntBadData1}] =
178+
prefixOutput{
179+
err: fmt.Errorf("failed to get prefix path: expected more data"),
180+
}
181+
182+
appOpts := config.AppOpts{IncludeDir: "hdr"}
183+
cliOpts := config.CliOpts{App: &appOpts}
184+
185+
testCases[prefixInput{cli: cmdcontext.CliCtx{
186+
IsTarantoolBinFromRepo: true,
187+
TarantoolExecutable: tntBinPath,
188+
},
189+
cliOpts: &cliOpts,
190+
data: &tntOkData,
191+
tntPrefixEnv: "/tnt/prefix"}] =
192+
prefixOutput{
193+
prefix: cwd + "/hdr",
194+
err: nil,
195+
}
196+
197+
for input, output := range testCases {
198+
tntFile, err := os.Create(tntBinPath)
199+
require.NoError(t, err)
200+
201+
_, err = tntFile.Write(*input.data)
202+
require.NoError(t, err)
203+
tntFile.Close()
204+
205+
err = os.Chmod(tntFile.Name(), 0755)
206+
require.NoError(t, err)
207+
208+
if input.tntPrefixEnv != "" {
209+
os.Setenv(tarantoolPrefixEnvVarName, input.tntPrefixEnv)
210+
}
211+
tarantoolPrefix, err := GetTarantoolPrefix(&input.cli, input.cliOpts)
212+
os.Unsetenv(tarantoolPrefixEnvVarName)
213+
if err == nil {
214+
assert.Nil(err)
215+
assert.Equal(output.prefix, tarantoolPrefix)
216+
} else {
217+
assert.Equal(output.err, err)
218+
}
219+
220+
os.Remove(tntBinPath)
221+
}
222+
}

cli/rocks/testdata/repo/manifest

Whitespace-only changes.

cli/util/util.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/apex/log"
2525
"github.com/spf13/cobra"
2626
"github.com/tarantool/tt/cli/cmdcontext"
27-
"github.com/tarantool/tt/cli/config"
2827
"gopkg.in/yaml.v2"
2928
)
3029

@@ -301,51 +300,6 @@ func GetTarantoolVersion(cli *cmdcontext.CliCtx) (string, error) {
301300
return cli.TarantoolVersion, nil
302301
}
303302

304-
// SetupTarantoolPrefix defines the installation prefix and the path to the tarantool header files.
305-
func SetupTarantoolPrefix(cli *cmdcontext.CliCtx, cliOpts *config.CliOpts) error {
306-
if cli.TarantoolIncludeDir != "" && cli.TarantoolInstallPrefix != "" {
307-
return nil
308-
}
309-
310-
if cli.IsTarantoolBinFromRepo {
311-
includeDir, err := JoinAbspath(cliOpts.App.IncludeDir, "include/tarantool")
312-
if err != nil {
313-
return err
314-
}
315-
316-
prefix, err := JoinAbspath(cliOpts.App.IncludeDir)
317-
if err != nil {
318-
return err
319-
}
320-
321-
cli.TarantoolIncludeDir = includeDir
322-
cli.TarantoolInstallPrefix = prefix
323-
324-
return nil
325-
}
326-
327-
output, err := exec.Command(cli.TarantoolExecutable, "--version").Output()
328-
if err != nil {
329-
return fmt.Errorf("failed to get tarantool version: %s", err)
330-
}
331-
332-
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
333-
if len(lines) < 3 {
334-
return fmt.Errorf("failed to get prefix path: expected more data")
335-
}
336-
337-
re := regexp.MustCompile(`^.*\s-DCMAKE_INSTALL_PREFIX=(?P<prefix>\/.*)\s.*$`)
338-
matches := FindNamedMatches(re, lines[2])
339-
if len(matches) == 0 {
340-
return fmt.Errorf("failed to get prefix path: regexp does not match")
341-
}
342-
343-
cli.TarantoolInstallPrefix = matches["prefix"]
344-
cli.TarantoolIncludeDir = cli.TarantoolInstallPrefix + "/include/tarantool"
345-
346-
return nil
347-
}
348-
349303
// ReadEmbedFile reads content of embed file in string mode.
350304
func ReadEmbedFile(fs embed.FS, path string) (string, error) {
351305
content, err := ReadEmbedFileBinary(fs, path)

0 commit comments

Comments
 (0)