@@ -11,89 +11,103 @@ import (
1111)
1212
1313var (
14- workDir string
15- envVars []string
14+ execDockerImage string
15+ execWorkDir string
16+ execEnvVars []string
1617)
1718
18- // execCmd represents the exec command
1919var execCmd = & cobra.Command {
2020 Use : "exec [command] [args...]" ,
2121 Short : "Execute a command" ,
22- Long : `Execute a command with optional environment variables and working directory.
23-
24- Example:
25- runshell exec ls -l
26- runshell exec --env KEY=VALUE --workdir /tmp ls -l
27- runshell exec --docker-image ubuntu:latest ls -l` ,
28- Args : cobra .MinimumNArgs (1 ),
29- RunE : runExec ,
30- }
31-
32- func init () {
33- rootCmd .AddCommand (execCmd )
22+ Long : `Execute a command with optional Docker container and environment variables.` ,
23+ RunE : func (cmd * cobra.Command , args []string ) error {
24+ if len (args ) < 1 {
25+ return fmt .Errorf ("requires at least 1 arg(s), only received %d" , len (args ))
26+ }
3427
35- execCmd .Flags ().StringVar (& workDir , "workdir" , "" , "Working directory for command execution" )
36- execCmd .Flags ().StringArrayVar (& envVars , "env" , nil , "Environment variables (KEY=VALUE)" )
37- execCmd .Flags ().StringVar (& dockerImage , "docker-image" , "" , "Docker image to run command in" )
28+ // 创建执行器
29+ var exec types.Executor
30+ if execDockerImage != "" {
31+ exec = executor .NewDockerExecutor (execDockerImage )
32+ } else {
33+ exec = executor .NewLocalExecutor ()
34+ }
3835
39- // 禁用标志解析,这样可以正确处理命令参数中的标志
40- execCmd .Flags ().SetInterspersed (false )
41- }
36+ // 创建管道执行器
37+ pipeExec := executor .NewPipelineExecutor (exec )
38+
39+ // 检查是否包含管道符
40+ cmdStr := strings .Join (args , " " )
41+ if strings .Contains (cmdStr , "|" ) {
42+ // 解析管道命令
43+ pipeline , err := pipeExec .ParsePipeline (cmdStr )
44+ if err != nil {
45+ return fmt .Errorf ("failed to parse pipeline: %w" , err )
46+ }
47+
48+ // 设置执行选项
49+ pipeline .Options = & types.ExecuteOptions {
50+ WorkDir : execWorkDir ,
51+ Env : parseEnvVars (execEnvVars ),
52+ Stdin : os .Stdin ,
53+ Stdout : os .Stdout ,
54+ Stderr : os .Stderr ,
55+ }
56+ pipeline .Context = cmd .Context ()
57+
58+ // 执行管道命令
59+ result , err := pipeExec .ExecutePipeline (pipeline )
60+ if err != nil {
61+ return fmt .Errorf ("failed to execute pipeline: %w" , err )
62+ }
63+
64+ if result .ExitCode != 0 {
65+ return fmt .Errorf ("pipeline failed with exit code %d" , result .ExitCode )
66+ }
67+
68+ return nil
69+ }
4270
43- func runExec (cmd * cobra.Command , args []string ) error {
44- // 创建本地执行器
45- localExec := executor .NewLocalExecutor ()
71+ // 非管道命令的处理
72+ ctx := & types.ExecuteContext {
73+ Context : cmd .Context (),
74+ Args : args ,
75+ Options : & types.ExecuteOptions {
76+ WorkDir : execWorkDir ,
77+ Env : parseEnvVars (execEnvVars ),
78+ Stdin : os .Stdin ,
79+ Stdout : os .Stdout ,
80+ Stderr : os .Stderr ,
81+ },
82+ }
4683
47- // 如果指定了 Docker 镜像,创建 Docker 执行器
48- var exec interface {} = localExec
49- if dockerImage != "" {
50- dockerExec , err := executor .NewDockerExecutor (dockerImage )
84+ result , err := exec .Execute (ctx )
5185 if err != nil {
52- return fmt .Errorf ("failed to create Docker executor : %v " , err )
86+ return fmt .Errorf ("failed to execute command : %w " , err )
5387 }
54- exec = dockerExec
55- }
5688
57- // 准备执行选项
58- opts := & types.ExecuteOptions {
59- WorkDir : workDir ,
60- Env : make (map [string ]string ),
61- }
62-
63- // 解析环境变量
64- for _ , env := range envVars {
65- key , value , found := strings .Cut (env , "=" )
66- if ! found {
67- return fmt .Errorf ("invalid environment variable format: %s" , env )
89+ if result .ExitCode != 0 {
90+ return fmt .Errorf ("command failed with exit code %d" , result .ExitCode )
6891 }
69- opts .Env [key ] = value
70- }
71-
72- // 执行命令
73- result , err := exec .(types.Executor ).Execute (cmd .Context (), args [0 ], args [1 :], opts )
74- if err != nil {
75- return fmt .Errorf ("failed to execute command: %v" , err )
76- }
7792
78- // 输出结果
79- if result .Output != "" {
80- fmt .Print (result .Output )
81- }
93+ return nil
94+ },
95+ }
8296
83- // 如果有错误,输出到标准错误
84- if result .Error != nil {
85- fmt .Fprintf (os .Stderr , "Error: %v\n " , result .Error )
86- }
97+ func init () {
98+ rootCmd .AddCommand (execCmd )
99+ execCmd .Flags ().StringVar (& execDockerImage , "docker-image" , "" , "Docker image to run command in" )
100+ execCmd .Flags ().StringVar (& execWorkDir , "workdir" , "" , "Working directory for command execution" )
101+ execCmd .Flags ().StringArrayVar (& execEnvVars , "env" , nil , "Environment variables (KEY=VALUE)" )
102+ }
87103
88- // 如果是测试模式,返回错误而不是退出
89- if cmd .Context () != nil {
90- if result .ExitCode != 0 {
91- return fmt .Errorf ("command failed with exit code %d" , result .ExitCode )
104+ func parseEnvVars (vars []string ) map [string ]string {
105+ env := make (map [string ]string )
106+ for _ , v := range vars {
107+ parts := strings .SplitN (v , "=" , 2 )
108+ if len (parts ) == 2 {
109+ env [parts [0 ]] = parts [1 ]
92110 }
93- return nil
94111 }
95-
96- // 使用命令的退出码退出
97- os .Exit (result .ExitCode )
98- return nil
112+ return env
99113}
0 commit comments