This commit is contained in:
parent
7a2b012833
commit
a81a19491f
2
go.mod
2
go.mod
|
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/chzyer/readline v1.5.1
|
||||
github.com/lmika/gopkgs v0.0.0-20240408110817-a02f6fc67d1f
|
||||
github.com/stretchr/testify v1.10.0
|
||||
lmika.dev/pkg/modash v0.0.0-20250619112300-0be0b6b35b1b
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -17,5 +18,4 @@ require (
|
|||
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lmika.dev/pkg/modash v0.0.0-20250619112300-0be0b6b35b1b // indirect
|
||||
)
|
||||
|
|
|
|||
1
go.sum
1
go.sum
|
|
@ -22,6 +22,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
|
|
|
|||
|
|
@ -2,20 +2,32 @@ package builtins
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"ucl.lmika.dev/ucl"
|
||||
)
|
||||
|
||||
type OSProvider interface {
|
||||
LookupEnv(string) (string, bool)
|
||||
Exec(ctx context.Context, cmd string, args ...string) (*exec.Cmd, error)
|
||||
}
|
||||
|
||||
type osHandlers struct {
|
||||
provider OSProvider
|
||||
}
|
||||
|
||||
func OS() ucl.Module {
|
||||
osh := osHandlers{}
|
||||
osh := osHandlers{
|
||||
provider: builtinOSProvider{},
|
||||
}
|
||||
|
||||
return ucl.Module{
|
||||
Name: "os",
|
||||
Builtins: map[string]ucl.BuiltinHandler{
|
||||
"env": osh.env,
|
||||
"env": osh.env,
|
||||
"exec": osh.exec,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +38,7 @@ func (oh osHandlers) env(ctx context.Context, args ucl.CallArgs) (any, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
val, ok := os.LookupEnv(envName)
|
||||
val, ok := oh.provider.LookupEnv(envName)
|
||||
if ok {
|
||||
return val, nil
|
||||
}
|
||||
|
|
@ -38,3 +50,42 @@ func (oh osHandlers) env(ctx context.Context, args ucl.CallArgs) (any, error) {
|
|||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (oh osHandlers) exec(ctx context.Context, args ucl.CallArgs) (any, error) {
|
||||
var cmdArgs []string
|
||||
|
||||
for args.NArgs() > 0 {
|
||||
var s string
|
||||
if err := args.Bind(&s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmdArgs = append(cmdArgs, s)
|
||||
}
|
||||
|
||||
if len(cmdArgs) == 0 {
|
||||
return nil, errors.New("expected command")
|
||||
}
|
||||
|
||||
cmd, err := oh.provider.Exec(ctx, cmdArgs[0], cmdArgs[1:]...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return string(res), nil
|
||||
}
|
||||
|
||||
type builtinOSProvider struct{}
|
||||
|
||||
func (builtinOSProvider) LookupEnv(key string) (string, bool) {
|
||||
return os.LookupEnv(key)
|
||||
}
|
||||
|
||||
func (builtinOSProvider) Exec(ctx context.Context, name string, args ...string) (*exec.Cmd, error) {
|
||||
return exec.CommandContext(ctx, name, args...), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@ package builtins_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"ucl.lmika.dev/ucl"
|
||||
"ucl.lmika.dev/ucl/builtins"
|
||||
)
|
||||
|
|
@ -34,3 +36,25 @@ func TestOS_Env(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOS_Exec(t *testing.T) {
|
||||
tests := []struct {
|
||||
descr string
|
||||
eval string
|
||||
want any
|
||||
}{
|
||||
{descr: "run command 1", eval: `os:exec "echo" "hello, world"`, want: "hello, world\n"},
|
||||
{descr: "run command 1", eval: `os:exec "date" "+%Y%m%d"`, want: time.Now().Format("20060102") + "\n"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.descr, func(t *testing.T) {
|
||||
inst := ucl.New(
|
||||
ucl.WithModule(builtins.OS()),
|
||||
)
|
||||
res, err := inst.EvalString(context.Background(), tt.eval)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, res)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue