2025-02-09 21:33:11 +01:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2025-02-09 21:10:22 +01:00
|
|
|
import shlex
|
2025-02-09 21:23:17 +01:00
|
|
|
from unittest import mock
|
2025-02-09 21:10:22 +01:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
import pre_commit.constants as C
|
2025-02-09 21:31:47 +01:00
|
|
|
from pre_commit import envcontext
|
2025-02-09 21:10:22 +01:00
|
|
|
from pre_commit import git
|
2025-02-09 21:36:17 +01:00
|
|
|
from pre_commit import yaml
|
2025-02-09 21:10:22 +01:00
|
|
|
from pre_commit.commands.autoupdate import _check_hooks_still_exist_at_rev
|
|
|
|
from pre_commit.commands.autoupdate import autoupdate
|
|
|
|
from pre_commit.commands.autoupdate import RepositoryCannotBeUpdatedError
|
|
|
|
from pre_commit.commands.autoupdate import RevInfo
|
|
|
|
from pre_commit.util import cmd_output
|
|
|
|
from testing.auto_namedtuple import auto_namedtuple
|
|
|
|
from testing.fixtures import add_config_to_repo
|
|
|
|
from testing.fixtures import make_config_from_repo
|
|
|
|
from testing.fixtures import make_repo
|
|
|
|
from testing.fixtures import modify_manifest
|
|
|
|
from testing.fixtures import read_config
|
|
|
|
from testing.fixtures import sample_local_config
|
|
|
|
from testing.fixtures import write_config
|
|
|
|
from testing.util import git_commit
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def up_to_date(tempdir_factory):
|
|
|
|
yield make_repo(tempdir_factory, 'python_hooks_repo')
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def out_of_date(tempdir_factory):
|
|
|
|
path = make_repo(tempdir_factory, 'python_hooks_repo')
|
|
|
|
original_rev = git.head_rev(path)
|
|
|
|
|
|
|
|
git_commit(cwd=path)
|
|
|
|
head_rev = git.head_rev(path)
|
|
|
|
|
|
|
|
yield auto_namedtuple(
|
|
|
|
path=path, original_rev=original_rev, head_rev=head_rev,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def tagged(out_of_date):
|
|
|
|
cmd_output('git', 'tag', 'v1.2.3', cwd=out_of_date.path)
|
|
|
|
yield out_of_date
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def hook_disappearing(tempdir_factory):
|
|
|
|
path = make_repo(tempdir_factory, 'python_hooks_repo')
|
|
|
|
original_rev = git.head_rev(path)
|
|
|
|
|
|
|
|
with modify_manifest(path) as manifest:
|
|
|
|
manifest[0]['id'] = 'bar'
|
|
|
|
|
|
|
|
yield auto_namedtuple(path=path, original_rev=original_rev)
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_from_config():
|
|
|
|
info = RevInfo.from_config({'repo': 'repo/path', 'rev': 'v1.2.3'})
|
|
|
|
assert info == RevInfo('repo/path', 'v1.2.3', None)
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_update_up_to_date_repo(up_to_date):
|
|
|
|
config = make_config_from_repo(up_to_date)
|
2025-02-09 21:41:54 +01:00
|
|
|
info = RevInfo.from_config(config)._replace(hook_ids=frozenset(('foo',)))
|
2025-02-09 21:10:22 +01:00
|
|
|
new_info = info.update(tags_only=False, freeze=False)
|
|
|
|
assert info == new_info
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_update_out_of_date_repo(out_of_date):
|
|
|
|
config = make_config_from_repo(
|
|
|
|
out_of_date.path, rev=out_of_date.original_rev,
|
|
|
|
)
|
|
|
|
info = RevInfo.from_config(config)
|
|
|
|
new_info = info.update(tags_only=False, freeze=False)
|
|
|
|
assert new_info.rev == out_of_date.head_rev
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_update_non_master_default_branch(out_of_date):
|
|
|
|
# change the default branch to be not-master
|
|
|
|
cmd_output('git', '-C', out_of_date.path, 'branch', '-m', 'dev')
|
|
|
|
test_rev_info_update_out_of_date_repo(out_of_date)
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_update_tags_even_if_not_tags_only(tagged):
|
|
|
|
config = make_config_from_repo(tagged.path, rev=tagged.original_rev)
|
|
|
|
info = RevInfo.from_config(config)
|
|
|
|
new_info = info.update(tags_only=False, freeze=False)
|
|
|
|
assert new_info.rev == 'v1.2.3'
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_update_tags_only_does_not_pick_tip(tagged):
|
|
|
|
git_commit(cwd=tagged.path)
|
|
|
|
config = make_config_from_repo(tagged.path, rev=tagged.original_rev)
|
|
|
|
info = RevInfo.from_config(config)
|
|
|
|
new_info = info.update(tags_only=True, freeze=False)
|
|
|
|
assert new_info.rev == 'v1.2.3'
|
|
|
|
|
|
|
|
|
2025-02-09 21:33:11 +01:00
|
|
|
def test_rev_info_update_tags_prefers_version_tag(tagged, out_of_date):
|
|
|
|
cmd_output('git', 'tag', 'latest', cwd=out_of_date.path)
|
|
|
|
config = make_config_from_repo(tagged.path, rev=tagged.original_rev)
|
|
|
|
info = RevInfo.from_config(config)
|
|
|
|
new_info = info.update(tags_only=True, freeze=False)
|
|
|
|
assert new_info.rev == 'v1.2.3'
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_update_tags_non_version_tag(out_of_date):
|
|
|
|
cmd_output('git', 'tag', 'latest', cwd=out_of_date.path)
|
|
|
|
config = make_config_from_repo(
|
|
|
|
out_of_date.path, rev=out_of_date.original_rev,
|
|
|
|
)
|
|
|
|
info = RevInfo.from_config(config)
|
|
|
|
new_info = info.update(tags_only=True, freeze=False)
|
|
|
|
assert new_info.rev == 'latest'
|
|
|
|
|
|
|
|
|
2025-02-09 21:10:22 +01:00
|
|
|
def test_rev_info_update_freeze_tag(tagged):
|
|
|
|
git_commit(cwd=tagged.path)
|
|
|
|
config = make_config_from_repo(tagged.path, rev=tagged.original_rev)
|
|
|
|
info = RevInfo.from_config(config)
|
|
|
|
new_info = info.update(tags_only=True, freeze=True)
|
|
|
|
assert new_info.rev == tagged.head_rev
|
|
|
|
assert new_info.frozen == 'v1.2.3'
|
|
|
|
|
|
|
|
|
|
|
|
def test_rev_info_update_does_not_freeze_if_already_sha(out_of_date):
|
|
|
|
config = make_config_from_repo(
|
|
|
|
out_of_date.path, rev=out_of_date.original_rev,
|
|
|
|
)
|
|
|
|
info = RevInfo.from_config(config)
|
|
|
|
new_info = info.update(tags_only=True, freeze=True)
|
|
|
|
assert new_info.rev == out_of_date.head_rev
|
|
|
|
assert new_info.frozen is None
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_up_to_date_repo(up_to_date, tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
contents = (
|
|
|
|
f'repos:\n'
|
|
|
|
f'- repo: {up_to_date}\n'
|
|
|
|
f' rev: {git.head_rev(up_to_date)}\n'
|
|
|
|
f' hooks:\n'
|
|
|
|
f' - id: foo\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(contents)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
assert cfg.read() == contents
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_old_revision_broken(tempdir_factory, in_tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
"""In $FUTURE_VERSION, hooks.yaml will no longer be supported. This
|
|
|
|
asserts that when that day comes, pre-commit will be able to autoupdate
|
|
|
|
despite not being able to read hooks.yaml in that repository.
|
|
|
|
"""
|
|
|
|
path = make_repo(tempdir_factory, 'python_hooks_repo')
|
|
|
|
config = make_config_from_repo(path, check=False)
|
|
|
|
|
|
|
|
cmd_output('git', 'mv', C.MANIFEST_FILE, 'nope.yaml', cwd=path)
|
|
|
|
git_commit(cwd=path)
|
|
|
|
# Assume this is the revision the user's old repository was at
|
|
|
|
rev = git.head_rev(path)
|
|
|
|
cmd_output('git', 'mv', 'nope.yaml', C.MANIFEST_FILE, cwd=path)
|
|
|
|
git_commit(cwd=path)
|
|
|
|
update_rev = git.head_rev(path)
|
|
|
|
|
|
|
|
config['rev'] = rev
|
|
|
|
write_config('.', config)
|
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
before = f.read()
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
after = f.read()
|
|
|
|
assert before != after
|
|
|
|
assert update_rev in after
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_out_of_date_repo(out_of_date, tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
fmt = (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: {}\n'
|
|
|
|
' rev: {}\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(fmt.format(out_of_date.path, out_of_date.original_rev))
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
assert cfg.read() == fmt.format(out_of_date.path, out_of_date.head_rev)
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_with_core_useBuiltinFSMonitor(out_of_date, tmpdir):
|
2025-02-09 21:31:47 +01:00
|
|
|
# force the setting on "globally" for git
|
|
|
|
home = tmpdir.join('fakehome').ensure_dir()
|
|
|
|
home.join('.gitconfig').write('[core]\nuseBuiltinFSMonitor = true\n')
|
|
|
|
with envcontext.envcontext((('HOME', str(home)),)):
|
2025-02-09 21:41:54 +01:00
|
|
|
test_autoupdate_out_of_date_repo(out_of_date, tmpdir)
|
2025-02-09 21:31:47 +01:00
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_pure_yaml(out_of_date, tmpdir):
|
2025-02-09 21:36:17 +01:00
|
|
|
with mock.patch.object(yaml, 'Dumper', yaml.yaml.SafeDumper):
|
2025-02-09 21:41:54 +01:00
|
|
|
test_autoupdate_out_of_date_repo(out_of_date, tmpdir)
|
2025-02-09 21:23:17 +01:00
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_only_one_to_update(up_to_date, out_of_date, tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
fmt = (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: {}\n'
|
|
|
|
' rev: {}\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
'- repo: {}\n'
|
|
|
|
' rev: {}\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
before = fmt.format(
|
|
|
|
up_to_date, git.head_rev(up_to_date),
|
|
|
|
out_of_date.path, out_of_date.original_rev,
|
|
|
|
)
|
|
|
|
cfg.write(before)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
assert cfg.read() == fmt.format(
|
|
|
|
up_to_date, git.head_rev(up_to_date),
|
|
|
|
out_of_date.path, out_of_date.head_rev,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def test_autoupdate_out_of_date_repo_with_correct_repo_name(
|
2025-02-09 21:41:54 +01:00
|
|
|
out_of_date, in_tmpdir,
|
2025-02-09 21:10:22 +01:00
|
|
|
):
|
|
|
|
stale_config = make_config_from_repo(
|
|
|
|
out_of_date.path, rev=out_of_date.original_rev, check=False,
|
|
|
|
)
|
|
|
|
local_config = sample_local_config()
|
|
|
|
config = {'repos': [stale_config, local_config]}
|
|
|
|
write_config('.', config)
|
|
|
|
|
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
before = f.read()
|
|
|
|
repo_name = f'file://{out_of_date.path}'
|
|
|
|
ret = autoupdate(
|
2025-02-09 21:41:54 +01:00
|
|
|
C.CONFIG_FILE, freeze=False, tags_only=False,
|
2025-02-09 21:10:22 +01:00
|
|
|
repos=(repo_name,),
|
|
|
|
)
|
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
after = f.read()
|
|
|
|
assert ret == 0
|
|
|
|
assert before != after
|
|
|
|
assert out_of_date.head_rev in after
|
|
|
|
assert 'local' in after
|
|
|
|
|
|
|
|
|
|
|
|
def test_autoupdate_out_of_date_repo_with_wrong_repo_name(
|
2025-02-09 21:41:54 +01:00
|
|
|
out_of_date, in_tmpdir,
|
2025-02-09 21:10:22 +01:00
|
|
|
):
|
|
|
|
config = make_config_from_repo(
|
|
|
|
out_of_date.path, rev=out_of_date.original_rev, check=False,
|
|
|
|
)
|
|
|
|
write_config('.', config)
|
|
|
|
|
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
before = f.read()
|
|
|
|
# It will not update it, because the name doesn't match
|
|
|
|
ret = autoupdate(
|
2025-02-09 21:41:54 +01:00
|
|
|
C.CONFIG_FILE, freeze=False, tags_only=False,
|
2025-02-09 21:10:22 +01:00
|
|
|
repos=('dne',),
|
|
|
|
)
|
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
after = f.read()
|
|
|
|
assert ret == 0
|
|
|
|
assert before == after
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_does_not_reformat(tmpdir, out_of_date):
|
2025-02-09 21:10:22 +01:00
|
|
|
fmt = (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: {}\n'
|
|
|
|
' rev: {} # definitely the version I want!\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
' # These args are because reasons!\n'
|
|
|
|
' args: [foo, bar, baz]\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(fmt.format(out_of_date.path, out_of_date.original_rev))
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
expected = fmt.format(out_of_date.path, out_of_date.head_rev)
|
|
|
|
assert cfg.read() == expected
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_does_not_change_mixed_endlines_read(up_to_date, tmpdir):
|
2025-02-09 21:19:27 +01:00
|
|
|
fmt = (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: {}\n'
|
|
|
|
' rev: {} # definitely the version I want!\r\n'
|
|
|
|
' hooks:\r\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
' # These args are because reasons!\r\n'
|
|
|
|
' args: [foo, bar, baz]\r\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
|
|
|
|
expected = fmt.format(up_to_date, git.head_rev(up_to_date)).encode()
|
|
|
|
cfg.write_binary(expected)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:19:27 +01:00
|
|
|
assert cfg.read_binary() == expected
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_does_not_change_mixed_endlines_write(tmpdir, out_of_date):
|
2025-02-09 21:19:27 +01:00
|
|
|
fmt = (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: {}\n'
|
|
|
|
' rev: {} # definitely the version I want!\r\n'
|
|
|
|
' hooks:\r\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
' # These args are because reasons!\r\n'
|
|
|
|
' args: [foo, bar, baz]\r\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write_binary(
|
|
|
|
fmt.format(out_of_date.path, out_of_date.original_rev).encode(),
|
|
|
|
)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:19:27 +01:00
|
|
|
expected = fmt.format(out_of_date.path, out_of_date.head_rev).encode()
|
|
|
|
assert cfg.read_binary() == expected
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_loses_formatting_when_not_detectable(out_of_date, tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
"""A best-effort attempt is made at updating rev without rewriting
|
|
|
|
formatting. When the original formatting cannot be detected, this
|
|
|
|
is abandoned.
|
|
|
|
"""
|
|
|
|
config = (
|
|
|
|
'repos: [\n'
|
|
|
|
' {{\n'
|
|
|
|
' repo: {}, rev: {},\n'
|
|
|
|
' hooks: [\n'
|
|
|
|
' # A comment!\n'
|
|
|
|
' {{id: foo}},\n'
|
|
|
|
' ],\n'
|
|
|
|
' }}\n'
|
|
|
|
']\n'.format(
|
|
|
|
shlex.quote(out_of_date.path), out_of_date.original_rev,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(config)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
expected = (
|
|
|
|
f'repos:\n'
|
|
|
|
f'- repo: {out_of_date.path}\n'
|
|
|
|
f' rev: {out_of_date.head_rev}\n'
|
|
|
|
f' hooks:\n'
|
|
|
|
f' - id: foo\n'
|
|
|
|
)
|
|
|
|
assert cfg.read() == expected
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_tagged_repo(tagged, in_tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
config = make_config_from_repo(tagged.path, rev=tagged.original_rev)
|
|
|
|
write_config('.', config)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
assert 'v1.2.3' in f.read()
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_freeze(tagged, in_tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
config = make_config_from_repo(tagged.path, rev=tagged.original_rev)
|
|
|
|
write_config('.', config)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=True, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
expected = f'rev: {tagged.head_rev} # frozen: v1.2.3'
|
|
|
|
assert expected in f.read()
|
|
|
|
|
|
|
|
# if we un-freeze it should remove the frozen comment
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=False, tags_only=False) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
assert 'rev: v1.2.3\n' in f.read()
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_tags_only(tagged, in_tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
# add some commits after the tag
|
|
|
|
git_commit(cwd=tagged.path)
|
|
|
|
|
|
|
|
config = make_config_from_repo(tagged.path, rev=tagged.original_rev)
|
|
|
|
write_config('.', config)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=False, tags_only=True) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
assert 'v1.2.3' in f.read()
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_latest_no_config(out_of_date, in_tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
config = make_config_from_repo(
|
|
|
|
out_of_date.path, rev=out_of_date.original_rev,
|
|
|
|
)
|
|
|
|
write_config('.', config)
|
|
|
|
|
|
|
|
cmd_output('git', 'rm', '-r', ':/', cwd=out_of_date.path)
|
|
|
|
git_commit(cwd=out_of_date.path)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=False, tags_only=False) == 1
|
2025-02-09 21:10:22 +01:00
|
|
|
with open(C.CONFIG_FILE) as f:
|
|
|
|
assert out_of_date.original_rev in f.read()
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_hook_disppearing_repo_raises(hook_disappearing):
|
2025-02-09 21:10:22 +01:00
|
|
|
config = make_config_from_repo(
|
|
|
|
hook_disappearing.path,
|
|
|
|
rev=hook_disappearing.original_rev,
|
|
|
|
hooks=[{'id': 'foo'}],
|
|
|
|
)
|
|
|
|
info = RevInfo.from_config(config).update(tags_only=False, freeze=False)
|
|
|
|
with pytest.raises(RepositoryCannotBeUpdatedError):
|
2025-02-09 21:41:54 +01:00
|
|
|
_check_hooks_still_exist_at_rev(config, info)
|
2025-02-09 21:10:22 +01:00
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_hook_disappearing_repo(hook_disappearing, tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
contents = (
|
|
|
|
f'repos:\n'
|
|
|
|
f'- repo: {hook_disappearing.path}\n'
|
|
|
|
f' rev: {hook_disappearing.original_rev}\n'
|
|
|
|
f' hooks:\n'
|
|
|
|
f' - id: foo\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(contents)
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 1
|
2025-02-09 21:10:22 +01:00
|
|
|
assert cfg.read() == contents
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_local_hooks(in_git_dir):
|
2025-02-09 21:10:22 +01:00
|
|
|
config = sample_local_config()
|
|
|
|
add_config_to_repo('.', config)
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=False, tags_only=False) == 0
|
2025-02-09 21:20:28 +01:00
|
|
|
new_config_written = read_config('.')
|
|
|
|
assert len(new_config_written['repos']) == 1
|
|
|
|
assert new_config_written['repos'][0] == config
|
2025-02-09 21:10:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
def test_autoupdate_local_hooks_with_out_of_date_repo(
|
2025-02-09 21:41:54 +01:00
|
|
|
out_of_date, in_tmpdir,
|
2025-02-09 21:10:22 +01:00
|
|
|
):
|
|
|
|
stale_config = make_config_from_repo(
|
|
|
|
out_of_date.path, rev=out_of_date.original_rev, check=False,
|
|
|
|
)
|
|
|
|
local_config = sample_local_config()
|
|
|
|
config = {'repos': [local_config, stale_config]}
|
|
|
|
write_config('.', config)
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(C.CONFIG_FILE, freeze=False, tags_only=False) == 0
|
2025-02-09 21:20:28 +01:00
|
|
|
new_config_written = read_config('.')
|
|
|
|
assert len(new_config_written['repos']) == 2
|
|
|
|
assert new_config_written['repos'][0] == local_config
|
2025-02-09 21:10:22 +01:00
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_autoupdate_meta_hooks(tmpdir):
|
2025-02-09 21:10:22 +01:00
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: meta\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: check-useless-excludes\n',
|
|
|
|
)
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=True) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
assert cfg.read() == (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: meta\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: check-useless-excludes\n'
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_updates_old_format_to_new_format(tmpdir, capsys):
|
2025-02-09 21:10:22 +01:00
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(
|
|
|
|
'- repo: local\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
' name: foo\n'
|
|
|
|
' entry: ./bin/foo.sh\n'
|
|
|
|
' language: script\n',
|
|
|
|
)
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=True) == 0
|
2025-02-09 21:10:22 +01:00
|
|
|
contents = cfg.read()
|
|
|
|
assert contents == (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: local\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
' name: foo\n'
|
|
|
|
' entry: ./bin/foo.sh\n'
|
|
|
|
' language: script\n'
|
|
|
|
)
|
|
|
|
out, _ = capsys.readouterr()
|
|
|
|
assert out == 'Configuration has been migrated.\n'
|
2025-02-09 21:20:28 +01:00
|
|
|
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
def test_maintains_rev_quoting_style(tmpdir, out_of_date):
|
2025-02-09 21:20:28 +01:00
|
|
|
fmt = (
|
|
|
|
'repos:\n'
|
|
|
|
'- repo: {path}\n'
|
|
|
|
' rev: "{rev}"\n'
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
'- repo: {path}\n'
|
|
|
|
" rev: '{rev}'\n"
|
|
|
|
' hooks:\n'
|
|
|
|
' - id: foo\n'
|
|
|
|
)
|
|
|
|
cfg = tmpdir.join(C.CONFIG_FILE)
|
|
|
|
cfg.write(fmt.format(path=out_of_date.path, rev=out_of_date.original_rev))
|
|
|
|
|
2025-02-09 21:41:54 +01:00
|
|
|
assert autoupdate(str(cfg), freeze=False, tags_only=False) == 0
|
2025-02-09 21:20:28 +01:00
|
|
|
expected = fmt.format(path=out_of_date.path, rev=out_of_date.head_rev)
|
|
|
|
assert cfg.read() == expected
|