Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e74253d

Browse files
Allow shallow cloning
1 parent aa4bc9d commit e74253d

3 files changed

Lines changed: 90 additions & 15 deletions

File tree

pre_commit/store.py

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import pre_commit.constants as C
1111
from pre_commit import file_lock
1212
from pre_commit import git
13+
from pre_commit.util import CalledProcessError
1314
from pre_commit.util import clean_path_on_failure
1415
from pre_commit.util import cmd_output
1516
from pre_commit.util import resource_text
@@ -121,10 +122,7 @@ def _get_result():
121122
return result
122123

123124
logger.info('Initializing environment for {}.'.format(repo))
124-
125-
directory = tempfile.mkdtemp(prefix='repo', dir=self.directory)
126-
with clean_path_on_failure(directory):
127-
make_strategy(directory)
125+
directory = make_strategy()
128126

129127
# Update our db with the created repo
130128
with self.connect() as db:
@@ -134,19 +132,50 @@ def _get_result():
134132
)
135133
return directory
136134

137-
def clone(self, repo, ref, deps=()):
138-
"""Clone the given url and checkout the specific ref."""
139-
def clone_strategy(directory):
140-
env = git.no_git_env()
135+
def _perform_safe_clone(self, clone_strategy):
136+
directory = tempfile.mkdtemp(prefix='repo', dir=self.directory)
137+
with clean_path_on_failure(directory):
138+
clone_strategy(directory)
139+
return directory
141140

142-
cmd = ('git', 'clone', '--no-checkout', repo, directory)
143-
cmd_output(*cmd, env=env)
141+
def _complete_clone(self, repo, ref, directory):
142+
"""Perform a complete clone of a repository and its submodules """
143+
env = git.no_git_env()
144144

145-
def _git_cmd(*args):
146-
return cmd_output('git', *args, cwd=directory, env=env)
145+
cmd = ('git', 'clone', '--no-checkout', repo, directory)
146+
cmd_output(*cmd, env=env)
147+
148+
def _git_cmd(*args):
149+
return cmd_output('git', *args, cwd=directory, env=env)
150+
151+
_git_cmd('reset', ref, '--hard')
152+
_git_cmd('submodule', 'update', '--init', '--recursive')
147153

148-
_git_cmd('reset', ref, '--hard')
149-
_git_cmd('submodule', 'update', '--init', '--recursive')
154+
def _shallow_clone(self, repo, ref, directory):
155+
"""Perform a shallow clone of a repository and its submodules """
156+
env = git.no_git_env()
157+
158+
def _git_cmd(*args):
159+
return cmd_output('git', *args, cwd=directory, env=env)
160+
161+
_git_cmd('init', '.')
162+
_git_cmd('remote', 'add', 'origin', repo)
163+
_git_cmd('fetch', 'origin', ref, '--depth=1')
164+
_git_cmd('checkout', ref)
165+
_git_cmd('submodule', 'update', '--init', '--recursive', '--depth=1')
166+
167+
def clone(self, repo, ref, deps=()):
168+
"""Clone the given url and checkout the specific ref."""
169+
170+
def clone_strategy():
171+
try:
172+
def shallow_clone(directory):
173+
self._shallow_clone(repo, ref, directory)
174+
return self._perform_safe_clone(shallow_clone)
175+
except CalledProcessError:
176+
def complete_clone(directory):
177+
self._complete_clone(repo, ref, directory)
178+
return self._perform_safe_clone(complete_clone)
150179

151180
return self._new_repo(repo, ref, deps, clone_strategy)
152181

@@ -173,8 +202,11 @@ def _git_cmd(*args):
173202
_git_cmd('add', '.')
174203
git.commit(repo=directory)
175204

205+
def make_strategy():
206+
return self._perform_safe_clone(make_local_strategy)
207+
176208
return self._new_repo(
177-
'local', C.LOCAL_REPO_VERSION, deps, make_local_strategy,
209+
'local', C.LOCAL_REPO_VERSION, deps, make_strategy,
178210
)
179211

180212
def _create_config_table_if_not_exists(self, db):

testing/util.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,8 @@ def git_commit(*args, **kwargs):
142142
if msg is not None: # allow skipping `-m` with `msg=None`
143143
cmd += ('-m', msg)
144144
return fn(*cmd, **kwargs)
145+
146+
147+
def git_ref_count(repo):
148+
_, out, _ = cmd_output('git', 'rev-list', '--all', '--count', cwd=repo)
149+
return int(out.split()[0])

tests/store_test.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
from pre_commit import git
1313
from pre_commit.store import _get_default_directory
1414
from pre_commit.store import Store
15+
from pre_commit.util import CalledProcessError
1516
from testing.fixtures import git_dir
1617
from testing.util import cwd
1718
from testing.util import git_commit
19+
from testing.util import git_ref_count
1820

1921

2022
def test_our_session_fixture_works():
@@ -81,6 +83,7 @@ def test_clone(store, tempdir_factory, log_info_mock):
8183
assert dirname.startswith('repo')
8284
# Should be checked out to the rev we specified
8385
assert git.head_rev(ret) == rev
86+
assert git_ref_count(ret) == 1
8487

8588
# Assert there's an entry in the sqlite db for this
8689
assert store.select_all_repos() == [(path, rev, ret)]
@@ -111,6 +114,41 @@ def test_clone_when_repo_already_exists(store):
111114
assert store.clone('fake_repo', 'fake_ref') == 'fake_path'
112115

113116

117+
def test_clone_shallow_failure_fallback_to_complete(
118+
store, tempdir_factory,
119+
log_info_mock,
120+
):
121+
path = git_dir(tempdir_factory)
122+
with cwd(path):
123+
git_commit()
124+
rev = git.head_rev(path)
125+
git_commit()
126+
127+
# Force shallow clone failure
128+
def fake_shallow_clone(self, *args, **kwargs):
129+
raise CalledProcessError(None, None, None)
130+
store._shallow_clone = fake_shallow_clone
131+
132+
ret = store.clone(path, rev)
133+
134+
# Should have printed some stuff
135+
assert log_info_mock.call_args_list[0][0][0].startswith(
136+
'Initializing environment for ',
137+
)
138+
139+
# Should return a directory inside of the store
140+
assert os.path.exists(ret)
141+
assert ret.startswith(store.directory)
142+
# Directory should start with `repo`
143+
_, dirname = os.path.split(ret)
144+
assert dirname.startswith('repo')
145+
# Should be checked out to the rev we specified
146+
assert git.head_rev(ret) == rev
147+
148+
# Assert there's an entry in the sqlite db for this
149+
assert store.select_all_repos() == [(path, rev, ret)]
150+
151+
114152
def test_create_when_directory_exists_but_not_db(store):
115153
# In versions <= 0.3.5, there was no sqlite db causing a need for
116154
# backward compatibility

0 commit comments

Comments
 (0)