未验证 提交 24cee7dc 编写于 作者: LinuxSuRen's avatar LinuxSuRen 提交者: GitHub

Add sub shell support (#253)

* Add sub shell support

* Remove logger print
上级 da662914
......@@ -203,8 +203,13 @@ func saveConfig() (err error) {
var data []byte
config := getConfig()
configPath := configOptions.ConfigFileLocation
if rootOptions.ConfigFile != "" {
configPath = rootOptions.ConfigFile
}
if data, err = yaml.Marshal(&config); err == nil {
err = ioutil.WriteFile(configOptions.ConfigFileLocation, data, 0644)
err = ioutil.WriteFile(configPath, data, 0644)
}
return
}
......
......@@ -2,6 +2,7 @@ package cmd
import (
"github.com/AlecAivazis/survey/v2"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
......@@ -11,8 +12,8 @@ func init() {
var configSelectCmd = &cobra.Command{
Use: "select [<name>]",
Short: "Select one config as current Jenkins",
Long: `Select one config as current Jenkins`,
Short: i18n.T("Select one config as current Jenkins"),
Long: i18n.T("Select one config as current Jenkins"),
Run: func(_ *cobra.Command, args []string) {
if len(args) > 0 {
jenkinsName := args[0]
......
......@@ -2,11 +2,12 @@ package cmd
import (
"bytes"
"github.com/jenkins-zh/jenkins-cli/client"
"io/ioutil"
"net/http"
"os"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
......@@ -54,7 +55,7 @@ var _ = Describe("job type command", func() {
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
initConfig()
//initConfig()
jclient := &client.JobClient{
JenkinsCore: client.JenkinsCore{
RoundTripper: jobTypeOption.RoundTripper,
......
......@@ -34,11 +34,38 @@ var rootCmd = &cobra.Command{
Use: "jcli",
Short: i18n.T("jcli is a tool which could help you with your multiple Jenkins"),
Long: `jcli is Jenkins CLI which could help with your multiple Jenkins,
Manage your Jenkins and your pipelines
More information could found at https://jenkins-zh.cn`,
Manage your Jenkins and your pipelines
More information could found at https://jenkins-zh.cn`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
if logger, err = util.InitLogger(rootOptions.LoggerLevel); err == nil {
client.SetLogger(logger)
} else {
return
}
if rootOptions.ConfigFile == "" {
rootOptions.ConfigFile = os.Getenv("JCLI_CONFIG")
}
logger.Debug("read config file", zap.String("path", rootOptions.ConfigFile))
if rootOptions.Version && cmd.Flags().NFlag() == 1 {
return
}
if rootOptions.ConfigFile == "" {
if err := loadDefaultConfig(); err != nil {
configLoadErrorHandle(err)
}
} else {
if err := loadConfig(rootOptions.ConfigFile); err != nil {
configLoadErrorHandle(err)
}
}
// set Header Accept-Language
config = getConfig()
if config != nil {
client.SetLanguage(config.Language)
}
return
},
......@@ -60,7 +87,7 @@ var rootCmd = &cobra.Command{
},
}
// Execute will exectue the command
// Execute will execute the command
func Execute() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
......@@ -70,7 +97,6 @@ func Execute() {
var rootOptions RootOptions
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVarP(&rootOptions.ConfigFile, "configFile", "", "",
i18n.T("An alternative config file"))
rootCmd.PersistentFlags().StringVarP(&rootOptions.Jenkins, "jenkins", "j", "",
......@@ -83,26 +109,6 @@ func init() {
rootCmd.SetOut(os.Stdout)
}
func initConfig() {
if rootOptions.Version && rootCmd.Flags().NFlag() == 1 {
return
}
if rootOptions.ConfigFile == "" {
if err := loadDefaultConfig(); err != nil {
configLoadErrorHandle(err)
}
} else {
if err := loadConfig(rootOptions.ConfigFile); err != nil {
configLoadErrorHandle(err)
}
}
// set Header Accept-Language
config = getConfig()
if config != nil {
client.SetLanguage(config.Language)
}
}
func configLoadErrorHandle(err error) {
if os.IsNotExist(err) {
log.Printf("No config file found.")
......@@ -250,7 +256,7 @@ __jcli_custom_func() {
__jcli_get_plugin_name
return
;;
jcli_open | jcli_config_select | jcli_config_remove)
jcli_open | jcli_config_select | jcli_config_remove | jcli_shell)
__jcli_get_config_name
return
;;
......
package cmd
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"go.uber.org/zap"
"gopkg.in/yaml.v2"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(shellCmd)
}
const (
defaultRcFile = `
if [ -f /etc/bashrc ]; then
source /etc/bashrc
fi
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
if type -t __start_jcli >/dev/null; then true; else
source <(jcli completion)
fi
`
zshRcFile = `
if [ -f /etc/zshrc ]; then
source /etc/zshrc
fi
if [ -f ~/.zshrc ]; then
source ~/.zshrc
fi
`
)
var shellCmd = &cobra.Command{
Use: "shell [<name>]",
Short: i18n.T("Create a sub shell so that changes to a specific Jenkins remain local to the shell."),
Long: i18n.T("Create a sub shell so that changes to a specific Jenkins remain local to the shell."),
Aliases: []string{"sh"},
PreRun: func(cmd *cobra.Command, args []string) {
if len(args) > 0 {
jenkinsName := args[0]
setCurrentJenkins(jenkinsName)
}
},
RunE: func(cmd *cobra.Command, _ []string) error {
tmpDirName, err := ioutil.TempDir("", ".jcli-shell-")
if err != nil {
return err
}
tmpConfigFileName := filepath.Join(tmpDirName, "/config")
var data []byte
config := getConfig()
if data, err = yaml.Marshal(&config); err == nil {
err = ioutil.WriteFile(tmpConfigFileName, data, 0644)
} else {
return err
}
fullShell := os.Getenv("SHELL")
shell := filepath.Base(fullShell)
if fullShell == "" && runtime.GOOS == "windows" {
// SHELL is set by git-bash but not cygwin :-(
shell = "cmd.exe"
}
prompt := createNewBashPrompt(os.Getenv("PS1"))
rcFile := defaultRcFile + "\nexport PS1=" + prompt + "\nexport JCLI_CONFIG=\"" + tmpConfigFileName + "\"\n"
tmpRCFileName := tmpDirName + "/.bashrc"
err = ioutil.WriteFile(tmpRCFileName, []byte(rcFile), 0760)
if err != nil {
return err
}
logger.Debug("temporary shell profile loaded", zap.String("path", tmpRCFileName))
e := exec.Command(shell, "-rcfile", tmpRCFileName, "-i")
if shell == "zsh" {
env := os.Environ()
env = append(env, fmt.Sprintf("ZDOTDIR=%s", tmpDirName))
e = exec.Command(shell, "-i")
e.Env = env
} else if shell == "cmd.exe" {
env := os.Environ()
env = append(env, fmt.Sprintf("JCLI_CONFIG=%s", tmpConfigFileName))
e = exec.Command(shell)
e.Env = env
}
e.Stdout = cmd.OutOrStdout()
e.Stderr = cmd.OutOrStderr()
e.Stdin = os.Stdin
err = e.Run()
if deleteError := os.RemoveAll(tmpDirName); deleteError != nil {
panic(err)
}
return err
},
}
func createNewBashPrompt(prompt string) string {
if prompt == "" {
return "'[\\u@\\h \\W jcli> ]\\$ '"
}
if prompt[0] == '"' {
return prompt[0:1] + "jcli> " + prompt[1:]
}
if prompt[0] == '\'' {
return prompt[0:1] + "jcli> " + prompt[1:]
}
return "'jcli> " + prompt + "'"
}
......@@ -114,6 +114,10 @@ msgstr "Jenkins CLI (jcli) 管理你的 Jenkins"
msgid "Whether skip the previous command hook"
msgstr "是否跳过前置命令钩子"
#: app/cmd/shell.go:49 app/cmd/shell.go:50
msgid "Create a sub shell so that changes to a specific Jenkins remain local to the shell."
msgstr "创建一个子 shell 使得对配置的修改保持在一个上下文中"
#: app/cmd/plugin.go:21 app/cmd/plugin.go:22
msgid "Manage the plugins of Jenkins"
msgstr "管理 Jenkins 的插件"
......@@ -168,7 +172,7 @@ msgstr "Jenkins 的令牌"
#: app/cmd/config_add.go:32
msgid "ProxyAuth of the Jenkins"
msgstr ""
msgstr "Jenkins 链接的代理认证"
#: app/cmd/center_watch.go:27
msgid "The watch will be continue util Jenkins needs restart"
......@@ -224,7 +228,7 @@ msgstr "设置更新中心为一个镜像地址"
#: app/cmd/plugin_search.go:33 app/cmd/plugin_search.go:34
msgid "Print the plugins of your Jenkins"
msgstr ""
msgstr "列出你的 Jenkins 中的插件"
#: app/cmd/plugin_upload.go:39
msgid "Whether show the upload progress"
......
......@@ -14,6 +14,7 @@ require (
github.com/gosexy/gettext v0.0.0-20160830220431-74466a0a0c4a // indirect
github.com/gosuri/uilive v0.0.3 // indirect
github.com/gosuri/uiprogress v0.0.1
github.com/imdario/mergo v0.3.8 // indirect
github.com/jessevdk/go-flags v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.10 // indirect
github.com/mitchellh/go-homedir v1.1.0
......@@ -21,5 +22,7 @@ require (
github.com/onsi/gomega v1.7.1
github.com/spf13/cobra v0.0.5
go.uber.org/zap v1.13.0
golang.org/x/oauth2 v0.0.0-20191122200657-5d9234df094c // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
gopkg.in/yaml.v2 v2.2.5
)
......@@ -121,6 +121,8 @@ github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
......@@ -242,9 +244,9 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEa
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.12.0 h1:dySoUQPFBGj6xwjmBzageVL8jGi8uxc6bEmJQjA06bw=
go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
......@@ -283,6 +285,8 @@ golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191122200657-5d9234df094c h1:HjRaKPaiWks0f5tA6ELVF7ZfqSppfPwOEEAvsrKUTO4=
golang.org/x/oauth2 v0.0.0-20191122200657-5d9234df094c/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
......@@ -317,6 +321,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
......@@ -363,11 +369,11 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册