prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Crash when /tmp is on a different device
  ```
  Traceback (most recent call last):
    File "/home/cameron/Workspace/hack16-llvm-lang/venv/bin/pre-commit", line 9, in <module>
      load_entry_point('pre-commit==0.4.0', 'console_scripts', 'pre-commit')()
    File "/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/main.py", line 136, in main
      'Command {0} failed to exit with a returncode'.format(args.command)
    File "/usr/lib64/python3.4/contextlib.py", line 77, in __exit__
      self.gen.throw(type, value, traceback)
    File "/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/error_handler.py", line 41, in error_handler
      traceback.format_exc(),
    File "/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/error_handler.py", line 24, in _log_and_exit
      store.require_created()
    File "/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/store.py", line 97, in require_created
      self._create()
    File "/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/store.py", line 90, in _create
      self._write_sqlite_db()
    File "/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/store.py", line 82, in _write_sqlite_db
      os.rename(tmpfile, self.db_path)
  OSError: [Errno 18] Invalid cross-device link: '/tmp/tmpz1pkyqsm' -> '/home/cameron/.pre-commit/db.db'
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pre_commit/store.py`
  Content:
  ```
  1 from __future__ import unicode_literals
  2 
  3 import contextlib
  4 import io
  5 import logging
  6 import os
  7 import os.path
  8 import sqlite3
  9 import tempfile
  10 
  11 from cached_property import cached_property
  12 
  13 from pre_commit.prefixed_command_runner import PrefixedCommandRunner
  14 from pre_commit.util import clean_path_on_failure
  15 from pre_commit.util import cmd_output
  16 from pre_commit.util import cwd
  17 
  18 
  19 logger = logging.getLogger('pre_commit')
  20 
  21 
  22 def _get_default_directory():
  23     """Returns the default directory for the Store.  This is intentionally
  24     underscored to indicate that `Store.get_default_directory` is the intended
  25     way to get this information.  This is also done so
  26     `Store.get_default_directory` can be mocked in tests and
  27     `_get_default_directory` can be tested.
  28     """
  29     return os.environ.get(
  30         'PRE_COMMIT_HOME',
  31         os.path.join(os.path.expanduser('~'), '.pre-commit'),
  32     )
  33 
  34 
  35 class Store(object):
  36     get_default_directory = staticmethod(_get_default_directory)
  37 
  38     class RepoPathGetter(object):
  39         def __init__(self, repo, sha, store):
  40             self._repo = repo
  41             self._sha = sha
  42             self._store = store
  43 
  44         @cached_property
  45         def repo_path(self):
  46             return self._store.clone(self._repo, self._sha)
  47 
  48     def __init__(self, directory=None):
  49         if directory is None:
  50             directory = self.get_default_directory()
  51 
  52         self.directory = directory
  53         self.__created = False
  54 
  55     def _write_readme(self):
  56         with io.open(os.path.join(self.directory, 'README'), 'w') as readme:
  57             readme.write(
  58                 'This directory is maintained by the pre-commit project.\n'
  59                 'Learn more: https://github.com/pre-commit/pre-commit\n'
  60             )
  61 
  62     def _write_sqlite_db(self):
  63         # To avoid a race where someone ^Cs between db creation and execution
  64         # of the CREATE TABLE statement
  65         fd, tmpfile = tempfile.mkstemp()
  66         # We'll be managing this file ourselves
  67         os.close(fd)
  68         # sqlite doesn't close its fd with its contextmanager >.<
  69         # contextlib.closing fixes this.
  70         # See: http://stackoverflow.com/a/28032829/812183
  71         with contextlib.closing(sqlite3.connect(tmpfile)) as db:
  72             db.executescript(
  73                 'CREATE TABLE repos ('
  74                 '    repo CHAR(255) NOT NULL,'
  75                 '    ref CHAR(255) NOT NULL,'
  76                 '    path CHAR(255) NOT NULL,'
  77                 '    PRIMARY KEY (repo, ref)'
  78                 ');'
  79             )
  80 
  81         # Atomic file move
  82         os.rename(tmpfile, self.db_path)
  83 
  84     def _create(self):
  85         if os.path.exists(self.db_path):
  86             return
  87         if not os.path.exists(self.directory):
  88             os.makedirs(self.directory)
  89             self._write_readme()
  90         self._write_sqlite_db()
  91 
  92     def require_created(self):
  93         """Require the pre-commit file store to be created."""
  94         if self.__created:
  95             return
  96 
  97         self._create()
  98         self.__created = True
  99 
  100     def clone(self, url, sha):
  101         """Clone the given url and checkout the specific sha."""
  102         self.require_created()
  103 
  104         # Check if we already exist
  105         with sqlite3.connect(self.db_path) as db:
  106             result = db.execute(
  107                 'SELECT path FROM repos WHERE repo = ? AND ref = ?',
  108                 [url, sha],
  109             ).fetchone()
  110             if result:
  111                 return result[0]
  112 
  113         logger.info('Initializing environment for {0}.'.format(url))
  114 
  115         dir = tempfile.mkdtemp(prefix='repo', dir=self.directory)
  116         with clean_path_on_failure(dir):
  117             cmd_output('git', 'clone', '--no-checkout', url, dir)
  118             with cwd(dir):
  119                 cmd_output('git', 'checkout', sha)
  120 
  121         # Update our db with the created repo
  122         with sqlite3.connect(self.db_path) as db:
  123             db.execute(
  124                 'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)',
  125                 [url, sha, dir],
  126             )
  127         return dir
  128 
  129     def get_repo_path_getter(self, repo, sha):
  130         return self.RepoPathGetter(repo, sha, self)
  131 
  132     @cached_property
  133     def cmd_runner(self):
  134         return PrefixedCommandRunner(self.directory)
  135 
  136     @cached_property
  137     def db_path(self):
  138         return os.path.join(self.directory, 'db.db')
  139
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/pre_commit/store.py b/pre_commit/store.py
  --- a/pre_commit/store.py
  +++ b/pre_commit/store.py
  @@ -62,7 +62,7 @@
       def _write_sqlite_db(self):
           # To avoid a race where someone ^Cs between db creation and execution
           # of the CREATE TABLE statement
  -        fd, tmpfile = tempfile.mkstemp()
  +        fd, tmpfile = tempfile.mkstemp(dir=self.directory)
           # We'll be managing this file ourselves
           os.close(fd)
           # sqlite doesn't close its fd with its contextmanager >.<
  
verification_info: {"golden_diff": "diff --git a/pre_commit/store.py b/pre_commit/store.py\n--- a/pre_commit/store.py\n+++ b/pre_commit/store.py\n@@ -62,7 +62,7 @@\n     def _write_sqlite_db(self):\n         # To avoid a race where someone ^Cs between db creation and execution\n         # of the CREATE TABLE statement\n-        fd, tmpfile = tempfile.mkstemp()\n+        fd, tmpfile = tempfile.mkstemp(dir=self.directory)\n         # We'll be managing this file ourselves\n         os.close(fd)\n         # sqlite doesn't close its fd with its contextmanager >.<\n", "issue": "Crash when /tmp is on a different device\n```\nTraceback (most recent call last):\n  File \"/home/cameron/Workspace/hack16-llvm-lang/venv/bin/pre-commit\", line 9, in <module>\n    load_entry_point('pre-commit==0.4.0', 'console_scripts', 'pre-commit')()\n  File \"/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/main.py\", line 136, in main\n    'Command {0} failed to exit with a returncode'.format(args.command)\n  File \"/usr/lib64/python3.4/contextlib.py\", line 77, in __exit__\n    self.gen.throw(type, value, traceback)\n  File \"/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/error_handler.py\", line 41, in error_handler\n    traceback.format_exc(),\n  File \"/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/error_handler.py\", line 24, in _log_and_exit\n    store.require_created()\n  File \"/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/store.py\", line 97, in require_created\n    self._create()\n  File \"/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/store.py\", line 90, in _create\n    self._write_sqlite_db()\n  File \"/home/cameron/Workspace/hack16-llvm-lang/venv/lib/python3.4/site-packages/pre_commit/store.py\", line 82, in _write_sqlite_db\n    os.rename(tmpfile, self.db_path)\nOSError: [Errno 18] Invalid cross-device link: '/tmp/tmpz1pkyqsm' -> '/home/cameron/.pre-commit/db.db'\n```\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport io\nimport logging\nimport os\nimport os.path\nimport sqlite3\nimport tempfile\n\nfrom cached_property import cached_property\n\nfrom pre_commit.prefixed_command_runner import PrefixedCommandRunner\nfrom pre_commit.util import clean_path_on_failure\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import cwd\n\n\nlogger = logging.getLogger('pre_commit')\n\n\ndef _get_default_directory():\n    \"\"\"Returns the default directory for the Store.  This is intentionally\n    underscored to indicate that `Store.get_default_directory` is the intended\n    way to get this information.  This is also done so\n    `Store.get_default_directory` can be mocked in tests and\n    `_get_default_directory` can be tested.\n    \"\"\"\n    return os.environ.get(\n        'PRE_COMMIT_HOME',\n        os.path.join(os.path.expanduser('~'), '.pre-commit'),\n    )\n\n\nclass Store(object):\n    get_default_directory = staticmethod(_get_default_directory)\n\n    class RepoPathGetter(object):\n        def __init__(self, repo, sha, store):\n            self._repo = repo\n            self._sha = sha\n            self._store = store\n\n        @cached_property\n        def repo_path(self):\n            return self._store.clone(self._repo, self._sha)\n\n    def __init__(self, directory=None):\n        if directory is None:\n            directory = self.get_default_directory()\n\n        self.directory = directory\n        self.__created = False\n\n    def _write_readme(self):\n        with io.open(os.path.join(self.directory, 'README'), 'w') as readme:\n            readme.write(\n                'This directory is maintained by the pre-commit project.\\n'\n                'Learn more: https://github.com/pre-commit/pre-commit\\n'\n            )\n\n    def _write_sqlite_db(self):\n        # To avoid a race where someone ^Cs between db creation and execution\n        # of the CREATE TABLE statement\n        fd, tmpfile = tempfile.mkstemp()\n        # We'll be managing this file ourselves\n        os.close(fd)\n        # sqlite doesn't close its fd with its contextmanager >.<\n        # contextlib.closing fixes this.\n        # See: http://stackoverflow.com/a/28032829/812183\n        with contextlib.closing(sqlite3.connect(tmpfile)) as db:\n            db.executescript(\n                'CREATE TABLE repos ('\n                '    repo CHAR(255) NOT NULL,'\n                '    ref CHAR(255) NOT NULL,'\n                '    path CHAR(255) NOT NULL,'\n                '    PRIMARY KEY (repo, ref)'\n                ');'\n            )\n\n        # Atomic file move\n        os.rename(tmpfile, self.db_path)\n\n    def _create(self):\n        if os.path.exists(self.db_path):\n            return\n        if not os.path.exists(self.directory):\n            os.makedirs(self.directory)\n            self._write_readme()\n        self._write_sqlite_db()\n\n    def require_created(self):\n        \"\"\"Require the pre-commit file store to be created.\"\"\"\n        if self.__created:\n            return\n\n        self._create()\n        self.__created = True\n\n    def clone(self, url, sha):\n        \"\"\"Clone the given url and checkout the specific sha.\"\"\"\n        self.require_created()\n\n        # Check if we already exist\n        with sqlite3.connect(self.db_path) as db:\n            result = db.execute(\n                'SELECT path FROM repos WHERE repo = ? AND ref = ?',\n                [url, sha],\n            ).fetchone()\n            if result:\n                return result[0]\n\n        logger.info('Initializing environment for {0}.'.format(url))\n\n        dir = tempfile.mkdtemp(prefix='repo', dir=self.directory)\n        with clean_path_on_failure(dir):\n            cmd_output('git', 'clone', '--no-checkout', url, dir)\n            with cwd(dir):\n                cmd_output('git', 'checkout', sha)\n\n        # Update our db with the created repo\n        with sqlite3.connect(self.db_path) as db:\n            db.execute(\n                'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)',\n                [url, sha, dir],\n            )\n        return dir\n\n    def get_repo_path_getter(self, repo, sha):\n        return self.RepoPathGetter(repo, sha, self)\n\n    @cached_property\n    def cmd_runner(self):\n        return PrefixedCommandRunner(self.directory)\n\n    @cached_property\n    def db_path(self):\n        return os.path.join(self.directory, 'db.db')\n", "path": "pre_commit/store.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport io\nimport logging\nimport os\nimport os.path\nimport sqlite3\nimport tempfile\n\nfrom cached_property import cached_property\n\nfrom pre_commit.prefixed_command_runner import PrefixedCommandRunner\nfrom pre_commit.util import clean_path_on_failure\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import cwd\n\n\nlogger = logging.getLogger('pre_commit')\n\n\ndef _get_default_directory():\n    \"\"\"Returns the default directory for the Store.  This is intentionally\n    underscored to indicate that `Store.get_default_directory` is the intended\n    way to get this information.  This is also done so\n    `Store.get_default_directory` can be mocked in tests and\n    `_get_default_directory` can be tested.\n    \"\"\"\n    return os.environ.get(\n        'PRE_COMMIT_HOME',\n        os.path.join(os.path.expanduser('~'), '.pre-commit'),\n    )\n\n\nclass Store(object):\n    get_default_directory = staticmethod(_get_default_directory)\n\n    class RepoPathGetter(object):\n        def __init__(self, repo, sha, store):\n            self._repo = repo\n            self._sha = sha\n            self._store = store\n\n        @cached_property\n        def repo_path(self):\n            return self._store.clone(self._repo, self._sha)\n\n    def __init__(self, directory=None):\n        if directory is None:\n            directory = self.get_default_directory()\n\n        self.directory = directory\n        self.__created = False\n\n    def _write_readme(self):\n        with io.open(os.path.join(self.directory, 'README'), 'w') as readme:\n            readme.write(\n                'This directory is maintained by the pre-commit project.\\n'\n                'Learn more: https://github.com/pre-commit/pre-commit\\n'\n            )\n\n    def _write_sqlite_db(self):\n        # To avoid a race where someone ^Cs between db creation and execution\n        # of the CREATE TABLE statement\n        fd, tmpfile = tempfile.mkstemp(dir=self.directory)\n        # We'll be managing this file ourselves\n        os.close(fd)\n        # sqlite doesn't close its fd with its contextmanager >.<\n        # contextlib.closing fixes this.\n        # See: http://stackoverflow.com/a/28032829/812183\n        with contextlib.closing(sqlite3.connect(tmpfile)) as db:\n            db.executescript(\n                'CREATE TABLE repos ('\n                '    repo CHAR(255) NOT NULL,'\n                '    ref CHAR(255) NOT NULL,'\n                '    path CHAR(255) NOT NULL,'\n                '    PRIMARY KEY (repo, ref)'\n                ');'\n            )\n\n        # Atomic file move\n        os.rename(tmpfile, self.db_path)\n\n    def _create(self):\n        if os.path.exists(self.db_path):\n            return\n        if not os.path.exists(self.directory):\n            os.makedirs(self.directory)\n            self._write_readme()\n        self._write_sqlite_db()\n\n    def require_created(self):\n        \"\"\"Require the pre-commit file store to be created.\"\"\"\n        if self.__created:\n            return\n\n        self._create()\n        self.__created = True\n\n    def clone(self, url, sha):\n        \"\"\"Clone the given url and checkout the specific sha.\"\"\"\n        self.require_created()\n\n        # Check if we already exist\n        with sqlite3.connect(self.db_path) as db:\n            result = db.execute(\n                'SELECT path FROM repos WHERE repo = ? AND ref = ?',\n                [url, sha],\n            ).fetchone()\n            if result:\n                return result[0]\n\n        logger.info('Initializing environment for {0}.'.format(url))\n\n        dir = tempfile.mkdtemp(prefix='repo', dir=self.directory)\n        with clean_path_on_failure(dir):\n            cmd_output('git', 'clone', '--no-checkout', url, dir)\n            with cwd(dir):\n                cmd_output('git', 'checkout', sha)\n\n        # Update our db with the created repo\n        with sqlite3.connect(self.db_path) as db:\n            db.execute(\n                'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)',\n                [url, sha, dir],\n            )\n        return dir\n\n    def get_repo_path_getter(self, repo, sha):\n        return self.RepoPathGetter(repo, sha, self)\n\n    @cached_property\n    def cmd_runner(self):\n        return PrefixedCommandRunner(self.directory)\n\n    @cached_property\n    def db_path(self):\n        return os.path.join(self.directory, 'db.db')\n", "path": "pre_commit/store.py"}]}