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

Skip to content

Commit 49da1ba

Browse files
committed
Added the useful thinking bit of the autoupdate and tests.
1 parent d8f8f5e commit 49da1ba

5 files changed

Lines changed: 144 additions & 8 deletions

File tree

pre_commit/commands.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
import os
55
import pkg_resources
66
import stat
7+
from plumbum import local
8+
9+
from pre_commit.ordereddict import OrderedDict
10+
from pre_commit.repository import Repository
711

812

913
def install(runner):
@@ -29,3 +33,46 @@ def uninstall(runner):
2933
os.remove(runner.pre_commit_path)
3034
print('pre-commit uninstalled')
3135
return 0
36+
37+
38+
class RepositoryCannotBeUpdatedError(RuntimeError): pass
39+
40+
41+
def _update_repository(repo_config):
42+
"""Updates a repository to the tip of `master`. If the repository cannot
43+
be updated because a hook that is configured does not exist in `master`,
44+
this raises a RepositoryCannotBeUpdatedError
45+
46+
Args:
47+
repo_config - A config for a repository
48+
"""
49+
repo = Repository(repo_config)
50+
51+
with repo.in_checkout():
52+
local['git']['fetch']()
53+
head_sha = local['git']['rev-parse', 'origin/master']().strip()
54+
55+
# Don't bother trying to update if our sha is the same
56+
if head_sha == repo_config['sha']:
57+
return repo_config
58+
59+
# Construct a new config with the head sha
60+
new_config = OrderedDict(repo_config)
61+
new_config['sha'] = head_sha
62+
new_repo = Repository(new_config)
63+
64+
# See if any of our hooks were deleted with the new commits
65+
hooks = set(repo.hooks.keys())
66+
hooks_missing = hooks - (hooks & set(new_repo.manifest.keys()))
67+
if hooks_missing:
68+
raise RepositoryCannotBeUpdatedError(
69+
'Cannot update because the tip of master is missing these hooks:\n'
70+
'{0}'.format(', '.join(sorted(hooks_missing)))
71+
)
72+
73+
return new_config
74+
75+
76+
def autoupdate(runner):
77+
"""Auto-update the pre-commit config to the latest versions of repos."""
78+
pass

pre_commit/run.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,7 @@ def run(argv):
100100

101101
subparsers.add_parser('uninstall', help='Uninstall the pre-commit script.')
102102

103-
execute_hook = subparsers.add_parser(
104-
'execute-hook', help='Run a single hook.'
105-
)
106-
execute_hook.add_argument('hook', help='The hook-id to run.')
107-
execute_hook.add_argument(
108-
'--all-files', '-a', action='store_true', default=False,
109-
help='Run on all the files in the repo.',
110-
)
103+
subparsers.add_parser('autoupdate', help='Auto-update hooks config.')
111104

112105
run = subparsers.add_parser('run', help='Run hooks.')
113106
run.add_argument('hook', nargs='?', help='A single hook-id to run'),
@@ -130,6 +123,8 @@ def run(argv):
130123
return commands.install(runner)
131124
elif args.command == 'uninstall':
132125
return commands.uninstall(runner)
126+
elif args.command == 'autoupdate':
127+
return commands.autoupdate(runner)
133128
elif args.command == 'run':
134129
if args.hook:
135130
return run_single_hook(runner, args.hook, all_files=args.all_files)

testing/auto_namedtuple.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
import collections
3+
4+
def auto_namedtuple(classname='auto_namedtuple', **kwargs):
5+
"""Returns an automatic namedtuple object.
6+
7+
Args:
8+
classname - The class name for the returned object.
9+
**kwargs - Properties to give the returned object.
10+
"""
11+
return (collections.namedtuple(classname, kwargs.keys())(**kwargs))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- id: bar
2+
name: Bar
3+
entry: bar
4+
language: python

tests/commands_test.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11

2+
import jsonschema
23
import os
34
import os.path
45
import pkg_resources
6+
import pytest
7+
import shutil
58
import stat
9+
from plumbum import local
610

11+
from pre_commit import git
12+
from pre_commit.clientlib.validate_config import CONFIG_JSON_SCHEMA
13+
from pre_commit.clientlib.validate_config import validate_config_extra
714
from pre_commit.commands import install
15+
from pre_commit.commands import RepositoryCannotBeUpdatedError
816
from pre_commit.commands import uninstall
17+
from pre_commit.commands import _update_repository
18+
from pre_commit.ordereddict import OrderedDict
919
from pre_commit.runner import Runner
20+
from testing.auto_namedtuple import auto_namedtuple
21+
from testing.util import get_resource_path
1022

1123

1224
def test_install_pre_commit(empty_git_dir):
@@ -35,3 +47,70 @@ def test_uninstall(empty_git_dir):
3547
assert os.path.exists(runner.pre_commit_path)
3648
uninstall(runner)
3749
assert not os.path.exists(runner.pre_commit_path)
50+
51+
52+
@pytest.yield_fixture
53+
def up_to_date_repo(python_hooks_repo):
54+
config = OrderedDict((
55+
('repo', python_hooks_repo),
56+
('sha', git.get_head_sha(python_hooks_repo)),
57+
('hooks', [{'id': 'foo', 'files': ''}]),
58+
))
59+
jsonschema.validate([config], CONFIG_JSON_SCHEMA)
60+
validate_config_extra([config])
61+
yield auto_namedtuple(
62+
repo_config=config,
63+
python_hooks_repo=python_hooks_repo,
64+
)
65+
66+
67+
def test_up_to_date_repo(up_to_date_repo):
68+
input_sha = up_to_date_repo.repo_config['sha']
69+
ret = _update_repository(up_to_date_repo.repo_config)
70+
assert ret['sha'] == input_sha
71+
72+
73+
@pytest.yield_fixture
74+
def out_of_date_repo(python_hooks_repo):
75+
config = OrderedDict((
76+
('repo', python_hooks_repo),
77+
('sha', git.get_head_sha(python_hooks_repo)),
78+
('hooks', [{'id': 'foo', 'files': ''}]),
79+
))
80+
jsonschema.validate([config], CONFIG_JSON_SCHEMA)
81+
validate_config_extra([config])
82+
local['git']['commit', '--allow-empty', '-m', 'foo']()
83+
head_sha = git.get_head_sha(python_hooks_repo)
84+
yield auto_namedtuple(
85+
repo_config=config,
86+
head_sha=head_sha,
87+
python_hooks_repo=python_hooks_repo,
88+
)
89+
90+
91+
def test_out_of_date_repo(out_of_date_repo):
92+
ret = _update_repository(out_of_date_repo.repo_config)
93+
assert ret['sha'] == out_of_date_repo.head_sha
94+
95+
96+
@pytest.yield_fixture
97+
def hook_disappearing_repo(python_hooks_repo):
98+
config = OrderedDict((
99+
('repo', python_hooks_repo),
100+
('sha', git.get_head_sha(python_hooks_repo)),
101+
('hooks', [{'id': 'foo', 'files': ''}]),
102+
))
103+
jsonschema.validate([config], CONFIG_JSON_SCHEMA)
104+
validate_config_extra([config])
105+
shutil.copy(get_resource_path('manifest_without_foo.yaml'), 'manifest.yaml')
106+
local['git']['add', '.']()
107+
local['git']['commit', '-m', 'Remove foo']()
108+
yield auto_namedtuple(
109+
repo_config=config,
110+
python_hooks_repo=python_hooks_repo,
111+
)
112+
113+
114+
def test_hook_disppearing_repo_raises(hook_disappearing_repo):
115+
with pytest.raises(RepositoryCannotBeUpdatedError):
116+
_update_repository(hook_disappearing_repo.repo_config)

0 commit comments

Comments
 (0)