From e4caa87f12e05265290878d7b72f35c417c385b8 Mon Sep 17 00:00:00 2001 From: Martin Tournoij Date: Mon, 11 Sep 2017 12:59:18 +0100 Subject: [PATCH 1/2] Run dlv from a temporary directory This fixes two things: - My comments here: https://github.com/fatih/vim-go/pull/1390/commits/8d617ece1e74bddfe47b5d0bc06dd1f821b54fcf#r138018608 It's true that `:lcd` is only for the current window, but me personally I still wouldn't expect any user-visible changes in the current directory when using `:GoDebugStart`. - It prevents `dlv` from creating a binary in the directory. At best this is an annoying side-effect, but at worst it could cause people to lose files: consider what would happen if someone has a package named `foo` but also had a file named `foo` in that directory? If you always use `go install` (like I do) then this is fine, and `:GoDebugStart` creating this file can be rather surprising. Note: this PR requires this patch to work correctly: https://github.com/fatih/vim-go/pull/1435 --- autoload/go/debug.vim | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/autoload/go/debug.vim b/autoload/go/debug.vim index 96255476e9..07b2617bad 100644 --- a/autoload/go/debug.vim +++ b/autoload/go/debug.vim @@ -391,20 +391,33 @@ function! go#debug#StartWith(...) abort endif try + " Run dlv from a temporary directory so it won't put the binary in the + " current dir. We pass --wd= so the binary is still run from the current + " dir. + let original_dir = getcwd() + let tmp = fnamemodify(tempname(), ':h') + let pkgname = go#package#FromPath(bufname('')) + exe 'lcd ' . tmp + echohl SpecialKey | echomsg 'Starting GoDebug...' | echohl None let s:state['message'] = [] - exe 'lcd' fnamemodify(bufname(''), ':p:h') - let job = job_start(dlv . ' debug --headless --api-version=2 --log --listen=' . g:go_debug_address . ' --accept-multiclient ' . join(a:000, ' '), { - \ 'out_cb': function('s:starting'), - \ 'err_cb': function('s:starting'), - \ 'exit_cb': function('s:exit'), - \ 'stoponexit': 'kill', + + let l:cmd = printf('%s debug --headless --api-version=2 --log --listen=%s --wd=%s --accept-multiclient %s %s', + \ dlv, g:go_debug_address, original_dir, pkgname, join(a:000, ' ')) + + let job = job_start(l:cmd, { + \ 'out_cb': function('s:starting'), + \ 'err_cb': function('s:starting'), + \ 'exit_cb': function('s:exit'), + \ 'stoponexit': 'kill', \}) let ch = job_getchannel(job) let s:state['job'] = job catch echohl Error | echomsg v:exception | echohl None return + finally + exe 'lcd ' . original_dir endtry endfunction From 6aa7a2f8dca7a8bd086130d7110b4c20e000387c Mon Sep 17 00:00:00 2001 From: Martin Tournoij Date: Tue, 12 Sep 2017 10:23:18 +0100 Subject: [PATCH 2/2] Make temp dir in cross-platform way Since tempnam() seems to behave different on Linux and Windows. --- autoload/go/debug.vim | 2 +- autoload/go/util.vim | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/autoload/go/debug.vim b/autoload/go/debug.vim index 07b2617bad..c01d112d00 100644 --- a/autoload/go/debug.vim +++ b/autoload/go/debug.vim @@ -395,8 +395,8 @@ function! go#debug#StartWith(...) abort " current dir. We pass --wd= so the binary is still run from the current " dir. let original_dir = getcwd() - let tmp = fnamemodify(tempname(), ':h') let pkgname = go#package#FromPath(bufname('')) + let tmp = go#util#tempdir('vim-go-debug-') exe 'lcd ' . tmp echohl SpecialKey | echomsg 'Starting GoDebug...' | echohl None diff --git a/autoload/go/util.vim b/autoload/go/util.vim index d35783f3ba..60a4f31f27 100644 --- a/autoload/go/util.vim +++ b/autoload/go/util.vim @@ -299,4 +299,36 @@ function! go#util#GetLines() return buf endfunction +" Make a named temporary directory which starts with "prefix". +" +" Unfortunately Vim's tempname() is not portable enough across various systems; +" see: https://github.com/mattn/vim-go/pull/3#discussion_r138084911 +function! go#util#tempdir(prefix) abort + " See :help tempfile + if go#util#IsWin() + let l:dirs = [$TMP, $TEMP, 'c:\tmp', 'c:\temp'] + else + let l:dirs = [$TMPDIR, '/tmp', './', $HOME] + endif + + let l:dir = '' + for l:d in dirs + if !empty(l:d) && filewritable(l:d) == 2 + let l:dir = l:d + break + endif + endfor + + if l:dir == '' + echoerr 'Unable to find directory to store temporary directory in' + return + endif + + " Not great randomness, but "good enough" for our purpose here. + let l:rnd = sha256(printf('%s%s', localtime(), fnamemodify(bufname(''), ":p"))) + let l:tmp = printf("%s/%s%s", l:dir, a:prefix, l:rnd) + call mkdir(l:tmp, 'p', 0700) + return l:tmp +endfunction + " vim: sw=2 ts=2 et