Skip to content

Commit d4ab49b

Browse files
committed
feat: add xargs command
1 parent 7d33f90 commit d4ab49b

File tree

5 files changed

+93
-11
lines changed

5 files changed

+93
-11
lines changed

e2e/tests/pipelines/pipelines.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ var _ = DevSpaceDescribe("portforward", func() {
5252
framework.ExpectLocalFileContentsImmediately("test.txt", "Hello World!\n")
5353
})
5454

55-
ginkgo.It("should exec container", func() {
55+
ginkgo.It("should watch files", func() {
5656
tempDir, err := framework.CopyToTempDir("tests/pipelines/testdata/watch")
5757
framework.ExpectNoError(err)
5858
defer framework.CleanupTempDir(initialDir, tempDir)

e2e/tests/pipelines/testdata/watch/devspace.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ pipelines:
1414
- run: |-
1515
echo "Hello World" >> test2.yaml
1616
17+
other3:
18+
steps:
19+
- run: |-
20+
echo "other other2" | xargs run_pipelines
21+
1722
dev:
1823
steps:
1924
- run: |-
20-
watch -p *.txt -- run_pipelines other other2
25+
watch -p *.txt -- run_pipelines other3

pkg/devspace/pipeline/engine/pipelinehandler/commands/watch.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ import (
66
"github.com/bmatcuk/doublestar"
77
"github.com/jessevdk/go-flags"
88
devspacecontext "github.com/loft-sh/devspace/pkg/devspace/context"
9-
"github.com/loft-sh/devspace/pkg/devspace/pipeline/engine"
10-
"github.com/loft-sh/devspace/pkg/devspace/pipeline/types"
9+
types2 "github.com/loft-sh/devspace/pkg/devspace/pipeline/engine/types"
1110
"github.com/loft-sh/devspace/pkg/util/log"
1211
"github.com/loft-sh/devspace/pkg/util/tomb"
1312
"github.com/loft-sh/notify"
1413
"github.com/pkg/errors"
15-
"mvdan.cc/sh/v3/interp"
1614
"os"
1715
"path/filepath"
1816
"strings"
@@ -25,7 +23,7 @@ type WatchOptions struct {
2523
Paths []string `long:"path" short:"p" description:"The paths to watch. Can be patterns in the form of ./**/my-file.txt"`
2624
}
2725

28-
func Watch(devCtx *devspacecontext.Context, pipeline types.Pipeline, args []string, newHandler NewHandlerFn) error {
26+
func Watch(devCtx *devspacecontext.Context, args []string, handler types2.ExecHandler) error {
2927
devCtx.Log.Debugf("watch %s", strings.Join(args, " "))
3028
options := &WatchOptions{}
3129
args, err := flags.ParseArgs(options, args)
@@ -40,11 +38,8 @@ func Watch(devCtx *devspacecontext.Context, pipeline types.Pipeline, args []stri
4038
}
4139

4240
w := &watcher{}
43-
hc := interp.HandlerCtx(devCtx.Context)
4441
return w.Watch(devCtx.Context, options.Paths, options.FailOnError, func(ctx context.Context) error {
45-
devCtx := devCtx.WithContext(ctx)
46-
_, err := engine.ExecutePipelineShellCommand(ctx, args[0]+" $@", args[1:], hc.Dir, false, hc.Stdout, hc.Stderr, hc.Stdin, hc.Env, newHandler(devCtx, hc.Stdout, pipeline))
47-
return err
42+
return handler.ExecHandler(ctx, args)
4843
}, devCtx.Log)
4944
}
5045

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package commands
2+
3+
import (
4+
"errors"
5+
devspacecontext "github.com/loft-sh/devspace/pkg/devspace/context"
6+
"github.com/loft-sh/devspace/pkg/devspace/pipeline/engine/types"
7+
"io/ioutil"
8+
"mvdan.cc/sh/v3/interp"
9+
"strings"
10+
)
11+
12+
var xArgsUsage = errors.New(`usage: xargs [utility [argument ...]]`)
13+
14+
type XArgsOptions struct {
15+
Delimiter string
16+
}
17+
18+
func XArgs(devCtx *devspacecontext.Context, args []string, handler types.ExecHandler) error {
19+
options := &XArgsOptions{
20+
Delimiter: " ",
21+
}
22+
23+
args, err := parseXArgsOptions(args, options)
24+
if err != nil {
25+
return err
26+
} else if len(args) == 0 {
27+
return xArgsUsage
28+
}
29+
30+
hc := interp.HandlerCtx(devCtx.Context)
31+
out, err := ioutil.ReadAll(hc.Stdin)
32+
if err != nil {
33+
return err
34+
}
35+
36+
addArgs := strings.Split(string(out), options.Delimiter)
37+
for _, addArg := range addArgs {
38+
addArg = strings.TrimSpace(addArg)
39+
if addArg == "" {
40+
continue
41+
}
42+
43+
args = append(args, addArg)
44+
}
45+
return handler.ExecHandler(devCtx.Context, args)
46+
}
47+
48+
func parseXArgsOptions(args []string, options *XArgsOptions) ([]string, error) {
49+
// check args for flags
50+
startAt := 0
51+
for i := 0; i < len(args); i++ {
52+
arg := args[i]
53+
if len(arg) > 0 && arg[0] == '-' {
54+
startAt++
55+
arg = arg[1:]
56+
57+
switch arg {
58+
case "d", "-delimiter":
59+
if i+1 == len(args) {
60+
return nil, xArgsUsage
61+
}
62+
63+
i++
64+
startAt++
65+
options.Delimiter = args[i]
66+
default:
67+
return nil, xArgsUsage
68+
}
69+
70+
continue
71+
}
72+
73+
break
74+
}
75+
76+
return args[startAt:], nil
77+
}

pkg/devspace/pipeline/engine/pipelinehandler/handler.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ import (
1818

1919
// PipelineCommands are commands that can only be run within a pipeline and have special functionality in there
2020
var PipelineCommands = map[string]func(devCtx *devspacecontext.Context, pipeline types.Pipeline, args []string) error{
21+
"xargs": func(devCtx *devspacecontext.Context, pipeline types.Pipeline, args []string) error {
22+
hc := interp.HandlerCtx(devCtx.Context)
23+
return commands.XArgs(devCtx, args, NewPipelineExecHandler(devCtx, hc.Stdout, pipeline))
24+
},
2125
"exec_container": func(devCtx *devspacecontext.Context, pipeline types.Pipeline, args []string) error {
2226
return commands.ExecContainer(devCtx, args)
2327
},
@@ -31,7 +35,8 @@ var PipelineCommands = map[string]func(devCtx *devspacecontext.Context, pipeline
3135
return commands.RunDefaultPipeline(devCtx, pipeline, args, NewPipelineExecHandler)
3236
},
3337
"watch": func(devCtx *devspacecontext.Context, pipeline types.Pipeline, args []string) error {
34-
return commands.Watch(devCtx, pipeline, args, NewPipelineExecHandler)
38+
hc := interp.HandlerCtx(devCtx.Context)
39+
return commands.Watch(devCtx, args, NewPipelineExecHandler(devCtx, hc.Stdout, pipeline))
3540
},
3641
"run_pipelines": func(devCtx *devspacecontext.Context, pipeline types.Pipeline, args []string) error {
3742
return commands.RunPipelines(devCtx, pipeline, args)

0 commit comments

Comments
 (0)