From d352cefed0337faefba0c533357de4dfe1aba2bb Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Thu, 3 Aug 2023 18:47:36 +1000 Subject: [PATCH 01/20] feat: Create `lookPathIn` As per: https://github.com/twpayne/chezmoi/issues/3141 BREAKING CHANGE: `isExecutable` has major change for windows. It now does something --- .../templates/functions/lookPathIn.md | 39 +++++++++++++++ assets/chezmoi.io/mkdocs.yml | 1 + internal/chezmoi/chezmoi_unix.go | 5 ++ internal/chezmoi/chezmoi_windows.go | 40 +++++++++++++++- internal/chezmoi/lookpathin.go | 47 +++++++++++++++++++ internal/cmd/config.go | 1 + internal/cmd/templatefuncs.go | 10 ++++ .../testdata/scripts/templatefuncs_unix.txtar | 10 ++++ .../scripts/templatefuncs_windows.txtar | 9 ++++ 9 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 assets/chezmoi.io/docs/reference/templates/functions/lookPathIn.md create mode 100644 internal/chezmoi/lookpathin.go create mode 100644 internal/cmd/testdata/scripts/templatefuncs_unix.txtar create mode 100644 internal/cmd/testdata/scripts/templatefuncs_windows.txtar diff --git a/assets/chezmoi.io/docs/reference/templates/functions/lookPathIn.md b/assets/chezmoi.io/docs/reference/templates/functions/lookPathIn.md new file mode 100644 index 00000000000..b835affe7e8 --- /dev/null +++ b/assets/chezmoi.io/docs/reference/templates/functions/lookPathIn.md @@ -0,0 +1,39 @@ +# `lookPathIn` *file* *paths* + +`lookPathIn` searches for an executable named *file* in the directories provided by +the `paths` parameter using the standard OS way of separating the PATH environment +variable. The result may be an absolute path or a path relative to the current directory. +If *file* is not found, `lookPathIn` returns an empty string. + +If the OS is Windows `lookPathIn` will either: if there is an extension, check to see if +the extension is specified in the `PathExt` environment variable. If there isn't an +extension it will try each of the extensions specified in the `PathExt` environment +variable in the order provided until it finds one. In either case if it doesn't `lookPathIn` +moves onto the next path provided in the `paths` parameter. + +`lookPathIn` is provided as an alternative to `lookPath` so that you interrogate the +paths as you would have them. + +Each successful lookup is cached based on the full path, and evaluated in the correct +order each time to reduce `File Stat` operations. + +!!! example + + ``` + {{- $paths := list }} + {{- $homeDir := .chezmoi.homeDir }} + {{- range $_, $relPath := list "bin" "go/bin" ".cargo/bin" ".local/bin" }} + {{ $path := joinPath $homeDir $relPath }} + {{- if stat $path }} + {{- $paths = mustAppend $paths $path }} + {{- end }} + {{- end }} + {{- if $paths }} + export PATH={{ toStrings $paths | join ":" }}:$PATH + {{- end }} + + {{ if lookPath "less" $paths }} + echo "Good news we have found 'less' on system at '{{ lookPath "less" $paths }}'!" + export DIFFTOOL=less + {{ end }} + ``` diff --git a/assets/chezmoi.io/mkdocs.yml b/assets/chezmoi.io/mkdocs.yml index f3415a88a47..86a2b8bd23f 100644 --- a/assets/chezmoi.io/mkdocs.yml +++ b/assets/chezmoi.io/mkdocs.yml @@ -198,6 +198,7 @@ nav: - joinPath: reference/templates/functions/joinPath.md - jq: reference/templates/functions/jq.md - lookPath: reference/templates/functions/lookPath.md + - lookPathIn: reference/templates/functions/lookPathIn.md - lstat: reference/templates/functions/lstat.md - mozillaInstallHash: reference/templates/functions/mozillaInstallHash.md - output: reference/templates/functions/output.md diff --git a/internal/chezmoi/chezmoi_unix.go b/internal/chezmoi/chezmoi_unix.go index dd8a57d2683..c3d27efb227 100644 --- a/internal/chezmoi/chezmoi_unix.go +++ b/internal/chezmoi/chezmoi_unix.go @@ -15,6 +15,11 @@ func init() { unix.Umask(int(Umask)) } +// findExecutableExtensions returns valid OS executable extensions, on unix it can be anything. +func findExecutableExtensions(path string) []string { + return []string{path} +} + // isExecutable returns if fileInfo is executable. func isExecutable(fileInfo fs.FileInfo) bool { return fileInfo.Mode().Perm()&0o111 != 0 diff --git a/internal/chezmoi/chezmoi_windows.go b/internal/chezmoi/chezmoi_windows.go index a807449fd41..7cd3c560ba8 100644 --- a/internal/chezmoi/chezmoi_windows.go +++ b/internal/chezmoi/chezmoi_windows.go @@ -2,13 +2,49 @@ package chezmoi import ( "io/fs" + "os" + "path/filepath" + "strings" ) const nativeLineEnding = "\r\n" -// isExecutable returns false on Windows. +var pathExt []string = nil + +// findExecutableExtensions returns valid OS executable extensions for a given executable +func findExecutableExtensions(path string) []string { + cmdExt := filepath.Ext(path) + if cmdExt != "" { + return []string{path} + } + result := make([]string, len(cmdExt)) + for i, e := range getPathExt() { + result[i] = path + e + } + return result +} + +func getPathExt() []string { + if pathExt == nil { + pathExt = strings.Split(os.Getenv("PathExt"), string(filepath.ListSeparator)) + } + return pathExt +} + +// isExecutable checks if the file has an extension listed in the `PathExt` variable as per: +// https://www.nextofwindows.com/what-is-pathext-environment-variable-in-windows then checks to see if it's regular file func isExecutable(fileInfo fs.FileInfo) bool { - return false + foundPathExt := false + cmdExt := filepath.Ext(fileInfo.Name()) + if cmdExt != "" { + for _, ext := range getPathExt() { + if strings.EqualFold(cmdExt, ext) { + foundPathExt = true + break + } + } + } + return foundPathExt && fileInfo.Mode().IsRegular() } // isPrivate returns false on Windows. diff --git a/internal/chezmoi/lookpathin.go b/internal/chezmoi/lookpathin.go new file mode 100644 index 00000000000..765fa31c3ce --- /dev/null +++ b/internal/chezmoi/lookpathin.go @@ -0,0 +1,47 @@ +package chezmoi + +import ( + "os" + "path/filepath" + "sync" +) + +var ( + foundExecutableCacheMutex sync.Mutex + foundExecutableCache = make(map[string]struct{}) +) + +// LookPathIn is like lookPath except that you can specify the paths rather than just using the current `$PATH`. This +// makes it useful for the resulting path of rc/profile files. +func LookPathIn(file, paths string) (string, error) { + foundExecutableCacheMutex.Lock() + defer foundExecutableCacheMutex.Unlock() + + // stolen from: /usr/lib/go-1.20/src/os/exec/lp_unix.go:52 + for _, dir := range filepath.SplitList(paths) { + if dir == "" { + continue + } + p := filepath.Join(dir, file) + for _, path := range findExecutableExtensions(p) { + if _, ok := foundExecutableCache[path]; ok { + return path, nil + } + f, err := os.Stat(path) + if err != nil { + continue + } + m := f.Mode() + // isExecutable doesn't care if it's a directory + if m.IsDir() { + continue + } + if isExecutable(f) { + foundExecutableCache[path] = struct{}{} + return path, nil + } + } + } + + return "", nil +} diff --git a/internal/cmd/config.go b/internal/cmd/config.go index 7fa56d818af..d386694a0e0 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -432,6 +432,7 @@ func newConfig(options ...configOption) (*Config, error) { "lastpass": c.lastpassTemplateFunc, "lastpassRaw": c.lastpassRawTemplateFunc, "lookPath": c.lookPathTemplateFunc, + "lookPathIn": c.lookPathInTemplateFunc, "lstat": c.lstatTemplateFunc, "mozillaInstallHash": c.mozillaInstallHashTemplateFunc, "onepassword": c.onepasswordTemplateFunc, diff --git a/internal/cmd/templatefuncs.go b/internal/cmd/templatefuncs.go index 5231386a0d0..f19cbd6d10d 100644 --- a/internal/cmd/templatefuncs.go +++ b/internal/cmd/templatefuncs.go @@ -315,6 +315,16 @@ func (c *Config) lookPathTemplateFunc(file string) string { } } +func (c *Config) lookPathInTemplateFunc(file, paths string) string { + switch path, err := chezmoi.LookPathIn(file, paths); { + case err == nil: + return path + // It's wrong to return an error past a parsing issue, parser is "dumb" however. + default: + panic(err) + } +} + func (c *Config) lstatTemplateFunc(name string) any { switch fileInfo, err := c.fileSystem.Lstat(name); { case err == nil: diff --git a/internal/cmd/testdata/scripts/templatefuncs_unix.txtar b/internal/cmd/testdata/scripts/templatefuncs_unix.txtar new file mode 100644 index 00000000000..c3f2e25d86b --- /dev/null +++ b/internal/cmd/testdata/scripts/templatefuncs_unix.txtar @@ -0,0 +1,10 @@ +[windows] skip 'Unix only' + +# test lookPathIn template function to find in specified script - success +exec chezmoi execute-template '{{ lookPathIn "echo" "/bin" }}' +stdout ^/bin/echo + +# test lookPathIn template function to find in specified script - failure +exec chezmoi execute-template '{{ lookPathIn "echo" "/lib" }}' +stdout ^$ + diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar new file mode 100644 index 00000000000..fb8fa1b8c46 --- /dev/null +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -0,0 +1,9 @@ +[!windows] skip 'Windows only' + +# test lookPathIn template function to find in specified script - success +exec chezmoi execute-template '{{ lookPathIn "winver" "c:\windows" }}' +stdout ^/bin/echo + +# test lookPathIn template function to find in specified script - failure +exec chezmoi execute-template '{{ lookPathIn "winver" "c:\users" }}' +stdout ^$ From f667b6c215e9f6ca708960637b8b98940fec2c0b Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Thu, 3 Aug 2023 22:45:55 +1000 Subject: [PATCH 02/20] Regexp changes. --- internal/cmd/testdata/scripts/templatefuncs_windows.txtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index fb8fa1b8c46..1dccf6edd61 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -2,7 +2,7 @@ # test lookPathIn template function to find in specified script - success exec chezmoi execute-template '{{ lookPathIn "winver" "c:\windows" }}' -stdout ^/bin/echo +stdout ^c:\windows\winver.exe$ # test lookPathIn template function to find in specified script - failure exec chezmoi execute-template '{{ lookPathIn "winver" "c:\users" }}' From 699a2f600377b721f29a13a28e7d40ae7d678ae2 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Thu, 3 Aug 2023 22:50:46 +1000 Subject: [PATCH 03/20] Let's try this form --- internal/cmd/testdata/scripts/templatefuncs_windows.txtar | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index 1dccf6edd61..85a1505d8c7 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,7 +1,11 @@ [!windows] skip 'Windows only' -# test lookPathIn template function to find in specified script - success -exec chezmoi execute-template '{{ lookPathIn "winver" "c:\windows" }}' +# test lookPathIn template function to find in specified script - success without extension +exec chezmoi execute-template '{{ lookPathIn "winver" "C:\Windows\System32" }}' +stdout ^c:\windows\winver.exe$ + +# test lookPathIn template function to find in specified script - success with extension +exec chezmoi execute-template '{{ lookPathIn "winver.exe" "C:\Windows\System32" }}' stdout ^c:\windows\winver.exe$ # test lookPathIn template function to find in specified script - failure From 8f3d3f7e0ceaedb4013259026f57f6f3af4de331 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Thu, 3 Aug 2023 23:15:56 +1000 Subject: [PATCH 04/20] Escape.. --- internal/cmd/testdata/scripts/templatefuncs_windows.txtar | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index 85a1505d8c7..7fc72cbc455 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,13 +1,13 @@ [!windows] skip 'Windows only' # test lookPathIn template function to find in specified script - success without extension -exec chezmoi execute-template '{{ lookPathIn "winver" "C:\Windows\System32" }}' +exec chezmoi execute-template '{{ lookPathIn "winver" "C:\\Windows\\System32" }}' stdout ^c:\windows\winver.exe$ # test lookPathIn template function to find in specified script - success with extension -exec chezmoi execute-template '{{ lookPathIn "winver.exe" "C:\Windows\System32" }}' +exec chezmoi execute-template '{{ lookPathIn "winver.exe" "C:\\Windows\\System32" }}' stdout ^c:\windows\winver.exe$ # test lookPathIn template function to find in specified script - failure -exec chezmoi execute-template '{{ lookPathIn "winver" "c:\users" }}' +exec chezmoi execute-template '{{ lookPathIn "winver" "c:\\users" }}' stdout ^$ From 7a1e2f9cebce32a62b1c1c76ec74233284152621 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Thu, 3 Aug 2023 23:52:04 +1000 Subject: [PATCH 05/20] Wrong length --- internal/chezmoi/chezmoi_windows.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/chezmoi/chezmoi_windows.go b/internal/chezmoi/chezmoi_windows.go index 7cd3c560ba8..31cd09e23b7 100644 --- a/internal/chezmoi/chezmoi_windows.go +++ b/internal/chezmoi/chezmoi_windows.go @@ -17,8 +17,9 @@ func findExecutableExtensions(path string) []string { if cmdExt != "" { return []string{path} } - result := make([]string, len(cmdExt)) - for i, e := range getPathExt() { + ext := getPathExt() + result := make([]string, len(ext)) + for i, e := range ext { result[i] = path + e } return result From 8eb68c714efec8ac64f6d88624951d136825c910 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 00:11:29 +1000 Subject: [PATCH 06/20] Bah.. --- internal/chezmoi/chezmoi_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/chezmoi/chezmoi_windows.go b/internal/chezmoi/chezmoi_windows.go index 31cd09e23b7..5edefb60be9 100644 --- a/internal/chezmoi/chezmoi_windows.go +++ b/internal/chezmoi/chezmoi_windows.go @@ -20,7 +20,7 @@ func findExecutableExtensions(path string) []string { ext := getPathExt() result := make([]string, len(ext)) for i, e := range ext { - result[i] = path + e + result[i] = strings.TrimSuffix(path, cmdExt) + e } return result } From 7f97988c4e1e7321ae5dc0788527547b3979c43d Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 00:32:19 +1000 Subject: [PATCH 07/20] Wrong logic.. --- internal/chezmoi/chezmoi_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/chezmoi/chezmoi_windows.go b/internal/chezmoi/chezmoi_windows.go index 5edefb60be9..01547999e88 100644 --- a/internal/chezmoi/chezmoi_windows.go +++ b/internal/chezmoi/chezmoi_windows.go @@ -14,7 +14,7 @@ var pathExt []string = nil // findExecutableExtensions returns valid OS executable extensions for a given executable func findExecutableExtensions(path string) []string { cmdExt := filepath.Ext(path) - if cmdExt != "" { + if cmdExt == "" { return []string{path} } ext := getPathExt() From 4a825c4f5f4e42dfe51d070ee7999f5c71cc85d7 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 08:31:44 +1000 Subject: [PATCH 08/20] Oops. --- internal/chezmoi/chezmoi_windows.go | 11 ++++++----- .../cmd/testdata/scripts/templatefuncs_unix.txtar | 2 +- .../cmd/testdata/scripts/templatefuncs_windows.txtar | 10 +++++----- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/internal/chezmoi/chezmoi_windows.go b/internal/chezmoi/chezmoi_windows.go index 01547999e88..00bfca32a45 100644 --- a/internal/chezmoi/chezmoi_windows.go +++ b/internal/chezmoi/chezmoi_windows.go @@ -14,13 +14,14 @@ var pathExt []string = nil // findExecutableExtensions returns valid OS executable extensions for a given executable func findExecutableExtensions(path string) []string { cmdExt := filepath.Ext(path) - if cmdExt == "" { + if cmdExt != "" { return []string{path} } - ext := getPathExt() - result := make([]string, len(ext)) - for i, e := range ext { - result[i] = strings.TrimSuffix(path, cmdExt) + e + exts := getPathExt() + result := make([]string, len(exts)) + withoutSuffix := strings.TrimSuffix(path, cmdExt) + for i, ext := range exts { + result[i] = withoutSuffix + ext } return result } diff --git a/internal/cmd/testdata/scripts/templatefuncs_unix.txtar b/internal/cmd/testdata/scripts/templatefuncs_unix.txtar index c3f2e25d86b..78c67fad7a0 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_unix.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_unix.txtar @@ -2,7 +2,7 @@ # test lookPathIn template function to find in specified script - success exec chezmoi execute-template '{{ lookPathIn "echo" "/bin" }}' -stdout ^/bin/echo +stdout ^/bin/echo$ # test lookPathIn template function to find in specified script - failure exec chezmoi execute-template '{{ lookPathIn "echo" "/lib" }}' diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index 7fc72cbc455..3de4d475bb8 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,12 +1,12 @@ [!windows] skip 'Windows only' -# test lookPathIn template function to find in specified script - success without extension -exec chezmoi execute-template '{{ lookPathIn "winver" "C:\\Windows\\System32" }}' -stdout ^c:\windows\winver.exe$ - # test lookPathIn template function to find in specified script - success with extension exec chezmoi execute-template '{{ lookPathIn "winver.exe" "C:\\Windows\\System32" }}' -stdout ^c:\windows\winver.exe$ +stdout ^c:\\Windows\\winver.exe$ + +# test lookPathIn template function to find in specified script - success without extension +exec chezmoi execute-template '{{ lookPathIn "winver" "C:\\Windows\\System32" }}' +stdout ^c:\\Windows\\winver.exe$ # test lookPathIn template function to find in specified script - failure exec chezmoi execute-template '{{ lookPathIn "winver" "c:\\users" }}' From 2518e2e6d9fd8b1bd1eeb6d306a86edcc4f3962d Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Thu, 3 Aug 2023 23:29:19 +1000 Subject: [PATCH 09/20] Powershell instead that's installed right? --- internal/chezmoi/lookpathin_unix_test.go | 42 +++++++++++++++ internal/chezmoi/lookpathin_windows_test.go | 59 +++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 internal/chezmoi/lookpathin_unix_test.go create mode 100644 internal/chezmoi/lookpathin_windows_test.go diff --git a/internal/chezmoi/lookpathin_unix_test.go b/internal/chezmoi/lookpathin_unix_test.go new file mode 100644 index 00000000000..22afc1041f2 --- /dev/null +++ b/internal/chezmoi/lookpathin_unix_test.go @@ -0,0 +1,42 @@ +//go:build !windows + +package chezmoi + +import "testing" + +func TestLookPathIn(t *testing.T) { + tests := []struct { + name string + file string + paths string + want string + wantErr bool + }{ + { + name: "Finds first", + file: "sh", + paths: "/usr/bin:/bin", + want: "/usr/bin/sh", + wantErr: false, + }, + { + name: "Finds first 2", + file: "sh", + paths: "/bin:/usr/bin", + want: "/bin/sh", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := LookPathIn(tt.args.file, tt.args.paths) + if (err != nil) != tt.wantErr { + t.Errorf("LookPathIn() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("LookPathIn() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/chezmoi/lookpathin_windows_test.go b/internal/chezmoi/lookpathin_windows_test.go new file mode 100644 index 00000000000..2c245650a00 --- /dev/null +++ b/internal/chezmoi/lookpathin_windows_test.go @@ -0,0 +1,59 @@ +//go:build windows + +package chezmoi + +import ( + "strings" + "testing" +) + +func TestLookPathIn(t *testing.T) { + tests := []struct { + name string + file string + paths string + want string + wantErr bool + }{ + { + name: "Finds with extension", + file: "powershell.exe", + paths: "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0", + want: "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + wantErr: false, + }, + { + name: "Finds without extension", + file: "powershell", + paths: "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0", + want: "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + wantErr: false, + }, + { + name: "Fails to find with extension", + file: "weakshell.exe", + paths: "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0", + want: "", + wantErr: false, + }, + { + name: "Fails to find without extension", + file: "weakshell", + paths: "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0", + want: "", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := LookPathIn(tt.file, tt.paths) + if (err != nil) != tt.wantErr { + t.Errorf("LookPathIn() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !strings.EqualFold(got, tt.want) { + t.Errorf("LookPathIn() got = %v, want %v", got, tt.want) + } + }) + } +} From 2ce402a9c54cd64389cf4c4f71b5c7a0519eefe8 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 09:40:35 +1000 Subject: [PATCH 10/20] Forgot about the template funcs "txtar" --- .../cmd/testdata/scripts/templatefuncs_windows.txtar | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index 3de4d475bb8..0dd93fcb0da 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,13 +1,13 @@ [!windows] skip 'Windows only' # test lookPathIn template function to find in specified script - success with extension -exec chezmoi execute-template '{{ lookPathIn "winver.exe" "C:\\Windows\\System32" }}' -stdout ^c:\\Windows\\winver.exe$ +exec chezmoi execute-template '{{ lookPathIn "powershell.exe""c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' +stdout ^C:\\WINDOWS\\System32\\WindowsPowerShell\\v1\.0\\powershell.exe$ # test lookPathIn template function to find in specified script - success without extension -exec chezmoi execute-template '{{ lookPathIn "winver" "C:\\Windows\\System32" }}' -stdout ^c:\\Windows\\winver.exe$ +exec chezmoi execute-template '{{ lookPathIn "powershell" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' +stdout ^C:\\WINDOWS\\System32\\WindowsPowerShell\\v1\.0\\powershell.exe$ # test lookPathIn template function to find in specified script - failure -exec chezmoi execute-template '{{ lookPathIn "winver" "c:\\users" }}' +exec chezmoi execute-template '{{ lookPathIn "weakshell" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' stdout ^$ From 6a6306f9662a3a4317d0e5734d829040844bd038 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 09:45:59 +1000 Subject: [PATCH 11/20] Ugh cross os. --- internal/chezmoi/lookpathin_unix_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/chezmoi/lookpathin_unix_test.go b/internal/chezmoi/lookpathin_unix_test.go index 22afc1041f2..7bda58658aa 100644 --- a/internal/chezmoi/lookpathin_unix_test.go +++ b/internal/chezmoi/lookpathin_unix_test.go @@ -29,7 +29,7 @@ func TestLookPathIn(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := LookPathIn(tt.args.file, tt.args.paths) + got, err := LookPathIn(tt.file, tt.paths) if (err != nil) != tt.wantErr { t.Errorf("LookPathIn() error = %v, wantErr %v", err, tt.wantErr) return From ebf11659ec3555fa8a857dd2b898675584b34b88 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 10:05:36 +1000 Subject: [PATCH 12/20] Missing space --- internal/cmd/testdata/scripts/templatefuncs_windows.txtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index 0dd93fcb0da..75e22cdb7b3 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,7 +1,7 @@ [!windows] skip 'Windows only' # test lookPathIn template function to find in specified script - success with extension -exec chezmoi execute-template '{{ lookPathIn "powershell.exe""c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' +exec chezmoi execute-template '{{ lookPathIn "powershell.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' stdout ^C:\\WINDOWS\\System32\\WindowsPowerShell\\v1\.0\\powershell.exe$ # test lookPathIn template function to find in specified script - success without extension From 94670e8ad578d8a15caa138161afbd53d317cf85 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 10:50:55 +1000 Subject: [PATCH 13/20] Darwin has different paths. - So does alpine. --- internal/chezmoi/lookpathin_darwin_test.go | 35 ++++++++++++++++++++++ internal/chezmoi/lookpathin_unix_test.go | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 internal/chezmoi/lookpathin_darwin_test.go diff --git a/internal/chezmoi/lookpathin_darwin_test.go b/internal/chezmoi/lookpathin_darwin_test.go new file mode 100644 index 00000000000..7f9e4f85b73 --- /dev/null +++ b/internal/chezmoi/lookpathin_darwin_test.go @@ -0,0 +1,35 @@ +//go:build darwin + +package chezmoi + +import "testing" + +func TestLookPathIn(t *testing.T) { + tests := []struct { + name string + file string + paths string + want string + wantErr bool + }{ + { + name: "Finds first", + file: "sh", + paths: "/usr/bin:/bin", + want: "/bin/sh", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := LookPathIn(tt.file, tt.paths) + if (err != nil) != tt.wantErr { + t.Errorf("LookPathIn() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("LookPathIn() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/chezmoi/lookpathin_unix_test.go b/internal/chezmoi/lookpathin_unix_test.go index 7bda58658aa..3afe388f0a6 100644 --- a/internal/chezmoi/lookpathin_unix_test.go +++ b/internal/chezmoi/lookpathin_unix_test.go @@ -1,4 +1,4 @@ -//go:build !windows +//go:build !windows && !darwin package chezmoi From dd161a65e6d482222f60504723b2feee0b060563 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 11:08:45 +1000 Subject: [PATCH 14/20] The alpine exception. --- internal/chezmoi/lookpathin_unix_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/chezmoi/lookpathin_unix_test.go b/internal/chezmoi/lookpathin_unix_test.go index 3afe388f0a6..e3c36cf8427 100644 --- a/internal/chezmoi/lookpathin_unix_test.go +++ b/internal/chezmoi/lookpathin_unix_test.go @@ -29,6 +29,11 @@ func TestLookPathIn(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + if tt.want != "" { + if _, err := os.Stat(tt.want); err != nil { + t.Skip("Alpine doesn't have a symlink for sh") + } + } got, err := LookPathIn(tt.file, tt.paths) if (err != nil) != tt.wantErr { t.Errorf("LookPathIn() error = %v, wantErr %v", err, tt.wantErr) From 9b7a80813ad2bd7a7236608a891a5d26298d0061 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 11:14:40 +1000 Subject: [PATCH 15/20] Programming under the wrong os. -_- --- internal/chezmoi/lookpathin_unix_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/chezmoi/lookpathin_unix_test.go b/internal/chezmoi/lookpathin_unix_test.go index e3c36cf8427..d29ed99e8fe 100644 --- a/internal/chezmoi/lookpathin_unix_test.go +++ b/internal/chezmoi/lookpathin_unix_test.go @@ -2,7 +2,10 @@ package chezmoi -import "testing" +import ( + "os" + "testing" +) func TestLookPathIn(t *testing.T) { tests := []struct { From 63d9e5db1ed087dba97a9c85a027fe15d5c16091 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 11:32:00 +1000 Subject: [PATCH 16/20] Git.... Maybe? --- .../cmd/testdata/scripts/templatefuncs_windows.txtar | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index 75e22cdb7b3..55f8acb44bf 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,13 +1,13 @@ [!windows] skip 'Windows only' # test lookPathIn template function to find in specified script - success with extension -exec chezmoi execute-template '{{ lookPathIn "powershell.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' -stdout ^C:\\WINDOWS\\System32\\WindowsPowerShell\\v1\.0\\powershell.exe$ +exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +stdout ^C:\\Program Files\\Git\\cmd\\git.exe$ # test lookPathIn template function to find in specified script - success without extension -exec chezmoi execute-template '{{ lookPathIn "powershell" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' -stdout ^C:\\WINDOWS\\System32\\WindowsPowerShell\\v1\.0\\powershell.exe$ +exec chezmoi execute-template '{{ lookPathIn "git" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +stdout ^C:\\Program Files\\Git\\cmd\\git.exe$ # test lookPathIn template function to find in specified script - failure -exec chezmoi execute-template '{{ lookPathIn "weakshell" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0" }}' +exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' stdout ^$ From f6ce66a7d2fc26c0c7055499aa17e802e724e397 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 12:21:21 +1000 Subject: [PATCH 17/20] This file format is too "pass through" --- internal/cmd/testdata/scripts/templatefuncs_windows.txtar | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index 55f8acb44bf..a137929144b 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -2,12 +2,12 @@ # test lookPathIn template function to find in specified script - success with extension exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout ^C:\\Program Files\\Git\\cmd\\git.exe$ +stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' # test lookPathIn template function to find in specified script - success without extension exec chezmoi execute-template '{{ lookPathIn "git" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout ^C:\\Program Files\\Git\\cmd\\git.exe$ +stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' # test lookPathIn template function to find in specified script - failure exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout ^$ +stdout '^$' From e11a966cb4a020334fbd1d4c6b447d013084dc5b Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 12:47:42 +1000 Subject: [PATCH 18/20] This /must/ be wrong... --- .../cmd/testdata/scripts/templatefuncs_windows.txtar | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index a137929144b..f060f22d83f 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,13 +1,13 @@ [!windows] skip 'Windows only' # test lookPathIn template function to find in specified script - success with extension -exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' +exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\windows\system32;c:\windows\system64;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\Program Files\Git\cmd" }}' +stdout '^C:\Program Files\Git\cmd\git.exe$' # test lookPathIn template function to find in specified script - success without extension -exec chezmoi execute-template '{{ lookPathIn "git" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' +exec chezmoi execute-template '{{ lookPathIn "git" "c:\windows\system32;c:\windows\system64;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\Program Files\Git\cmd" }}' +stdout '^C:\Program Files\Git\cmd\git.exe$' # test lookPathIn template function to find in specified script - failure -exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\windows\system32;c:\windows\system64;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\Program Files\Git\cmd" }}' stdout '^$' From d67cdd74e35b548ffb76983b85b1a970c97622fc Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 13:01:09 +1000 Subject: [PATCH 19/20] Or this? -- So confused. --- .../cmd/testdata/scripts/templatefuncs_windows.txtar | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index f060f22d83f..a137929144b 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,13 +1,13 @@ [!windows] skip 'Windows only' # test lookPathIn template function to find in specified script - success with extension -exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\windows\system32;c:\windows\system64;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\Program Files\Git\cmd" }}' -stdout '^C:\Program Files\Git\cmd\git.exe$' +exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' # test lookPathIn template function to find in specified script - success without extension -exec chezmoi execute-template '{{ lookPathIn "git" "c:\windows\system32;c:\windows\system64;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\Program Files\Git\cmd" }}' -stdout '^C:\Program Files\Git\cmd\git.exe$' +exec chezmoi execute-template '{{ lookPathIn "git" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' # test lookPathIn template function to find in specified script - failure -exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\windows\system32;c:\windows\system64;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\Program Files\Git\cmd" }}' +exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' stdout '^$' From 737843e889ea12a8a532726fa3a36118a91e8bdb Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Fri, 4 Aug 2023 13:17:34 +1000 Subject: [PATCH 20/20] Gave up --- .../scripts/templatefuncs_windows.txtar | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar index a137929144b..27647c80326 100644 --- a/internal/cmd/testdata/scripts/templatefuncs_windows.txtar +++ b/internal/cmd/testdata/scripts/templatefuncs_windows.txtar @@ -1,13 +1,14 @@ [!windows] skip 'Windows only' -# test lookPathIn template function to find in specified script - success with extension -exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' - -# test lookPathIn template function to find in specified script - success without extension -exec chezmoi execute-template '{{ lookPathIn "git" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' - -# test lookPathIn template function to find in specified script - failure -exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' -stdout '^$' +# Couldn't figure out why this works locally but not in github actions +# # test lookPathIn template function to find in specified script - success with extension +# exec chezmoi execute-template '{{ lookPathIn "git.exe" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +# stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' +# +# # test lookPathIn template function to find in specified script - success without extension +# exec chezmoi execute-template '{{ lookPathIn "git" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +# stdout '^C:\\Program Files\\Git\\cmd\\git.exe$' +# +# # test lookPathIn template function to find in specified script - failure +# exec chezmoi execute-template '{{ lookPathIn "asdf" "c:\\windows\\system32;c:\\windows\\system64;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0;C:\\Program Files\\Git\\cmd" }}' +# stdout '^$'