Repository: pre-commit/pre-commit
Issue: hook using node doesn't work on FreeBSD

We have a hook using doctoc, the node package. I cannot install the hook, this is the output:

```
desktop1% pre-commit install --install-hooks                                                                                                                                                                                                  
pre-commit installed at .git/hooks/pre-commit
[INFO] Initializing environment for git@github.com:jockej/pre-commit-hooks.git.
[INFO] Initializing environment for https://github.com/thlorenz/doctoc.
[INFO] Initializing environment for https://gitlab.com/pycqa/flake8.
[INFO] Initializing environment for https://github.com/jorisroovers/gitlint.
[INFO] Installing environment for https://github.com/thlorenz/doctoc.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: CalledProcessError: command: ('/home/joakim/.cache/pre-commit/repoizbdwm4g/node_env-system/bin/node', '/usr/local/bin/npm', 'install', '-g', '.')
return code: 254
expected return code: 0
stdout: (none)
stderr:
    npm ERR! code ENOENT
    npm ERR! syscall chmod
    npm ERR! path /home/joakim/.cache/pre-commit/repoizbdwm4g/node_env-system/lib/node_modules/doctoc/doctoc.js
    npm ERR! errno -2
    npm ERR! enoent ENOENT: no such file or directory, chmod '/home/joakim/.cache/pre-commit/repoizbdwm4g/node_env-system/lib/node_modules/doctoc/doctoc.js'
    npm ERR! enoent This is related to npm not being able to find a file.
    npm ERR! enoent 
    
    npm ERR! A complete log of this run can be found in:
    npm ERR!     /home/joakim/.npm/_logs/2020-05-07T10_30_16_218Z-debug.log
    
Check the log at /home/joakim/.cache/pre-commit/pre-commit.log
```
These hooks all install and run perfectly on GNU/Linux.

I believe it happens because pre-commit tries to use the --prebuilt flag to nodeenv, however this doesn't work for FreeBSD since there are no prebuilt packages (the URL constructed gives a 404). I have node installed so it should be possible to use --system, but I haven't been able to make it work myself.

Nodeenv itself seems to work fine with --system.

Please let me know if I can help with trying things on FreeBSD.


Changed files:
tests/store_test.py, pre_commit/store.py

diff --git a/pre_commit/store.py b/pre_commit/store.py
index 8bcbf99..6d8c40a 100644
--- a/pre_commit/store.py
+++ b/pre_commit/store.py
@@ -30,10 +30,11 @@ def _get_default_directory() -> str:
     `Store.get_default_directory` can be mocked in tests and
     `_get_default_directory` can be tested.
     """
-    return os.environ.get('PRE_COMMIT_HOME') or os.path.join(
+    ret = os.environ.get('PRE_COMMIT_HOME') or os.path.join(
         os.environ.get('XDG_CACHE_HOME') or os.path.expanduser('~/.cache'),
         'pre-commit',
     )
+    return os.path.realpath(ret)
 
 
 class Store:
diff --git a/tests/store_test.py b/tests/store_test.py
index 5866616..6a4e900 100644
--- a/tests/store_test.py
+++ b/tests/store_test.py
@@ -25,7 +25,8 @@ def test_our_session_fixture_works():
 def test_get_default_directory_defaults_to_home():
     # Not we use the module level one which is not mocked
     ret = _get_default_directory()
-    assert ret == os.path.join(os.path.expanduser('~/.cache'), 'pre-commit')
+    expected = os.path.realpath(os.path.expanduser('~/.cache/pre-commit'))
+    assert ret == expected
 
 
 def test_adheres_to_xdg_specification():
@@ -33,7 +34,8 @@ def test_adheres_to_xdg_specification():
         os.environ, {'XDG_CACHE_HOME': '/tmp/fakehome'},
     ):
         ret = _get_default_directory()
-        assert ret == os.path.join('/tmp/fakehome', 'pre-commit')
+    expected = os.path.realpath('/tmp/fakehome/pre-commit')
+    assert ret == expected
 
 
 def test_uses_environment_variable_when_present():
@@ -41,7 +43,8 @@ def test_uses_environment_variable_when_present():
         os.environ, {'PRE_COMMIT_HOME': '/tmp/pre_commit_home'},
     ):
         ret = _get_default_directory()
-        assert ret == '/tmp/pre_commit_home'
+    expected = os.path.realpath('/tmp/pre_commit_home')
+    assert ret == expected
 
 
 def test_store_init(store):