diff --git a/bake/hclparser/stdlib.go b/bake/hclparser/stdlib.go index 50f9fd940..09cb6e9b8 100644 --- a/bake/hclparser/stdlib.go +++ b/bake/hclparser/stdlib.go @@ -2,10 +2,15 @@ package hclparser import ( "errors" + "os" + "os/user" "path" + "path/filepath" + "runtime" "strings" "time" + "github.com/docker/cli/cli/config" "github.com/hashicorp/go-cty-funcs/cidr" "github.com/hashicorp/go-cty-funcs/crypto" "github.com/hashicorp/go-cty-funcs/encoding" @@ -62,6 +67,7 @@ var stdlibFunctions = []funcDef{ {name: "greaterthan", fn: stdlib.GreaterThanFunc}, {name: "greaterthanorequalto", fn: stdlib.GreaterThanOrEqualToFunc}, {name: "hasindex", fn: stdlib.HasIndexFunc}, + {name: "homedir", factory: homedirFunc}, {name: "indent", fn: stdlib.IndentFunc}, {name: "index", fn: stdlib.IndexFunc}, {name: "indexof", factory: indexOfFunc}, @@ -254,6 +260,27 @@ func timestampFunc() function.Function { }) } +// homedirFunc constructs a function that returns the current user's home directory. +func homedirFunc() function.Function { + return function.New(&function.Spec{ + Description: `Returns the current user's home directory.`, + Params: []function.Parameter{}, + Type: function.StaticReturnType(cty.String), + Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { + home, err := os.UserHomeDir() + if err != nil { + if home == "" && runtime.GOOS != "windows" { + if u, err := user.Current(); err == nil { + return cty.StringVal(u.HomeDir), nil + } + } + return cty.StringVal(filepath.Dir(config.Dir())), nil + } + return cty.StringVal(home), nil + }, + }) +} + func Stdlib() map[string]function.Function { funcs := make(map[string]function.Function, len(stdlibFunctions)) for _, v := range stdlibFunctions { diff --git a/bake/hclparser/stdlib_test.go b/bake/hclparser/stdlib_test.go index e0d3dd29b..bd745a601 100644 --- a/bake/hclparser/stdlib_test.go +++ b/bake/hclparser/stdlib_test.go @@ -1,6 +1,7 @@ package hclparser import ( + "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -197,3 +198,10 @@ func TestSanitize(t *testing.T) { }) } } + +func TestHomedir(t *testing.T) { + home, err := homedirFunc().Call(nil) + require.NoError(t, err) + require.NotEmpty(t, home.AsString()) + require.True(t, filepath.IsAbs(home.AsString())) +} diff --git a/docs/bake-stdlib.md b/docs/bake-stdlib.md index a26128dd4..b9879abbf 100644 --- a/docs/bake-stdlib.md +++ b/docs/bake-stdlib.md @@ -43,6 +43,7 @@ title: Bake standard library functions | `greaterthan` | Returns true if and only if the second number is greater than the first. | | `greaterthanorequalto` | Returns true if and only if the second number is greater than or equal to the first. | | `hasindex` | Returns true if if the given collection can be indexed with the given key without producing an error, or false otherwise. | +| `homedir` | Returns the current user's home directory. | | `indent` | Adds a given number of spaces after each newline character in the given string. | | `index` | Returns the element with the given key from the given collection, or raises an error if there is no such element. | | `indexof` | Finds the element index for a given value in a list. |