diff --git a/CHANGELOG.md b/CHANGELOG.md index 2070a2637..955bb8211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added +- `tt pack `: added TCM file packaging. + ### Changed ### Fixed diff --git a/cli/cmdcontext/cmdcontext.go b/cli/cmdcontext/cmdcontext.go index 044f4d7c9..9016ce2bd 100644 --- a/cli/cmdcontext/cmdcontext.go +++ b/cli/cmdcontext/cmdcontext.go @@ -30,6 +30,12 @@ type TarantoolCli struct { version version.Version } +// TcmCli describes tarantool executable. +type TcmCli struct { + // Executable is a path to tcm executable. + Executable string +} + // GetVersion returns and caches the tarantool version. func (tntCli *TarantoolCli) GetVersion() (version.Version, error) { if tntCli.version.Str != "" { @@ -104,6 +110,8 @@ type CliCtx struct { Verbose bool // TarantoolCli is current tarantool cli. TarantoolCli TarantoolCli + // Tcmcli is current tcm cli. + TcmCli TcmCli // IntegrityCheck is a public key used for integrity check. IntegrityCheck string // IntegrityCheckPeriod is an period during which the integrity check is reproduced. diff --git a/cli/configure/configure.go b/cli/configure/configure.go index 57d4c6236..3d54f08d3 100644 --- a/cli/configure/configure.go +++ b/cli/configure/configure.go @@ -422,6 +422,9 @@ func Cli(cmdCtx *cmdcontext.CmdCtx) error { // Set default (system) tarantool binary, can be replaced by "local" or "system" later. cmdCtx.Cli.TarantoolCli.Executable, _ = exec.LookPath("tarantool") + // Set default (system) tcm binary, can be replaced by "local" or "system" later. + cmdCtx.Cli.TcmCli.Executable, _ = exec.LookPath("tcm") + switch { case cmdCtx.Cli.IsSystem: return configureSystemCli(cmdCtx) @@ -552,6 +555,29 @@ func detectLocalTt(cliOpts *config.CliOpts) (string, error) { return localCli, nil } +// detectLocalTcm searches for available Tcm executable. +func detectLocalTcm(cmdCtx *cmdcontext.CmdCtx, cliOpts *config.CliOpts) (string, error) { + localTcm, err := util.JoinAbspath(cliOpts.Env.BinDir, "tcm") + if err != nil { + return "", err + } + + if _, err := os.Stat(localTcm); err == nil { + if _, err := exec.LookPath(localTcm); err != nil { + return "", fmt.Errorf(`found TCM binary %q isn't executable: %s`, + localTcm, err) + } + + cmdCtx.Cli.TcmCli.Executable = localTcm + } else if !os.IsNotExist(err) { + return "", fmt.Errorf("failed to get access to TCM binary file: %s", err) + } + + log.Debugf("tcm executable found: %q", cmdCtx.Cli.TcmCli.Executable) + + return localTcm, nil +} + // configureLocalCli configures Tarantool CLI if the launch is local. func configureLocalCli(cmdCtx *cmdcontext.CmdCtx) error { launchDir, err := os.Getwd() @@ -595,6 +621,11 @@ func configureLocalCli(cmdCtx *cmdcontext.CmdCtx) error { return err } + _, err = detectLocalTcm(cmdCtx, cliOpts) + if err != nil { + return err + } + var localCli string if !cmdCtx.Cli.IsSelfExec { localCli, err = detectLocalTt(cliOpts) diff --git a/cli/pack/common.go b/cli/pack/common.go index 6d726ef38..390bb5e3a 100644 --- a/cli/pack/common.go +++ b/cli/pack/common.go @@ -266,6 +266,18 @@ func copyBinaries(bundleEnvPath string, packCtx *PackCtx, cmdCtx *cmdcontext.Cmd if err := util.CopyFileDeep(ttExecutable, util.JoinPaths(pkgBin, "tt")); err != nil { return fmt.Errorf("failed copying tt: %s", err) } + + // Copy tcm. + if packCtx.WithBinaries { + if cmdCtx.Cli.TcmCli.Executable == "" { + log.Warnf("Skip copying tcm binary: not found") + } else { + if err := util.CopyFileDeep(cmdCtx.Cli.TcmCli.Executable, + util.JoinPaths(pkgBin, "tcm")); err != nil { + return fmt.Errorf("failed copying tcm: %s", err) + } + } + } return nil } diff --git a/test/integration/pack/test_bundles/bundle4/bin/tcm_bin b/test/integration/pack/test_bundles/bundle4/bin/tcm_bin new file mode 100644 index 000000000..e69de29bb diff --git a/test/integration/pack/test_pack.py b/test/integration/pack/test_pack.py index b6c00fd93..bba754919 100644 --- a/test/integration/pack/test_pack.py +++ b/test/integration/pack/test_pack.py @@ -1014,8 +1014,11 @@ def test_pack_tgz_links_to_binaries(tt_cmd, tmp_path): tt_is_link = os.path.islink(os.path.join(extract_path, "bin", "tt")) tnt_is_link = os.path.islink(os.path.join(extract_path, "bin", "tarantool")) + tcm_is_link = os.path.islink(os.path.join(extract_path, "bin", "tcm")) + assert not tt_is_link assert not tnt_is_link + assert not tcm_is_link shutil.rmtree(extract_path) os.remove(package_file)