summaryrefslogtreecommitdiffstats
path: root/pre_commit/commands/migrate_config.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-10-09 06:23:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-10-09 06:23:31 +0000
commit08605d822cdf05ee12d3f5d936ee1b4c4f46bb70 (patch)
treed733c49718aafd45ed7614531bc87b7ab1efc706 /pre_commit/commands/migrate_config.py
parentAdding upstream version 3.8.0. (diff)
downloadpre-commit-upstream/4.0.1.tar.xz
pre-commit-upstream/4.0.1.zip
Adding upstream version 4.0.1.upstream/4.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pre_commit/commands/migrate_config.py')
-rw-r--r--pre_commit/commands/migrate_config.py80
1 files changed, 70 insertions, 10 deletions
diff --git a/pre_commit/commands/migrate_config.py b/pre_commit/commands/migrate_config.py
index 842fb3a..c5d47a0 100644
--- a/pre_commit/commands/migrate_config.py
+++ b/pre_commit/commands/migrate_config.py
@@ -1,13 +1,21 @@
from __future__ import annotations
-import re
+import functools
+import itertools
import textwrap
+from typing import Callable
import cfgv
import yaml
+from yaml.nodes import ScalarNode
from pre_commit.clientlib import InvalidConfigError
+from pre_commit.yaml import yaml_compose
from pre_commit.yaml import yaml_load
+from pre_commit.yaml_rewrite import MappingKey
+from pre_commit.yaml_rewrite import MappingValue
+from pre_commit.yaml_rewrite import match
+from pre_commit.yaml_rewrite import SequenceItem
def _is_header_line(line: str) -> bool:
@@ -38,16 +46,69 @@ def _migrate_map(contents: str) -> str:
return contents
-def _migrate_sha_to_rev(contents: str) -> str:
- return re.sub(r'(\n\s+)sha:', r'\1rev:', contents)
+def _preserve_style(n: ScalarNode, *, s: str) -> str:
+ style = n.style or ''
+ return f'{style}{s}{style}'
-def _migrate_python_venv(contents: str) -> str:
- return re.sub(
- r'(\n\s+)language: python_venv\b',
- r'\1language: python',
- contents,
+def _fix_stage(n: ScalarNode) -> str:
+ return _preserve_style(n, s=f'pre-{n.value}')
+
+
+def _migrate_composed(contents: str) -> str:
+ tree = yaml_compose(contents)
+ rewrites: list[tuple[ScalarNode, Callable[[ScalarNode], str]]] = []
+
+ # sha -> rev
+ sha_to_rev_replace = functools.partial(_preserve_style, s='rev')
+ sha_to_rev_matcher = (
+ MappingValue('repos'),
+ SequenceItem(),
+ MappingKey('sha'),
+ )
+ for node in match(tree, sha_to_rev_matcher):
+ rewrites.append((node, sha_to_rev_replace))
+
+ # python_venv -> python
+ language_matcher = (
+ MappingValue('repos'),
+ SequenceItem(),
+ MappingValue('hooks'),
+ SequenceItem(),
+ MappingValue('language'),
)
+ python_venv_replace = functools.partial(_preserve_style, s='python')
+ for node in match(tree, language_matcher):
+ if node.value == 'python_venv':
+ rewrites.append((node, python_venv_replace))
+
+ # stages rewrites
+ default_stages_matcher = (MappingValue('default_stages'), SequenceItem())
+ default_stages_match = match(tree, default_stages_matcher)
+ hook_stages_matcher = (
+ MappingValue('repos'),
+ SequenceItem(),
+ MappingValue('hooks'),
+ SequenceItem(),
+ MappingValue('stages'),
+ SequenceItem(),
+ )
+ hook_stages_match = match(tree, hook_stages_matcher)
+ for node in itertools.chain(default_stages_match, hook_stages_match):
+ if node.value in {'commit', 'push', 'merge-commit'}:
+ rewrites.append((node, _fix_stage))
+
+ rewrites.sort(reverse=True, key=lambda nf: nf[0].start_mark.index)
+
+ src_parts = []
+ end: int | None = None
+ for node, func in rewrites:
+ src_parts.append(contents[node.end_mark.index:end])
+ src_parts.append(func(node))
+ end = node.start_mark.index
+ src_parts.append(contents[:end])
+ src_parts.reverse()
+ return ''.join(src_parts)
def migrate_config(config_file: str, quiet: bool = False) -> int:
@@ -62,8 +123,7 @@ def migrate_config(config_file: str, quiet: bool = False) -> int:
raise cfgv.ValidationError(str(e))
contents = _migrate_map(contents)
- contents = _migrate_sha_to_rev(contents)
- contents = _migrate_python_venv(contents)
+ contents = _migrate_composed(contents)
if contents != orig_contents:
with open(config_file, 'w') as f: