-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: ignore local hooks, better save
- Loading branch information
Showing
14 changed files
with
395 additions
and
481 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
pdm 2.8.0 | ||
pdm 2.8.1 | ||
python 3.11.4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
from __future__ import annotations | ||
|
||
import difflib | ||
from functools import cached_property | ||
from typing import TYPE_CHECKING, Any, NamedTuple | ||
|
||
import strictyaml as yaml | ||
from strictyaml import Any as AnyStrictYaml | ||
from strictyaml import MapCombined, Optional, Seq, Str | ||
|
||
from sync_pre_commit_lock.utils import normalize_git_url | ||
|
||
if TYPE_CHECKING: | ||
from pathlib import Path | ||
|
||
schema = MapCombined( | ||
{ | ||
Optional("repos"): Seq( | ||
MapCombined( | ||
{ | ||
"repo": Str(), | ||
Optional("rev"): Str(), | ||
}, | ||
Str(), | ||
AnyStrictYaml(), | ||
), | ||
) | ||
}, | ||
Str(), | ||
AnyStrictYaml(), | ||
) | ||
|
||
|
||
class PreCommitRepo(NamedTuple): | ||
repo: str | ||
rev: str # Check if is not loaded as float/int/other yolo | ||
|
||
|
||
class PreCommitHookConfig: | ||
def __init__( | ||
self, | ||
raw_file_contents: str, | ||
pre_commit_config_file_path: Path, | ||
) -> None: | ||
self.raw_file_contents = raw_file_contents | ||
self.yaml = yaml.dirty_load( | ||
raw_file_contents, schema=schema, allow_flow_style=True, label=str(pre_commit_config_file_path) | ||
) | ||
|
||
self.pre_commit_config_file_path = pre_commit_config_file_path | ||
|
||
@cached_property | ||
def original_file_lines(self) -> list[str]: | ||
return self.raw_file_contents.splitlines(keepends=True) | ||
|
||
@property | ||
def data(self) -> Any: | ||
return self.yaml.data | ||
|
||
@classmethod | ||
def from_yaml_file(cls, file_path: Path) -> PreCommitHookConfig: | ||
with file_path.open("r") as stream: | ||
file_contents = stream.read() | ||
|
||
return PreCommitHookConfig(file_contents, file_path) | ||
|
||
@cached_property | ||
def repos(self) -> list[PreCommitRepo]: | ||
"""Return the repos, excluding local repos.""" | ||
return [ | ||
PreCommitRepo(repo=repo["repo"], rev=repo["rev"]) for repo in (self.data["repos"] or []) if "rev" in repo | ||
] | ||
|
||
@cached_property | ||
def repos_normalized(self) -> set[PreCommitRepo]: | ||
return {PreCommitRepo(repo=normalize_git_url(repo.repo), rev=repo.rev) for repo in self.repos} | ||
|
||
@cached_property | ||
def document_start_offset(self) -> int: | ||
# Use re to split by lines and find the '---' | ||
lines = self.raw_file_contents.split("\n") | ||
for i, line in enumerate(lines): | ||
# Trim leading/trailing whitespaces | ||
line = line.strip() | ||
# Skip if line is a comment or empty/whitespace | ||
if line.startswith("#") or line == "": | ||
continue | ||
# If line is '---', return line number + 1 | ||
if line == "---": | ||
return i + 1 | ||
# If line isn't a comment and not '---' or empty/whitespace, it's the start of the YAML doc | ||
# We return the line number (add 1 for 1-based indexing) | ||
else: | ||
return i | ||
return 0 | ||
|
||
def update_pre_commit_repo_versions(self, new_versions: dict[PreCommitRepo, str]) -> None: | ||
"""Fix the pre-commit hooks to match the lockfile. Preserve comments and formatting as much as possible.""" | ||
|
||
if len(new_versions) == 0: | ||
return | ||
|
||
original_lines = self.original_file_lines | ||
updated_lines = original_lines[:] | ||
|
||
for repo_rev in self.yaml["repos"]: | ||
if "rev" not in repo_rev: | ||
continue | ||
|
||
repo, rev = repo_rev["repo"], repo_rev["rev"] | ||
normalized_repo = PreCommitRepo(normalize_git_url(str(repo)), str(rev)) | ||
if normalized_repo not in new_versions: | ||
continue | ||
|
||
rev_line_number = rev.end_line + self.document_start_offset | ||
rev_line_idx = rev_line_number - 1 | ||
original_rev_line: str = updated_lines[rev_line_idx] | ||
|
||
updated_lines[rev_line_idx] = original_rev_line.replace(str(rev), new_versions[normalized_repo]) | ||
|
||
changes = difflib.ndiff(original_lines, updated_lines) | ||
change_count = sum(1 for change in changes if change[0] in ["+", "-"]) | ||
|
||
if change_count == 0: | ||
# XXX We should probably raise an exception here | ||
return | ||
with self.pre_commit_config_file_path.open("w") as stream: | ||
stream.writelines(updated_lines) |
22 changes: 22 additions & 0 deletions
22
tests/fixtures/sample_pre_commit_config/pre-commit-config-document-separator.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
|
||
# Many unused lines before document separator | ||
|
||
--- | ||
default_language_version: | ||
python: python3.11 | ||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.4.0 | ||
hooks: | ||
- id: check-toml | ||
|
||
- repo: https://github.com/psf/black | ||
rev: 23.3.0 | ||
hooks: | ||
- id: black | ||
|
||
- repo: https://github.com/charliermarsh/ruff-pre-commit | ||
rev: 'v0.0.275' | ||
hooks: | ||
- id: ruff | ||
args: [--fix, --exit-non-zero-on-fix] |
31 changes: 31 additions & 0 deletions
31
tests/fixtures/sample_pre_commit_config/pre-commit-config-start-empty-lines.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
|
||
|
||
|
||
|
||
default_language_version: | ||
python: python3.11 | ||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.4.0 | ||
hooks: | ||
- id: check-toml | ||
- id: trailing-whitespace | ||
- id: check-executables-have-shebangs | ||
- id: debug-statements | ||
- id: end-of-file-fixer | ||
- id: check-added-large-files | ||
- id: check-merge-conflict | ||
- id: fix-byte-order-marker | ||
|
||
- repo: https://github.com/charliermarsh/ruff-pre-commit | ||
# Ruff version. | ||
rev: 'v0.0.277' | ||
hooks: | ||
- id: ruff | ||
args: [--fix, --exit-non-zero-on-fix] | ||
- repo: https://github.com/psf/black | ||
rev: 23.3.0 | ||
hooks: | ||
- id: black | ||
|
||
# XXX Fix the issue with documents |
21 changes: 21 additions & 0 deletions
21
tests/fixtures/sample_pre_commit_config/pre-commit-config-with-local.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
repos: | ||
- repo: https://github.com/astral-sh/ruff-pre-commit | ||
rev: "v0.0.280" | ||
hooks: | ||
- id: ruff | ||
args: [--fix, --exit-non-zero-on-fix, --show-fixes] | ||
- rev: 23.7.0 | ||
repo: https://github.com/psf/black | ||
hooks: | ||
- id: black | ||
- repo: local | ||
hooks: | ||
- id: mypy | ||
name: mypy | ||
entry: mypy | ||
args: [src, tests, --color-output] | ||
language: system | ||
types: [python] | ||
pass_filenames: false | ||
require_serial: true |
28 changes: 28 additions & 0 deletions
28
tests/fixtures/sample_pre_commit_config/pre-commit-config.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
default_language_version: | ||
python: python3.11 | ||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.4.0 | ||
hooks: | ||
- id: check-toml | ||
- id: trailing-whitespace | ||
- id: check-executables-have-shebangs | ||
- id: debug-statements | ||
- id: end-of-file-fixer | ||
- id: check-added-large-files | ||
- id: check-merge-conflict | ||
- id: fix-byte-order-marker | ||
|
||
- repo: https://github.com/charliermarsh/ruff-pre-commit | ||
# Ruff version. | ||
rev: 'v0.0.277' | ||
hooks: | ||
- id: ruff | ||
args: [--fix, --exit-non-zero-on-fix] | ||
- repo: https://github.com/psf/black | ||
rev: 23.3.0 | ||
hooks: | ||
- id: black | ||
|
||
# XXX Fix the issue with documents |
Oops, something went wrong.