mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 08:14:42 +04:00
Use sqlite3 instead of symlinks for managing repositories
This commit is contained in:
parent
3babceb2ca
commit
56e5c4eb2d
3 changed files with 72 additions and 34 deletions
|
|
@ -1,9 +1,11 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import contextlib
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
import os.path
|
||||
import sqlite3
|
||||
import tempfile
|
||||
|
||||
from cached_property import cached_property
|
||||
|
|
@ -12,7 +14,6 @@ from pre_commit.prefixed_command_runner import PrefixedCommandRunner
|
|||
from pre_commit.util import clean_path_on_failure
|
||||
from pre_commit.util import cmd_output
|
||||
from pre_commit.util import cwd
|
||||
from pre_commit.util import hex_md5
|
||||
|
||||
|
||||
logger = logging.getLogger('pre_commit')
|
||||
|
|
@ -58,11 +59,35 @@ class Store(object):
|
|||
'Learn more: https://github.com/pre-commit/pre-commit\n'
|
||||
)
|
||||
|
||||
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()
|
||||
# We'll be managing this file ourselves
|
||||
os.close(fd)
|
||||
# sqlite doesn't close its fd with its contextmanager >.<
|
||||
# contextlib.closing fixes this.
|
||||
# See: http://stackoverflow.com/a/28032829/812183
|
||||
with contextlib.closing(sqlite3.connect(tmpfile)) as db:
|
||||
db.executescript(
|
||||
'CREATE TABLE repos ('
|
||||
' repo CHAR(255) NOT NULL,'
|
||||
' ref CHAR(255) NOT NULL,'
|
||||
' path CHAR(255) NOT NULL,'
|
||||
' PRIMARY KEY (repo, ref)'
|
||||
');'
|
||||
)
|
||||
|
||||
# Atomic file move
|
||||
os.rename(tmpfile, self.db_path)
|
||||
|
||||
def _create(self):
|
||||
if os.path.exists(self.directory):
|
||||
if os.path.exists(self.db_path):
|
||||
return
|
||||
os.makedirs(self.directory)
|
||||
self._write_readme()
|
||||
if not os.path.exists(self.directory):
|
||||
os.makedirs(self.directory)
|
||||
self._write_readme()
|
||||
self._write_sqlite_db()
|
||||
|
||||
def require_created(self):
|
||||
"""Require the pre-commit file store to be created."""
|
||||
|
|
@ -77,9 +102,13 @@ class Store(object):
|
|||
self.require_created()
|
||||
|
||||
# Check if we already exist
|
||||
sha_path = os.path.join(self.directory, sha + '_' + hex_md5(url))
|
||||
if os.path.exists(sha_path):
|
||||
return os.readlink(sha_path)
|
||||
with sqlite3.connect(self.db_path) as db:
|
||||
result = db.execute(
|
||||
'SELECT path FROM repos WHERE repo = ? AND ref = ?',
|
||||
[url, sha],
|
||||
).fetchone()
|
||||
if result:
|
||||
return result[0]
|
||||
|
||||
logger.info('Initializing environment for {0}.'.format(url))
|
||||
|
||||
|
|
@ -89,8 +118,12 @@ class Store(object):
|
|||
with cwd(dir):
|
||||
cmd_output('git', 'checkout', sha)
|
||||
|
||||
# Make a symlink from sha->repo
|
||||
os.symlink(dir, sha_path)
|
||||
# Update our db with the created repo
|
||||
with sqlite3.connect(self.db_path) as db:
|
||||
db.execute(
|
||||
'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)',
|
||||
[url, sha, dir],
|
||||
)
|
||||
return dir
|
||||
|
||||
def get_repo_path_getter(self, repo, sha):
|
||||
|
|
@ -99,3 +132,7 @@ class Store(object):
|
|||
@cached_property
|
||||
def cmd_runner(self):
|
||||
return PrefixedCommandRunner(self.directory)
|
||||
|
||||
@cached_property
|
||||
def db_path(self):
|
||||
return os.path.join(self.directory, 'db.db')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue