We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
"Locking pre-commit directory" should only print if waiting for a lock
Otherwise this is just useless console noise

--- 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.path
7 import sqlite3
8 import tempfile
9 
10 from cached_property import cached_property
11 
12 import pre_commit.constants as C
13 from pre_commit import file_lock
14 from pre_commit.prefixed_command_runner import PrefixedCommandRunner
15 from pre_commit.util import clean_path_on_failure
16 from pre_commit.util import cmd_output
17 from pre_commit.util import copy_tree_to_path
18 from pre_commit.util import cwd
19 from pre_commit.util import no_git_env
20 from pre_commit.util import resource_filename
21 
22 
23 logger = logging.getLogger('pre_commit')
24 
25 
26 def _get_default_directory():
27     """Returns the default directory for the Store.  This is intentionally
28     underscored to indicate that `Store.get_default_directory` is the intended
29     way to get this information.  This is also done so
30     `Store.get_default_directory` can be mocked in tests and
31     `_get_default_directory` can be tested.
32     """
33     return os.environ.get(
34         'PRE_COMMIT_HOME',
35         os.path.join(os.path.expanduser('~'), '.pre-commit'),
36     )
37 
38 
39 class Store(object):
40     get_default_directory = staticmethod(_get_default_directory)
41     __created = False
42 
43     def __init__(self, directory=None):
44         if directory is None:
45             directory = self.get_default_directory()
46 
47         self.directory = directory
48 
49     @contextlib.contextmanager
50     def exclusive_lock(self, quiet=False):
51         if not quiet:
52             logger.info('Locking pre-commit directory')
53         with file_lock.lock(os.path.join(self.directory, '.lock')):
54             yield
55 
56     def _write_readme(self):
57         with io.open(os.path.join(self.directory, 'README'), 'w') as readme:
58             readme.write(
59                 'This directory is maintained by the pre-commit project.\n'
60                 'Learn more: https://github.com/pre-commit/pre-commit\n',
61             )
62 
63     def _write_sqlite_db(self):
64         # To avoid a race where someone ^Cs between db creation and execution
65         # of the CREATE TABLE statement
66         fd, tmpfile = tempfile.mkstemp(dir=self.directory)
67         # We'll be managing this file ourselves
68         os.close(fd)
69         # sqlite doesn't close its fd with its contextmanager >.<
70         # contextlib.closing fixes this.
71         # See: http://stackoverflow.com/a/28032829/812183
72         with contextlib.closing(sqlite3.connect(tmpfile)) as db:
73             db.executescript(
74                 'CREATE TABLE repos ('
75                 '    repo CHAR(255) NOT NULL,'
76                 '    ref CHAR(255) NOT NULL,'
77                 '    path CHAR(255) NOT NULL,'
78                 '    PRIMARY KEY (repo, ref)'
79                 ');',
80             )
81 
82         # Atomic file move
83         os.rename(tmpfile, self.db_path)
84 
85     def _create(self):
86         if not os.path.exists(self.directory):
87             os.makedirs(self.directory)
88             self._write_readme()
89 
90         if os.path.exists(self.db_path):
91             return
92         with self.exclusive_lock(quiet=True):
93             # Another process may have already completed this work
94             if os.path.exists(self.db_path):  # pragma: no cover (race)
95                 return
96             self._write_sqlite_db()
97 
98     def require_created(self):
99         """Require the pre-commit file store to be created."""
100         if not self.__created:
101             self._create()
102             self.__created = True
103 
104     def _new_repo(self, repo, ref, make_strategy):
105         self.require_created()
106 
107         def _get_result():
108             # Check if we already exist
109             with sqlite3.connect(self.db_path) as db:
110                 result = db.execute(
111                     'SELECT path FROM repos WHERE repo = ? AND ref = ?',
112                     [repo, ref],
113                 ).fetchone()
114                 if result:
115                     return result[0]
116 
117         result = _get_result()
118         if result:
119             return result
120         with self.exclusive_lock():
121             # Another process may have already completed this work
122             result = _get_result()
123             if result:  # pragma: no cover (race)
124                 return result
125 
126             logger.info('Initializing environment for {}.'.format(repo))
127 
128             directory = tempfile.mkdtemp(prefix='repo', dir=self.directory)
129             with clean_path_on_failure(directory):
130                 make_strategy(directory)
131 
132             # Update our db with the created repo
133             with sqlite3.connect(self.db_path) as db:
134                 db.execute(
135                     'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)',
136                     [repo, ref, directory],
137                 )
138         return directory
139 
140     def clone(self, repo, ref):
141         """Clone the given url and checkout the specific ref."""
142         def clone_strategy(directory):
143             cmd_output(
144                 'git', 'clone', '--no-checkout', repo, directory,
145                 env=no_git_env(),
146             )
147             with cwd(directory):
148                 cmd_output('git', 'reset', ref, '--hard', env=no_git_env())
149                 cmd_output(
150                     'git', 'submodule', 'update', '--init', '--recursive',
151                     env=no_git_env(),
152                 )
153 
154         return self._new_repo(repo, ref, clone_strategy)
155 
156     def make_local(self, deps):
157         def make_local_strategy(directory):
158             copy_tree_to_path(resource_filename('empty_template'), directory)
159         return self._new_repo(
160             'local:{}'.format(','.join(sorted(deps))), C.LOCAL_REPO_VERSION,
161             make_local_strategy,
162         )
163 
164     @cached_property
165     def cmd_runner(self):
166         return PrefixedCommandRunner(self.directory)
167 
168     @cached_property
169     def db_path(self):
170         return os.path.join(self.directory, 'db.db')
171
```

Path: `pre_commit/file_lock.py`
Content:
```
1 import contextlib
2 import errno
3 
4 
5 try:  # pragma: no cover (windows)
6     import msvcrt
7 
8     # https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/locking
9 
10     # on windows we lock "regions" of files, we don't care about the actual
11     # byte region so we'll just pick *some* number here.
12     _region = 0xffff
13 
14     @contextlib.contextmanager
15     def _locked(fileno):
16         while True:
17             try:
18                 msvcrt.locking(fileno, msvcrt.LK_LOCK, _region)
19             except OSError as e:
20                 # Locking violation. Returned when the _LK_LOCK or _LK_RLCK
21                 # flag is specified and the file cannot be locked after 10
22                 # attempts.
23                 if e.errno != errno.EDEADLOCK:
24                     raise
25             else:
26                 break
27 
28         try:
29             yield
30         finally:
31             # From cursory testing, it seems to get unlocked when the file is
32             # closed so this may not be necessary.
33             # The documentation however states:
34             # "Regions should be locked only briefly and should be unlocked
35             # before closing a file or exiting the program."
36             msvcrt.locking(fileno, msvcrt.LK_UNLCK, _region)
37 except ImportError:  # pragma: no cover (posix)
38     import fcntl
39 
40     @contextlib.contextmanager
41     def _locked(fileno):
42         fcntl.flock(fileno, fcntl.LOCK_EX)
43         try:
44             yield
45         finally:
46             fcntl.flock(fileno, fcntl.LOCK_UN)
47 
48 
49 @contextlib.contextmanager
50 def lock(path):
51     with open(path, 'a+') as f:
52         with _locked(f.fileno()):
53             yield
54
```
--- 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()

```

diff --git a/pre_commit/file_lock.py b/pre_commit/file_lock.py
--- a/pre_commit/file_lock.py
+++ b/pre_commit/file_lock.py
@@ -12,18 +12,22 @@
     _region = 0xffff
 
     @contextlib.contextmanager
-    def _locked(fileno):
-        while True:
-            try:
-                msvcrt.locking(fileno, msvcrt.LK_LOCK, _region)
-            except OSError as e:
-                # Locking violation. Returned when the _LK_LOCK or _LK_RLCK
-                # flag is specified and the file cannot be locked after 10
-                # attempts.
-                if e.errno != errno.EDEADLOCK:
-                    raise
-            else:
-                break
+    def _locked(fileno, blocked_cb):
+        try:
+            msvcrt.locking(fileno, msvcrt.LK_NBLCK, _region)
+        except IOError:
+            blocked_cb()
+            while True:
+                try:
+                    msvcrt.locking(fileno, msvcrt.LK_LOCK, _region)
+                except IOError as e:
+                    # Locking violation. Returned when the _LK_LOCK or _LK_RLCK
+                    # flag is specified and the file cannot be locked after 10
+                    # attempts.
+                    if e.errno != errno.EDEADLOCK:
+                        raise
+                else:
+                    break
 
         try:
             yield
@@ -38,8 +42,12 @@
     import fcntl
 
     @contextlib.contextmanager
-    def _locked(fileno):
-        fcntl.flock(fileno, fcntl.LOCK_EX)
+    def _locked(fileno, blocked_cb):
+        try:
+            fcntl.flock(fileno, fcntl.LOCK_EX | fcntl.LOCK_NB)
+        except IOError:
+            blocked_cb()
+            fcntl.flock(fileno, fcntl.LOCK_EX)
         try:
             yield
         finally:
@@ -47,7 +55,7 @@
 
 
 @contextlib.contextmanager
-def lock(path):
+def lock(path, blocked_cb):
     with open(path, 'a+') as f:
-        with _locked(f.fileno()):
+        with _locked(f.fileno(), blocked_cb):
             yield
diff --git a/pre_commit/store.py b/pre_commit/store.py
--- a/pre_commit/store.py
+++ b/pre_commit/store.py
@@ -47,10 +47,11 @@
         self.directory = directory
 
     @contextlib.contextmanager
-    def exclusive_lock(self, quiet=False):
-        if not quiet:
+    def exclusive_lock(self):
+        def blocked_cb():  # pragma: no cover (tests are single-process)
             logger.info('Locking pre-commit directory')
-        with file_lock.lock(os.path.join(self.directory, '.lock')):
+
+        with file_lock.lock(os.path.join(self.directory, '.lock'), blocked_cb):
             yield
 
     def _write_readme(self):
@@ -89,7 +90,7 @@
 
         if os.path.exists(self.db_path):
             return
-        with self.exclusive_lock(quiet=True):
+        with self.exclusive_lock():
             # Another process may have already completed this work
             if os.path.exists(self.db_path):  # pragma: no cover (race)
                 return

{"golden_diff": "diff --git a/pre_commit/file_lock.py b/pre_commit/file_lock.py\n--- a/pre_commit/file_lock.py\n+++ b/pre_commit/file_lock.py\n@@ -12,18 +12,22 @@\n     _region = 0xffff\n \n     @contextlib.contextmanager\n-    def _locked(fileno):\n-        while True:\n-            try:\n-                msvcrt.locking(fileno, msvcrt.LK_LOCK, _region)\n-            except OSError as e:\n-                # Locking violation. Returned when the _LK_LOCK or _LK_RLCK\n-                # flag is specified and the file cannot be locked after 10\n-                # attempts.\n-                if e.errno != errno.EDEADLOCK:\n-                    raise\n-            else:\n-                break\n+    def _locked(fileno, blocked_cb):\n+        try:\n+            msvcrt.locking(fileno, msvcrt.LK_NBLCK, _region)\n+        except IOError:\n+            blocked_cb()\n+            while True:\n+                try:\n+                    msvcrt.locking(fileno, msvcrt.LK_LOCK, _region)\n+                except IOError as e:\n+                    # Locking violation. Returned when the _LK_LOCK or _LK_RLCK\n+                    # flag is specified and the file cannot be locked after 10\n+                    # attempts.\n+                    if e.errno != errno.EDEADLOCK:\n+                        raise\n+                else:\n+                    break\n \n         try:\n             yield\n@@ -38,8 +42,12 @@\n     import fcntl\n \n     @contextlib.contextmanager\n-    def _locked(fileno):\n-        fcntl.flock(fileno, fcntl.LOCK_EX)\n+    def _locked(fileno, blocked_cb):\n+        try:\n+            fcntl.flock(fileno, fcntl.LOCK_EX | fcntl.LOCK_NB)\n+        except IOError:\n+            blocked_cb()\n+            fcntl.flock(fileno, fcntl.LOCK_EX)\n         try:\n             yield\n         finally:\n@@ -47,7 +55,7 @@\n \n \n @contextlib.contextmanager\n-def lock(path):\n+def lock(path, blocked_cb):\n     with open(path, 'a+') as f:\n-        with _locked(f.fileno()):\n+        with _locked(f.fileno(), blocked_cb):\n             yield\ndiff --git a/pre_commit/store.py b/pre_commit/store.py\n--- a/pre_commit/store.py\n+++ b/pre_commit/store.py\n@@ -47,10 +47,11 @@\n         self.directory = directory\n \n     @contextlib.contextmanager\n-    def exclusive_lock(self, quiet=False):\n-        if not quiet:\n+    def exclusive_lock(self):\n+        def blocked_cb():  # pragma: no cover (tests are single-process)\n             logger.info('Locking pre-commit directory')\n-        with file_lock.lock(os.path.join(self.directory, '.lock')):\n+\n+        with file_lock.lock(os.path.join(self.directory, '.lock'), blocked_cb):\n             yield\n \n     def _write_readme(self):\n@@ -89,7 +90,7 @@\n \n         if os.path.exists(self.db_path):\n             return\n-        with self.exclusive_lock(quiet=True):\n+        with self.exclusive_lock():\n             # Another process may have already completed this work\n             if os.path.exists(self.db_path):  # pragma: no cover (race)\n                 return\n", "issue": "\"Locking pre-commit directory\" should only print if waiting for a lock\nOtherwise this is just useless console noise\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport io\nimport logging\nimport os.path\nimport sqlite3\nimport tempfile\n\nfrom cached_property import cached_property\n\nimport pre_commit.constants as C\nfrom pre_commit import file_lock\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 copy_tree_to_path\nfrom pre_commit.util import cwd\nfrom pre_commit.util import no_git_env\nfrom pre_commit.util import resource_filename\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    __created = False\n\n    def __init__(self, directory=None):\n        if directory is None:\n            directory = self.get_default_directory()\n\n        self.directory = directory\n\n    @contextlib.contextmanager\n    def exclusive_lock(self, quiet=False):\n        if not quiet:\n            logger.info('Locking pre-commit directory')\n        with file_lock.lock(os.path.join(self.directory, '.lock')):\n            yield\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 not os.path.exists(self.directory):\n            os.makedirs(self.directory)\n            self._write_readme()\n\n        if os.path.exists(self.db_path):\n            return\n        with self.exclusive_lock(quiet=True):\n            # Another process may have already completed this work\n            if os.path.exists(self.db_path):  # pragma: no cover (race)\n                return\n            self._write_sqlite_db()\n\n    def require_created(self):\n        \"\"\"Require the pre-commit file store to be created.\"\"\"\n        if not self.__created:\n            self._create()\n            self.__created = True\n\n    def _new_repo(self, repo, ref, make_strategy):\n        self.require_created()\n\n        def _get_result():\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                    [repo, ref],\n                ).fetchone()\n                if result:\n                    return result[0]\n\n        result = _get_result()\n        if result:\n            return result\n        with self.exclusive_lock():\n            # Another process may have already completed this work\n            result = _get_result()\n            if result:  # pragma: no cover (race)\n                return result\n\n            logger.info('Initializing environment for {}.'.format(repo))\n\n            directory = tempfile.mkdtemp(prefix='repo', dir=self.directory)\n            with clean_path_on_failure(directory):\n                make_strategy(directory)\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                    [repo, ref, directory],\n                )\n        return directory\n\n    def clone(self, repo, ref):\n        \"\"\"Clone the given url and checkout the specific ref.\"\"\"\n        def clone_strategy(directory):\n            cmd_output(\n                'git', 'clone', '--no-checkout', repo, directory,\n                env=no_git_env(),\n            )\n            with cwd(directory):\n                cmd_output('git', 'reset', ref, '--hard', env=no_git_env())\n                cmd_output(\n                    'git', 'submodule', 'update', '--init', '--recursive',\n                    env=no_git_env(),\n                )\n\n        return self._new_repo(repo, ref, clone_strategy)\n\n    def make_local(self, deps):\n        def make_local_strategy(directory):\n            copy_tree_to_path(resource_filename('empty_template'), directory)\n        return self._new_repo(\n            'local:{}'.format(','.join(sorted(deps))), C.LOCAL_REPO_VERSION,\n            make_local_strategy,\n        )\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"}, {"content": "import contextlib\nimport errno\n\n\ntry:  # pragma: no cover (windows)\n    import msvcrt\n\n    # https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/locking\n\n    # on windows we lock \"regions\" of files, we don't care about the actual\n    # byte region so we'll just pick *some* number here.\n    _region = 0xffff\n\n    @contextlib.contextmanager\n    def _locked(fileno):\n        while True:\n            try:\n                msvcrt.locking(fileno, msvcrt.LK_LOCK, _region)\n            except OSError as e:\n                # Locking violation. Returned when the _LK_LOCK or _LK_RLCK\n                # flag is specified and the file cannot be locked after 10\n                # attempts.\n                if e.errno != errno.EDEADLOCK:\n                    raise\n            else:\n                break\n\n        try:\n            yield\n        finally:\n            # From cursory testing, it seems to get unlocked when the file is\n            # closed so this may not be necessary.\n            # The documentation however states:\n            # \"Regions should be locked only briefly and should be unlocked\n            # before closing a file or exiting the program.\"\n            msvcrt.locking(fileno, msvcrt.LK_UNLCK, _region)\nexcept ImportError:  # pragma: no cover (posix)\n    import fcntl\n\n    @contextlib.contextmanager\n    def _locked(fileno):\n        fcntl.flock(fileno, fcntl.LOCK_EX)\n        try:\n            yield\n        finally:\n            fcntl.flock(fileno, fcntl.LOCK_UN)\n\n\n@contextlib.contextmanager\ndef lock(path):\n    with open(path, 'a+') as f:\n        with _locked(f.fileno()):\n            yield\n", "path": "pre_commit/file_lock.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport io\nimport logging\nimport os.path\nimport sqlite3\nimport tempfile\n\nfrom cached_property import cached_property\n\nimport pre_commit.constants as C\nfrom pre_commit import file_lock\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 copy_tree_to_path\nfrom pre_commit.util import cwd\nfrom pre_commit.util import no_git_env\nfrom pre_commit.util import resource_filename\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    __created = False\n\n    def __init__(self, directory=None):\n        if directory is None:\n            directory = self.get_default_directory()\n\n        self.directory = directory\n\n    @contextlib.contextmanager\n    def exclusive_lock(self):\n        def blocked_cb():  # pragma: no cover (tests are single-process)\n            logger.info('Locking pre-commit directory')\n\n        with file_lock.lock(os.path.join(self.directory, '.lock'), blocked_cb):\n            yield\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 not os.path.exists(self.directory):\n            os.makedirs(self.directory)\n            self._write_readme()\n\n        if os.path.exists(self.db_path):\n            return\n        with self.exclusive_lock():\n            # Another process may have already completed this work\n            if os.path.exists(self.db_path):  # pragma: no cover (race)\n                return\n            self._write_sqlite_db()\n\n    def require_created(self):\n        \"\"\"Require the pre-commit file store to be created.\"\"\"\n        if not self.__created:\n            self._create()\n            self.__created = True\n\n    def _new_repo(self, repo, ref, make_strategy):\n        self.require_created()\n\n        def _get_result():\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                    [repo, ref],\n                ).fetchone()\n                if result:\n                    return result[0]\n\n        result = _get_result()\n        if result:\n            return result\n        with self.exclusive_lock():\n            # Another process may have already completed this work\n            result = _get_result()\n            if result:  # pragma: no cover (race)\n                return result\n\n            logger.info('Initializing environment for {}.'.format(repo))\n\n            directory = tempfile.mkdtemp(prefix='repo', dir=self.directory)\n            with clean_path_on_failure(directory):\n                make_strategy(directory)\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                    [repo, ref, directory],\n                )\n        return directory\n\n    def clone(self, repo, ref):\n        \"\"\"Clone the given url and checkout the specific ref.\"\"\"\n        def clone_strategy(directory):\n            cmd_output(\n                'git', 'clone', '--no-checkout', repo, directory,\n                env=no_git_env(),\n            )\n            with cwd(directory):\n                cmd_output('git', 'reset', ref, '--hard', env=no_git_env())\n                cmd_output(\n                    'git', 'submodule', 'update', '--init', '--recursive',\n                    env=no_git_env(),\n                )\n\n        return self._new_repo(repo, ref, clone_strategy)\n\n    def make_local(self, deps):\n        def make_local_strategy(directory):\n            copy_tree_to_path(resource_filename('empty_template'), directory)\n        return self._new_repo(\n            'local:{}'.format(','.join(sorted(deps))), C.LOCAL_REPO_VERSION,\n            make_local_strategy,\n        )\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"}, {"content": "import contextlib\nimport errno\n\n\ntry:  # pragma: no cover (windows)\n    import msvcrt\n\n    # https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/locking\n\n    # on windows we lock \"regions\" of files, we don't care about the actual\n    # byte region so we'll just pick *some* number here.\n    _region = 0xffff\n\n    @contextlib.contextmanager\n    def _locked(fileno, blocked_cb):\n        try:\n            msvcrt.locking(fileno, msvcrt.LK_NBLCK, _region)\n        except IOError:\n            blocked_cb()\n            while True:\n                try:\n                    msvcrt.locking(fileno, msvcrt.LK_LOCK, _region)\n                except IOError as e:\n                    # Locking violation. Returned when the _LK_LOCK or _LK_RLCK\n                    # flag is specified and the file cannot be locked after 10\n                    # attempts.\n                    if e.errno != errno.EDEADLOCK:\n                        raise\n                else:\n                    break\n\n        try:\n            yield\n        finally:\n            # From cursory testing, it seems to get unlocked when the file is\n            # closed so this may not be necessary.\n            # The documentation however states:\n            # \"Regions should be locked only briefly and should be unlocked\n            # before closing a file or exiting the program.\"\n            msvcrt.locking(fileno, msvcrt.LK_UNLCK, _region)\nexcept ImportError:  # pragma: no cover (posix)\n    import fcntl\n\n    @contextlib.contextmanager\n    def _locked(fileno, blocked_cb):\n        try:\n            fcntl.flock(fileno, fcntl.LOCK_EX | fcntl.LOCK_NB)\n        except IOError:\n            blocked_cb()\n            fcntl.flock(fileno, fcntl.LOCK_EX)\n        try:\n            yield\n        finally:\n            fcntl.flock(fileno, fcntl.LOCK_UN)\n\n\n@contextlib.contextmanager\ndef lock(path, blocked_cb):\n    with open(path, 'a+') as f:\n        with _locked(f.fileno(), blocked_cb):\n            yield\n", "path": "pre_commit/file_lock.py"}]}