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/chzyer/readline v1.5.1
|
||||||
github.com/lmika/gopkgs v0.0.0-20240408110817-a02f6fc67d1f
|
github.com/lmika/gopkgs v0.0.0-20240408110817-a02f6fc67d1f
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
|
lmika.dev/pkg/modash v0.0.0-20250619112300-0be0b6b35b1b
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
@ -17,5 +18,4 @@ require (
|
||||||
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
|
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect
|
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // 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/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 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
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/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 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,32 @@ package builtins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
"ucl.lmika.dev/ucl"
|
"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 {
|
type osHandlers struct {
|
||||||
|
provider OSProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func OS() ucl.Module {
|
func OS() ucl.Module {
|
||||||
osh := osHandlers{}
|
osh := osHandlers{
|
||||||
|
provider: builtinOSProvider{},
|
||||||
|
}
|
||||||
|
|
||||||
return ucl.Module{
|
return ucl.Module{
|
||||||
Name: "os",
|
Name: "os",
|
||||||
Builtins: map[string]ucl.BuiltinHandler{
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
val, ok := os.LookupEnv(envName)
|
val, ok := oh.provider.LookupEnv(envName)
|
||||||
if ok {
|
if ok {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
@ -38,3 +50,42 @@ func (oh osHandlers) env(ctx context.Context, args ucl.CallArgs) (any, error) {
|
||||||
|
|
||||||
return "", nil
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"ucl.lmika.dev/ucl"
|
"ucl.lmika.dev/ucl"
|
||||||
"ucl.lmika.dev/ucl/builtins"
|
"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