From 133a275d9bef7d8a930ee7d5a80a29437cff9c13 Mon Sep 17 00:00:00 2001 From: nexustar Date: Fri, 10 Dec 2021 17:52:00 +0800 Subject: [PATCH 1/3] cmd: add link and unlink --- cmd/link.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 2 ++ cmd/unlink.go | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 cmd/link.go create mode 100644 cmd/unlink.go diff --git a/cmd/link.go b/cmd/link.go new file mode 100644 index 0000000000..9551321016 --- /dev/null +++ b/cmd/link.go @@ -0,0 +1,53 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/pingcap/tiup/pkg/environment" + "github.com/spf13/cobra" +) + +func newLinkCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "link [:version]", + Short: "Link component binary to $PATH", + Long: `[experimental feature] +Link component binary to $PATH`, + RunE: func(cmd *cobra.Command, args []string) error { + teleCommand = cmd.CommandPath() + env := environment.GlobalEnv() + if len(args) != 1 { + return cmd.Help() + } + component, version := environment.ParseCompVersion(args[0]) + if version == "" { + var err error + version, err = env.SelectInstalledVersion(component, version) + if err != nil { + return err + } + } + binPath, _ := env.BinaryPath(component, version) + target := filepath.Join(env.LocalPath("bin"), filepath.Base(binPath)) + fmt.Printf("package %s provides these executables: %s\n", component, filepath.Base(binPath)) + _ = os.Remove(target) + return os.Symlink(binPath, target) + }, + } + return cmd +} diff --git a/cmd/root.go b/cmd/root.go index abd7edfd52..173c645c31 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -225,6 +225,8 @@ the latest stable version will be downloaded from the repository.`, newTelemetryCmd(), newEnvCmd(), newHistoryCmd(), + newLinkCmd(), + newUnlinkCmd(), ) } diff --git a/cmd/unlink.go b/cmd/unlink.go new file mode 100644 index 0000000000..0c9ff26397 --- /dev/null +++ b/cmd/unlink.go @@ -0,0 +1,42 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "os" + "path/filepath" + + "github.com/pingcap/tiup/pkg/environment" + "github.com/spf13/cobra" +) + +func newUnlinkCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "unlink ", + Short: "Unlink component binary to $PATH", + Long: `[experimental feature] +Unlink component binary in $PATH`, + RunE: func(cmd *cobra.Command, args []string) error { + teleCommand = cmd.CommandPath() + env := environment.GlobalEnv() + if len(args) != 1 { + return cmd.Help() + } + component, _ := environment.ParseCompVersion(args[0]) + target := filepath.Join(env.LocalPath("bin"), component) + return os.Remove(target) + }, + } + return cmd +} From 4043ee7dabcdb85c76fde5a83b45c44bc06ff69e Mon Sep 17 00:00:00 2001 From: nexustar Date: Fri, 25 Aug 2023 02:41:39 +0800 Subject: [PATCH 2/3] allow install tiup as other component --- pkg/environment/env.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/environment/env.go b/pkg/environment/env.go index 4bb55dd368..14814669f8 100644 --- a/pkg/environment/env.go +++ b/pkg/environment/env.go @@ -143,9 +143,6 @@ func (env *Environment) UpdateComponents(specs []string, nightly, force bool) er var v1specs []repository.ComponentSpec for _, spec := range specs { component, v := ParseCompVersion(spec) - if component == tiupName { - continue - } if v == "" && nightly { v = utils.NightlyVersionAlias } From 12d9930fb89510c2caf17a8882c2f96713777f7e Mon Sep 17 00:00:00 2001 From: nexustar Date: Fri, 25 Aug 2023 22:23:18 +0800 Subject: [PATCH 3/3] fix --- cmd/link.go | 22 +++----------------- cmd/unlink.go | 21 ++++++++++++++----- pkg/environment/env.go | 47 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/cmd/link.go b/cmd/link.go index 9551321016..f54b462433 100644 --- a/cmd/link.go +++ b/cmd/link.go @@ -14,10 +14,6 @@ package cmd import ( - "fmt" - "os" - "path/filepath" - "github.com/pingcap/tiup/pkg/environment" "github.com/spf13/cobra" ) @@ -25,9 +21,8 @@ import ( func newLinkCmd() *cobra.Command { cmd := &cobra.Command{ Use: "link [:version]", - Short: "Link component binary to $PATH", - Long: `[experimental feature] -Link component binary to $PATH`, + Short: "Link component binary to $TIUP_HOME/bin/", + Long: `[experimental] Link component binary to $TIUP_HOME/bin/`, RunE: func(cmd *cobra.Command, args []string) error { teleCommand = cmd.CommandPath() env := environment.GlobalEnv() @@ -35,18 +30,7 @@ Link component binary to $PATH`, return cmd.Help() } component, version := environment.ParseCompVersion(args[0]) - if version == "" { - var err error - version, err = env.SelectInstalledVersion(component, version) - if err != nil { - return err - } - } - binPath, _ := env.BinaryPath(component, version) - target := filepath.Join(env.LocalPath("bin"), filepath.Base(binPath)) - fmt.Printf("package %s provides these executables: %s\n", component, filepath.Base(binPath)) - _ = os.Remove(target) - return os.Symlink(binPath, target) + return env.Link(component, version) }, } return cmd diff --git a/cmd/unlink.go b/cmd/unlink.go index 0c9ff26397..d31c74b4cb 100644 --- a/cmd/unlink.go +++ b/cmd/unlink.go @@ -18,23 +18,34 @@ import ( "path/filepath" "github.com/pingcap/tiup/pkg/environment" + "github.com/pingcap/tiup/pkg/tui" "github.com/spf13/cobra" ) func newUnlinkCmd() *cobra.Command { cmd := &cobra.Command{ Use: "unlink ", - Short: "Unlink component binary to $PATH", - Long: `[experimental feature] -Unlink component binary in $PATH`, + Short: "Unlink component binary to $TIUP_HOME/bin/", + Long: `[experimental] Unlink component binary in $TIUP_HOME/bin/`, RunE: func(cmd *cobra.Command, args []string) error { teleCommand = cmd.CommandPath() env := environment.GlobalEnv() if len(args) != 1 { return cmd.Help() } - component, _ := environment.ParseCompVersion(args[0]) - target := filepath.Join(env.LocalPath("bin"), component) + component, version := environment.ParseCompVersion(args[0]) + version, err := env.SelectInstalledVersion(component, version) + if err != nil { + return err + } + binPath, err := env.BinaryPath(component, version) + if err != nil { + return err + } + target := env.LocalPath("bin", filepath.Base(binPath)) + if err := tui.PromptForConfirmOrAbortError("%s will be removed.\n Do you want to continue? [y/N]:", target); err != nil { + return err + } return os.Remove(target) }, } diff --git a/pkg/environment/env.go b/pkg/environment/env.go index 14814669f8..7c9d86bd29 100644 --- a/pkg/environment/env.go +++ b/pkg/environment/env.go @@ -30,11 +30,6 @@ import ( "golang.org/x/mod/semver" ) -// Name of components -const ( - tiupName = "tiup" -) - var ( // ErrInstallFirst indicates that a component/version is not installed ErrInstallFirst = errors.New("component not installed") @@ -209,6 +204,9 @@ func (env *Environment) SelectInstalledVersion(component string, ver utils.Versi }) errInstallFirst := errors.Annotatef(ErrInstallFirst, "use `tiup install %s` to install component `%s` first", component, component) + if !ver.IsEmpty() { + errInstallFirst = errors.Annotatef(ErrInstallFirst, "use `tiup install %s:%s` to install specified version", component, ver.String()) + } if ver.IsEmpty() || string(ver) == utils.NightlyVersionAlias { var selected utils.Version @@ -287,6 +285,45 @@ func (env *Environment) BinaryPath(component string, ver utils.Version) (string, return env.v1Repo.BinaryPath(installPath, component, ver.String()) } +// Link add soft link to $TIUP_HOME/bin/ +func (env *Environment) Link(component string, version utils.Version) error { + version, err := env.SelectInstalledVersion(component, version) + if err != nil { + return err + } + binPath, err := env.BinaryPath(component, version) + if err != nil { + return err + } + + target := env.LocalPath("bin", filepath.Base(binPath)) + backup := target + ".old" + exist := true + _, err = os.Stat(target) + if err != nil { + if !os.IsNotExist(err) { + return err + } + exist = false + } + if exist { + if err := os.Rename(target, backup); err != nil { + fmt.Printf("Backup of `%s` to `%s` failed.\n", target, backup) + return err + } + } + + fmt.Printf("package %s provides these executables: %s\n", component, filepath.Base(binPath)) + + err = os.Symlink(binPath, target) + if err != nil { + defer func() { _ = os.Rename(backup, target) }() + } else { + defer func() { _ = os.Remove(backup) }() + } + return err +} + // ParseCompVersion parses component part from [:version] specification func ParseCompVersion(spec string) (string, utils.Version) { if strings.Contains(spec, ":") {