From 641294465e20750b64b6984433fc2e5229c68044 Mon Sep 17 00:00:00 2001 From: w0rp Date: Thu, 14 May 2026 22:30:52 +0100 Subject: [PATCH] #5057: Avoid mixing slashes for Windows temporary files --- autoload/ale/command.vim | 2 +- autoload/ale/powershell.vim | 4 +-- test/handler/test_elmmake_handler.vader | 14 ++++----- test/test_format_command.vader | 13 +++++++++ test/test_powershell.vader | 39 +++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 test/test_powershell.vader diff --git a/autoload/ale/command.vim b/autoload/ale/command.vim index 4974a3407..ef3c4ed1d 100644 --- a/autoload/ale/command.vim +++ b/autoload/ale/command.vim @@ -142,7 +142,7 @@ function! s:TemporaryFilename(buffer) abort " Create a temporary filename, / " The file itself will not be created by this function. - return ale#util#Tempname() . (s:is_windows ? '\' : '/') . l:filename + return ale#path#GetAbsPath(ale#util#Tempname(), l:filename) endfunction " Given part of a command, replace any % with %%, so that no characters in diff --git a/autoload/ale/powershell.vim b/autoload/ale/powershell.vim index 8c1632065..66374dd98 100644 --- a/autoload/ale/powershell.vim +++ b/autoload/ale/powershell.vim @@ -8,8 +8,8 @@ function! s:TemporaryPSScript(buffer, input) abort " Create a temp dir to house our temp .ps1 script " a temp dir is needed as powershell needs the .ps1 " extension - let l:tempdir = ale#util#Tempname() . (has('win32') ? '\' : '/') - let l:tempscript = l:tempdir . l:filename + let l:tempscript = ale#path#GetAbsPath(ale#util#Tempname(), l:filename) + let l:tempdir = fnamemodify(l:tempscript, ':h') " Create the temporary directory for the file, unreadable by 'other' " users. call mkdir(l:tempdir, '', 0750) diff --git a/test/handler/test_elmmake_handler.vader b/test/handler/test_elmmake_handler.vader index f5906a8b3..7d50a4b8b 100644 --- a/test/handler/test_elmmake_handler.vader +++ b/test/handler/test_elmmake_handler.vader @@ -21,7 +21,7 @@ Execute(The elm-make handler should parse Elm 0.19 general problems correctly): \ ale_linters#elm#make#Handle(347, [ \ json_encode({ \ 'type': 'error', - \ 'path': ale#util#Tempname() . '/Module.elm', + \ 'path': ale#path#GetAbsPath(ale#util#Tempname(), 'Module.elm'), \ 'title': 'UNKNOWN IMPORT', \ 'message': ["error details\n\n", { 'string': 'styled details' }] \ }), @@ -60,7 +60,7 @@ Execute(The elm-make handler should parse Elm 0.19 compilation errors correctly) \ 'type': 'compile-errors', \ 'errors': [ \ { - \ 'path': ale#util#Tempname() . '/Module.elm', + \ 'path': ale#path#GetAbsPath(ale#util#Tempname(), 'Module.elm'), \ 'problems': [ \ { \ 'title': 'TYPE MISMATCH', @@ -186,7 +186,7 @@ Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly) \ 'details': 'warning details', \ 'region': {'start': { 'line': 33, 'column': 1 }, 'end': { 'line': 33, 'column': 19 } }, \ 'type': 'warning', - \ 'file': ale#util#Tempname() . '/Module.elm', + \ 'file': ale#path#GetAbsPath(ale#util#Tempname(), 'Module.elm'), \ } \ ]), \ json_encode([ @@ -197,7 +197,7 @@ Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly) \ 'details': 'error details 1', \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } }, \ 'type': 'error', - \ 'file': ale#util#Tempname() . '/Module.elm', + \ 'file': ale#path#GetAbsPath(ale#util#Tempname(), 'Module.elm'), \ }, \ { \ 'tag': 'TYPE MISMATCH', @@ -206,7 +206,7 @@ Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly) \ 'details': 'error details 2', \ 'region': { 'start': { 'line': 406, 'column': 5}, 'end': { 'line': 407, 'column': 17 } }, \ 'type':'error', - \ 'file': ale#util#Tempname() . '/Module.elm', + \ 'file': ale#path#GetAbsPath(ale#util#Tempname(), 'Module.elm'), \ }, \ { \ 'tag': 'TYPE MISMATCH', @@ -215,7 +215,7 @@ Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly) \ 'details': 'error details 3', \ 'region': { 'start': { 'line': 406, 'column': 5 }, 'end': { 'line': 406, 'column': 93 } }, \ 'type':'error', - \ 'file': ale#util#Tempname() . '/Module.elm', + \ 'file': ale#path#GetAbsPath(ale#util#Tempname(), 'Module.elm'), \ } \ ]), \ ]) @@ -276,7 +276,7 @@ Execute(The elm-make handler should put an error on the first line if a line can \ 'type': 'compile-errors', \ 'errors': [ \ { - \ 'path': ale#util#Tempname() . '/Module.elm', + \ 'path': ale#path#GetAbsPath(ale#util#Tempname(), 'Module.elm'), \ 'problems': [ \ { \ 'title': 'TYPE MISMATCH', diff --git a/test/test_format_command.vader b/test/test_format_command.vader index f318a681d..27674cff6 100644 --- a/test/test_format_command.vader +++ b/test/test_format_command.vader @@ -34,6 +34,7 @@ After: delfunction CheckTempFile delfunction GetTempBase + runtime autoload/ale/util.vim runtime autoload/ale/command.vim Execute(FormatCommand should do nothing to basic command strings): @@ -69,6 +70,18 @@ Execute(FormatCommand should convert %t to a new temporary filename): " The two temporary filenames formatted in should be the same. AssertEqual g:match[1], g:match[2] +Execute(FormatCommand should normalize mixed Windows temporary paths): + if has('win32') + function! ale#util#Tempname() abort + return 'D:/Personal/Temp/V6UA83E.tmp' + endfunction + + let g:result = ale#command#FormatCommand(bufnr('%'), '', '%t', 0, v:null, v:null, []) + + AssertEqual 'D:\Personal\Temp\V6UA83E.tmp\dummy.txt', g:result[0] + AssertEqual ale#Escape(g:result[0]), g:result[1] + endif + Execute(FormatCommand should not convert %t to a new temporary filename when the input is given as v:false): let g:result = ale#command#FormatCommand(bufnr('%'), '', 'foo %t bar %t', 0, v:false, v:null, []) diff --git a/test/test_powershell.vader b/test/test_powershell.vader new file mode 100644 index 000000000..657e5e88d --- /dev/null +++ b/test/test_powershell.vader @@ -0,0 +1,39 @@ +Before: + runtime autoload/ale/powershell.vim + + let g:ale_powershell_powershell_executable = 'pwsh' + +After: + if exists('g:tempname') + call delete(g:tempname, 'rf') + endif + + unlet! g:command + unlet! g:tempname + unlet! g:tempscript + unlet! g:ale_powershell_powershell_executable + + runtime autoload/ale/util.vim + +Execute(RunPowerShell should normalize mixed Windows temporary paths): + if has('win32') + let g:tempname = substitute(ale#util#Tempname(), '\\', '/', 'g') + + function! ale#util#Tempname() abort + return g:tempname + endfunction + + let g:tempscript = ale#path#GetAbsPath(g:tempname, 'script.ps1') + let g:command = ale#powershell#RunPowerShell( + \ bufnr(''), + \ 'powershell_powershell', + \ ['Write-Output ''ok'''], + \) + + AssertEqual + \ ale#Escape('pwsh') + \ . ' -Exe Bypass -NoProfile -File ' + \ . ale#Escape(g:tempscript) + \ . ' %t', + \ g:command + endif