From fb73da5959cbccde607ec592714030be4dd19fa2 Mon Sep 17 00:00:00 2001 From: Jerry Wiltse Date: Tue, 2 Sep 2025 22:03:51 -0400 Subject: [PATCH 1/3] Add two new special vars, which map directly to platform specific go constants: - PATH_LIST_SEPARATOR -> os.PathListSeparator - FILE_PATH_SEPARATOR -> os.PathSeparator Add joinEnv string function which is sibling to joinPath: - strings.Join(elem, string(os.PathListSeparator)) Add joinUrl string function which is sibling to joinPath: - path.Join(elem...) Add all to docs closes #2406 --- internal/templater/funcs.go | 68 ++++++++++++++++-------- website/src/docs/guide.md | 4 +- website/src/docs/reference/templating.md | 63 ++++++++++++++++++++++ 3 files changed, 110 insertions(+), 25 deletions(-) diff --git a/internal/templater/funcs.go b/internal/templater/funcs.go index c3fdc469b6..bf9b227b33 100644 --- a/internal/templater/funcs.go +++ b/internal/templater/funcs.go @@ -3,6 +3,8 @@ package templater import ( "maps" "math/rand/v2" + "os" + "path" "path/filepath" "runtime" "strings" @@ -21,27 +23,31 @@ var templateFuncs template.FuncMap func init() { taskFuncs := template.FuncMap{ - "OS": os, - "ARCH": arch, - "numCPU": runtime.NumCPU, - "catLines": catLines, - "splitLines": splitLines, - "fromSlash": filepath.FromSlash, - "toSlash": filepath.ToSlash, - "exeExt": exeExt, - "shellQuote": shellQuote, - "splitArgs": splitArgs, - "IsSH": IsSH, // Deprecated - "joinPath": filepath.Join, - "relPath": filepath.Rel, - "merge": merge, - "spew": spew.Sdump, - "fromYaml": fromYaml, - "mustFromYaml": mustFromYaml, - "toYaml": toYaml, - "mustToYaml": mustToYaml, - "uuid": uuid.New, - "randIntN": rand.IntN, + "OS": goos, + "ARCH": goarch, + "numCPU": runtime.NumCPU, + "catLines": catLines, + "splitLines": splitLines, + "fromSlash": filepath.FromSlash, + "toSlash": filepath.ToSlash, + "exeExt": exeExt, + "shellQuote": shellQuote, + "splitArgs": splitArgs, + "IsSH": IsSH, // Deprecated + "joinPath": filepath.Join, + "joinEnv": joinEnv, + "joinUrl": joinUrl, + "relPath": filepath.Rel, + "merge": merge, + "spew": spew.Sdump, + "fromYaml": fromYaml, + "mustFromYaml": mustFromYaml, + "toYaml": toYaml, + "mustToYaml": mustToYaml, + "uuid": uuid.New, + "randIntN": rand.IntN, + "PATH_LIST_SEPARATOR": pathListSeparator, + "FILE_PATH_SEPARATOR": filePathSeparator, } // aliases @@ -56,11 +62,11 @@ func init() { maps.Copy(templateFuncs, taskFuncs) } -func os() string { +func goos() string { return runtime.GOOS } -func arch() string { +func goarch() string { return runtime.GOARCH } @@ -94,6 +100,14 @@ func IsSH() bool { return true } +func joinEnv(elem ...string) string { + return strings.Join(elem, string(os.PathListSeparator)) +} + +func joinUrl(elem ...string) string { + return path.Join(elem...) +} + func merge(base map[string]any, v ...map[string]any) map[string]any { cap := len(v) for _, m := range v { @@ -130,3 +144,11 @@ func mustToYaml(v any) (string, error) { } return string(output), nil } + +func pathListSeparator() string { + return string(os.PathListSeparator) +} + +func filePathSeparator() string { + return string(os.PathSeparator) +} diff --git a/website/src/docs/guide.md b/website/src/docs/guide.md index a4d6b5e5ee..e0d45aca8c 100644 --- a/website/src/docs/guide.md +++ b/website/src/docs/guide.md @@ -516,9 +516,9 @@ If the directory does not exist, `task` creates it. ## Task dependencies -> Dependencies run in parallel, so dependencies of a task should not depend one +~~> Dependencies run in parallel, so dependencies of a task should not depend one > another. If you want to force tasks to run serially, take a look at the -> [Calling Another Task](#calling-another-task) section below. +> [Calling Another Task](#calling-another-task) section below.~~ You may have tasks that depend on others. Just pointing them on `deps` will make them run automatically before running the parent task: diff --git a/website/src/docs/reference/templating.md b/website/src/docs/reference/templating.md index ae2391048b..af09f0ac68 100644 --- a/website/src/docs/reference/templating.md +++ b/website/src/docs/reference/templating.md @@ -243,6 +243,24 @@ tasks: - echo "Working {{.USER_WORKING_DIR}}" ``` +#### `FILE_PATH_SEPARATOR` + +- **Type**: `string` +- **Description**: OS-specific path separator: Windows = `\`, others = `/` +- +> **Note**: See `joinPath` in [Path Functions](#path-functions) for joining filesystem paths for use with +> file system operations. + +### Environment Variables + +#### `PATH_LIST_SEPARATOR` + +- **Type**: `string` +- **Description**: OS-specific path separator for environment variables: Windows = `;`, others = `:` + +> **Note**: See `joinEnv` in [Environment Variable Functions](#environment-variable-functions) for joining +> paths for use in environment variables. + ### Status #### `CHECKSUM` @@ -613,6 +631,51 @@ tasks: - echo "Relative {{relPath .ROOT_DIR .TASKFILE_DIR}}" # Get relative path ``` +#### Environment Variable Functions + +```yaml +tasks: + paths: + vars: + WIN_PATH1: 'C:\Users\Person\bin' + WIN_PATH2: 'C:\Shared\bin' + cmds: + - echo "{{joinEnv .WIN_PATH1 .WIN_PATH2}}" # Join paths for windows env vars -> C:\Users\Person\bin;C:\Shared\bin +``` + +```yaml +tasks: + paths: + vars: + POSIX_PATH1: '/users/person/.local/bin' + POSIX_PATH2: '/usr/bin' + cmds: + - echo "{{joinEnv .POSIX_PATH1 .POSIX_PATH2}}" # Join paths for posix env vars -> /users/person/.local/bin:/usr/bin +``` + +#### URLs + +```yaml +tasks: + paths: + vars: + SERVER: 'http://localhost' + PATH1: 'path1' + PATH2: 'path2' + cmds: + - echo "{{joinUrl .SERVER .PATH1 .PATH2}}" # Join paths for URL -> http://localhost/path1/path2 +``` + +```yaml +tasks: + paths: + vars: + POSIX_PATH1: '/users/person/.local/bin' + POSIX_PATH2: '/usr/bin' + cmds: + - echo "{{joinEnv .POSIX_PATH1 .POSIX_PATH2}}" # Join paths for posix env vars -> /users/person/.local/bin:/usr/bin +``` + ### Data Structure Functions #### Dictionary Operations From 00be50c630d42d5d1cb787576ead2f4e2cbedccb Mon Sep 17 00:00:00 2001 From: Jerry Wiltse Date: Wed, 3 Sep 2025 09:42:41 -0400 Subject: [PATCH 2/3] Remove accidental guide.md doc change --- website/src/docs/guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/src/docs/guide.md b/website/src/docs/guide.md index e0d45aca8c..5ee4799cfd 100644 --- a/website/src/docs/guide.md +++ b/website/src/docs/guide.md @@ -516,9 +516,9 @@ If the directory does not exist, `task` creates it. ## Task dependencies -~~> Dependencies run in parallel, so dependencies of a task should not depend one +-> Dependencies run in parallel, so dependencies of a task should not depend one > another. If you want to force tasks to run serially, take a look at the -> [Calling Another Task](#calling-another-task) section below.~~ +> [Calling Another Task](#calling-another-task) section below. You may have tasks that depend on others. Just pointing them on `deps` will make them run automatically before running the parent task: From 9040bd42c99ee10e0951caf77d43c970c973e7bc Mon Sep 17 00:00:00 2001 From: Jerry Wiltse Date: Wed, 3 Sep 2025 09:43:21 -0400 Subject: [PATCH 3/3] Remove accidental guide.md doc change2 --- website/src/docs/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/docs/guide.md b/website/src/docs/guide.md index 5ee4799cfd..a4d6b5e5ee 100644 --- a/website/src/docs/guide.md +++ b/website/src/docs/guide.md @@ -516,7 +516,7 @@ If the directory does not exist, `task` creates it. ## Task dependencies --> Dependencies run in parallel, so dependencies of a task should not depend one +> Dependencies run in parallel, so dependencies of a task should not depend one > another. If you want to force tasks to run serially, take a look at the > [Calling Another Task](#calling-another-task) section below.