Repository: pre-commit/pre-commit

Issue:
Permission denied when installed this environment
Hello.

I'm not sure the permission is about the pre-commit but it looks likes so.

Here is my config

````yaml
- repo: git://github.com/dnephin/pre-commit-golang
  rev: master
  hooks:
    - id: go-fmt

- repo: git://github.com/golangci/golangci-lint
  rev: master
  hooks:
    - id: golangci-lint
      args:
      - --config .golangci.yml

- repo: git://github.com/detailyang/pre-commit-shell
  rev: v1.0.6
  hooks:
  - id: shell-lint
    args: [--color=always, "--exclude=SC1090,SC1091,SC2206"]
````

it looks like python3.7 shutil.rmtree raise the erorr as the following:
````python
An unexpected error has occurred: PermissionError: [Errno 13] Permission denied: '/Users/detailyang/.cache/pre-commit/repo2ba1f3b5/golangenv-default/pkg/mod/github.com/!burnt!sushi/toml@v0.3.1/.gitignore'
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 447, in _rmtree_safe_fd
    os.unlink(entry.name, dir_fd=topfd)
PermissionError: [Errno 13] Permission denied: '.gitignore'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/pre_commit/error_handler.py", line 46, in error_handler
    yield
  File "/usr/local/lib/python3.7/site-packages/pre_commit/main.py", line 294, in main
    return run(args.config, store, args)
  File "/usr/local/lib/python3.7/site-packages/pre_commit/commands/run.py", line 285, in run
    install_hook_envs(hooks, store)
  File "/usr/local/lib/python3.7/site-packages/pre_commit/repository.py", line 215, in install_hook_envs
    hook.install()
  File "/usr/local/lib/python3.7/site-packages/pre_commit/repository.py", line 90, in install
    rmtree(self.prefix.path(venv))
  File "/usr/local/lib/python3.7/site-packages/pre_commit/util.py", line 171, in rmtree
    shutil.rmtree(path, ignore_errors=False, onerror=handle_remove_readonly)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 491, in rmtree
    _rmtree_safe_fd(fd, path, onerror)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 429, in _rmtree_safe_fd
    _rmtree_safe_fd(dirfd, fullname, onerror)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 429, in _rmtree_safe_fd
    _rmtree_safe_fd(dirfd, fullname, onerror)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 429, in _rmtree_safe_fd
    _rmtree_safe_fd(dirfd, fullname, onerror)
  [Previous line repeated 2 more times]
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/shutil.py", line 449, in _rmtree_safe_fd
    onerror(os.unlink, fullname, sys.exc_info())
  File "/usr/local/lib/python3.7/site-packages/pre_commit/util.py", line 168, in handle_remove_readonly
    func(path)
PermissionError: [Errno 13] Permission denied: '/Users/detailyang/.cache/pre-commit/repo2ba1f3b5/golangenv-default/pkg/mod/github.com/!burnt!sushi/toml@v0.3.1/.gitignore'
````


Discussion:
It looks like the directory permission is not right (no w and x mode), See the below:

````bash
╰─λ ls -lah /Users/detailyang/.cache/pre-commit/repo2ba1f3b5/golangenv-default/pkg/mod/github.com/!burnt!sushi/                                                    0 < 19:58:09
dr-x------  detailyang  staff   -  Wed May 22 19:43:34 2019    toml@v0.3.1
````
The question is who is the bad bod create the `golangenv-default` ?
It's the go mod builtin feature (bug?), see https://github.com/golang/go/issues/27161 @absassi try `go clean -modcache`?
bummer, I'm not able to reproduce:

```console
(venv) asottile-mac:t asottile$ pre-commit install-hooks
[INFO] Initializing environment for git://github.com/golangci/golangci-lint.
[INFO] Installing environment for git://github.com/golangci/golangci-lint.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
(venv) asottile-mac:t asottile$ 
```
ahah! but I am able to reproduce by forcing go modules:

```console
(venv) asottile-mac:t asottile$ GO111MODULE=on pre-commit install-hooks
[INFO] Initializing environment for git://github.com/golangci/golangci-lint.
[INFO] Installing environment for git://github.com/golangci/golangci-lint.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: PermissionError: [Errno 13] Permission denied: '/Users/asottile/.cache/pre-commit/repofxcjmytd/golangenv-default/pkg/mod/gopkg.in/yaml.v2@v2.2.1/decode_test.go'
Check the log at /Users/asottile/.cache/pre-commit/pre-commit.log
```

Resolving patch:
diff --git a/pre_commit/util.py b/pre_commit/util.py
--- a/pre_commit/util.py
+++ b/pre_commit/util.py
@@ -158,13 +158,14 @@ def cmd_output(*cmd, **kwargs):
 
 def rmtree(path):
     """On windows, rmtree fails for readonly dirs."""
-    def handle_remove_readonly(func, path, exc):  # pragma: no cover (windows)
+    def handle_remove_readonly(func, path, exc):
         excvalue = exc[1]
         if (
                 func in (os.rmdir, os.remove, os.unlink) and
                 excvalue.errno == errno.EACCES
         ):
-            os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
+            for p in (path, os.path.dirname(path)):
+                os.chmod(p, os.stat(p).st_mode | stat.S_IWUSR)
             func(path)
         else:
             raise


Test patch:
diff --git a/tests/util_test.py b/tests/util_test.py
--- a/tests/util_test.py
+++ b/tests/util_test.py
@@ -1,6 +1,7 @@
 from __future__ import unicode_literals
 
 import os.path
+import stat
 
 import pytest
 
@@ -8,6 +9,7 @@
 from pre_commit.util import clean_path_on_failure
 from pre_commit.util import cmd_output
 from pre_commit.util import parse_version
+from pre_commit.util import rmtree
 from pre_commit.util import tmpdir
 
 
@@ -90,3 +92,14 @@ def test_parse_version():
     assert parse_version('0.0') == parse_version('0.0')
     assert parse_version('0.1') > parse_version('0.0')
     assert parse_version('2.1') >= parse_version('2')
+
+
+def test_rmtree_read_only_directories(tmpdir):
+    """Simulates the go module tree.  See #1042"""
+    tmpdir.join('x/y/z').ensure_dir().join('a').ensure()
+    mode = os.stat(str(tmpdir.join('x'))).st_mode
+    mode_no_w = mode & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)
+    tmpdir.join('x/y/z').chmod(mode_no_w)
+    tmpdir.join('x/y/z').chmod(mode_no_w)
+    tmpdir.join('x/y/z').chmod(mode_no_w)
+    rmtree(str(tmpdir.join('x')))