Shougo / denite.nvim

:dragon: Dark powered asynchronous unite all interfaces for Neovim/Vim8
Other
2.06k stars 216 forks source link

File source throws PermissionError if an unreadable file/directory in candidates #827

Closed orokasan closed 3 years ago

orokasan commented 3 years ago

Warning: I will close the issue without the minimal init.vim and the reproduction instructions.

Problems summary

After e0c8d50 and related commit, in file source, if candidates have unreadable file or directory, denite throws PermissionError [WinError 5]. I don't know this is a os related problem.

Expected

Environment Information (Required!)

Performance

Remote Plugins

health#provider#check

Clipboard (optional)

Python 2 provider (optional)

Python 3 provider (optional)

Python virtualenv

Ruby provider (optional)

Node.js provider (optional)

Perl provider (optional)

health#denite#check

denite.nvim

Provide a minimal init.vim with less than 50 lines (Required!)

set runtimepath+=~/.cache/dein/repos/github.com/Shougo/denite.nvim

How to reproduce problems from neovim startup (Required!)

  1. :Denite file:C\
  2. PermissionError occurs.
    
    [denite] file: invalid argument: "C"
    [denite] Traceback (most recent call last):
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\rplugin.py", line 28, in start
    [denite] return ui.start(args[0], context)
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 70, in start
    [denite] self._start_sources_queue(context)
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 170, in _start_sources_queue
    [denite] self._start(context['sources_queue'][0], context)
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 218, in _start
    [denite] self._gather_candidates()
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 854, in _gather_candidates
    [denite] self._denite.gather_candidates(self._context)
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\parent.py", line 48, in gather_candidates
    [denite] self._put('gather_candidates', [context])
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\parent.py", line 81, in _put
    [denite] return self._child.main(name, args, queue_id=0)
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\child.py", line 69, in main
    [denite] self.gather_candidates(args[0])
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\child.py", line 121, in gather_candidates
    [denite] candidates = self._gather_source_candidates(
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\child.py", line 394, in _gather_source_candidates
    [denite] candidates = source.gather_candidates(context)
    [denite] File "C:\Users\ork\.cache\dein\repos\github.com\Shougo\denite.nvim\rplugin\python3\denite\source\file\__init__.py", line 60, in gather_candidates
    [denite] fullpath = abspath(self.vim, f)
    [denite] File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\util.py", line 155, in abspath
    [denite] return str(Path(vim.call('getcwd')).joinpath(expand(path)).resolve())
    [denite] File "C:\Python38\lib\pathlib.py", line 1172, in resolve
    [denite] s = self._flavour.resolve(self, strict=strict)
    [denite] File "C:\Python38\lib\pathlib.py", line 205, in resolve
    [denite] s = self._ext_to_normal(_getfinalpathname(s))
    [denite] PermissionError: [WinError 5] アクセスが拒否されました。: 'C:\\Config.Msi' 
Shougo commented 3 years ago

Fixed.

orokasan commented 3 years ago

I checked 9848fc7 but above problem is probably not fixed.

[denite] file: invalid argument: "C"
[denite] Traceback (most recent call last):
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\rplugin.py", line 28, in start
[denite]     return ui.start(args[0], context)
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 70, in start
[denite]     self._start_sources_queue(context)
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 172, in _start_sources_queue
[denite]     self._start(context['sources_queue'][0], context)
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 220, in _start
[denite]     self._gather_candidates()
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\ui\default.py", line 856, in _gather_candidates
[denite]     self._denite.gather_candidates(self._context)
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\parent.py", line 48, in gather_candidates
[denite]     self._put('gather_candidates', [context])
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\parent.py", line 81, in _put
[denite]     return self._child.main(name, args, queue_id=0)
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\child.py", line 69, in main
[denite]     self.gather_candidates(args[0])
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\child.py", line 121, in gather_candidates
[denite]     candidates = self._gather_source_candidates(
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\child.py", line 394, in _gather_source_candidates
[denite]     candidates = source.gather_candidates(context)
[denite]   File "C:\Users\ork\.cache\dein\repos\github.com\Shougo\denite.nvim\rplugin\python3\denite\source\file\__init__.py", line 60, in gather_candidates
[denite]     fullpath = abspath(self.vim, f)
[denite]   File "C:/Users/ork/.cache/dein/repos/github.com/Shougo/denite.nvim/rplugin/python3\denite\util.py", line 169, in abspath
[denite]     path = path.resolve()
[denite]   File "C:\Python38\lib\pathlib.py", line 1172, in resolve
[denite]     s = self._flavour.resolve(self, strict=strict)
[denite]   File "C:\Python38\lib\pathlib.py", line 205, in resolve
[denite]     s = self._ext_to_normal(_getfinalpathname(s))
[denite] PermissionError: [WinError 5] アクセスが拒否されました。: 'C:\\Config.Msi'
[denite] Please execute :messages command.

Seems readable() cannot trap PermissionError on Windows. In defx.nvim, a similar problem fixed by try except statement. (I was faced that problem long ago) ref

Shougo commented 3 years ago

Really? I need to check the problem. Please wait.

Shougo commented 3 years ago

Please test the latest.

orokasan commented 3 years ago

I tested latest version but it isn't fixed. I tried this patch then fixed. but i don't know how it affects. Maybe only resolve() method causes error.

diff --git a/rplugin/python3/denite/source/file/__init__.py b/rplugin/python3/denite/source/file/__init__.py
index f0c5dac..97eae1d 100644
--- a/rplugin/python3/denite/source/file/__init__.py
+++ b/rplugin/python3/denite/source/file/__init__.py
@@ -62,7 +62,7 @@ class Source(Base):
                 f_path = Path(f)
                 abbr = (str(f_path.relative_to(path))
                         if fullpath != path and f.startswith(path + sep)
-                        else str(f_path.resolve())) + (
+                        else fullpath) + (
                             sep if f_path.is_dir() else '')
                 candidates.append({
                     'word': f,
diff --git a/rplugin/python3/denite/util.py b/rplugin/python3/denite/util.py
index c657811..d5a09ba 100644
--- a/rplugin/python3/denite/util.py
+++ b/rplugin/python3/denite/util.py
@@ -112,11 +112,11 @@ def load_external_module(base: str, module: str) -> None:

 def readable(path: Path) -> bool:
     try:
-        if access(str(path), R_OK) and path.stat():
+        if access(str(path), R_OK) and path.resolve():
             return True
         else:
             return False
-    except (Exception, OSError):
+    except Exception:
         return False

This patch is another solution, but Path.absolute() is undocumented method. (And I don't know why it is fixed)

diff --git a/rplugin/python3/denite/source/file/__init__.py b/rplugin/python3/denite/source/file/__init__.py
index f0c5dac..4000c97 100644
--- a/rplugin/python3/denite/source/file/__init__.py
+++ b/rplugin/python3/denite/source/file/__init__.py
@@ -62,7 +62,7 @@ class Source(Base):
                 f_path = Path(f)
                 abbr = (str(f_path.relative_to(path))
                         if fullpath != path and f.startswith(path + sep)
-                        else str(f_path.resolve())) + (
+                        else str(f_path.absolute())) + (
                             sep if f_path.is_dir() else '')
                 candidates.append({
                     'word': f,
diff --git a/rplugin/python3/denite/util.py b/rplugin/python3/denite/util.py
index c657811..178fa77 100644
--- a/rplugin/python3/denite/util.py
+++ b/rplugin/python3/denite/util.py
@@ -166,7 +166,7 @@ def abspath(vim: Nvim, pathstr: str) -> str:
     if not path.is_absolute():
         path = Path(vim.call('getcwd')).joinpath(pathstr)
     if readable(path):
-        path = path.resolve()
+        path = path.absolute()
     return str(path)
Shougo commented 3 years ago

OK. Please test the latest.

orokasan commented 3 years ago

confirm the problem is almost fixed. thanks! But this segment should be like below.

diff --git a/rplugin/python3/denite/source/file/__init__.py b/rplugin/python3/denite/source/file/__init__.py
index f0c5dac..944f7fc 100644
--- a/rplugin/python3/denite/source/file/__init__.py
+++ b/rplugin/python3/denite/source/file/__init__.py
@@ -62,8 +62,7 @@ class Source(Base):
                 f_path = Path(f)
                 abbr = (str(f_path.relative_to(path))
                         if fullpath != path and f.startswith(path + sep)
-                        else str(f_path.resolve())) + (
-                            sep if f_path.is_dir() else '')
+                        else fullpath) + (sep if f_path.is_dir() else '')
                 candidates.append({
                     'word': f,
                     'abbr': abbr,
Shougo commented 3 years ago

@orokasan Have you read the source code? resolve() is not included in the latest version file/__init__.py.

Question: Where is the diff bring from?

Shougo commented 3 years ago

Please check the latest version.

orokasan commented 3 years ago

I mean,

diff --git a/rplugin/python3/denite/source/file/__init__.py b/rplugin/python3/denite/source/file/__init__.py
index e9b6958..944f7fc 100644
--- a/rplugin/python3/denite/source/file/__init__.py
+++ b/rplugin/python3/denite/source/file/__init__.py
@@ -62,7 +62,7 @@ class Source(Base):
                 f_path = Path(f)
                 abbr = (str(f_path.relative_to(path))
                         if fullpath != path and f.startswith(path + sep)
-                        else (fullpath + sep if f_path.is_dir() else ''))
+                        else fullpath) + (sep if f_path.is_dir() else '')
                 candidates.append({
                     'word': f,
                     'abbr': abbr,
Shougo commented 3 years ago

It is the same of the latest.

orokasan commented 3 years ago

Oops, sorry. Ignore this. Thank you for your cooperation!