runtime(netrw): "O" in a local listing does not copy the file

Problem:  Pressing "O" in a local listing reports "cannot determine
          method" instead of copying the file to the current directory
          as documented in |netrw-O|.
Solution: Use the islocal argument of netrw#Obtain() instead of
          b:netrw_islocal, and copy the files from b:netrw_curdir.

b:netrw_islocal is only set when a file is marked while other files are
already marked, so without marks netrw#Obtain() took the remote branch.
The names in the listing are relative to b:netrw_curdir, which is not
vim's current directory when netrw obtains a file, so the local copy
command could not find them.

related: #21534

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Yoko Davis <56965728+revesis@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yoko DavisandClaude Opus 5.5 authored and Christian Brabandt committed 2026-10-21 15:57:34 +00:00
1 parent b6e28306e3
commit 98106548d0
2 files changed
+34 -1

No files matched your search

+3 -1
View File
@@ -964,10 +964,12 @@ function netrw#Obtain(islocal,fname,...)
let tgtdir= getcwd()
endif
if exists("b:netrw_islocal") && b:netrw_islocal
if a:islocal
" obtain a file from local b:netrw_curdir to (local) tgtdir
if exists("b:netrw_curdir") && getcwd() != b:netrw_curdir
let topath = netrw#fs#ComposePath(tgtdir,"")
" names in the listing are relative to b:netrw_curdir, not to vim's current directory
let fnamelist = map(copy(fnamelist), {_, fname -> isabsolutepath(fname) ? fname : netrw#fs#ComposePath(b:netrw_curdir, fname)})
if has("win32") && !g:netrw_cygwin
" transfer files one at time
for fname in fnamelist
+31
View File
@@ -691,6 +691,37 @@ func Test_netrw_obtain_reject_evil_hostname()
endtry
endfunc
" "O" in a local listing copies the file under the cursor to the current directory
func Test_netrw_obtain_local()
let dir = getcwd() .. '/Xnetrwobtain'
call mkdir(dir, 'pR')
call writefile(['obtained'], dir .. '/Xobtainfile')
try
exe 'Explore' dir
call search('^Xobtainfile$')
let msg = execute('normal O')
call assert_notmatch('cannot determine method', msg)
call assert_equal(['obtained'], readfile('Xobtainfile'))
" the same for marked files
call delete('Xobtainfile')
call writefile(['marked'], dir .. '/Xobtainmarked')
Explore
call search('^Xobtainfile$')
normal mf
call search('^Xobtainmarked$')
normal mf
let msg = execute('normal O')
call assert_notmatch('cannot determine method', msg)
call assert_equal(['obtained'], readfile('Xobtainfile'))
call assert_equal(['marked'], readfile('Xobtainmarked'))
finally
bwipe!
call delete('Xobtainfile')
call delete('Xobtainmarked')
endtry
endfunc
func Test_netrw_hostname()
let valid_hostnames = [
\ 'localhost',