Skip to content

Commit 3eab644

Browse files
authored
Merge pull request #708 from daschuer/tx_precommit
pre-commit: Ignore time stamps in po files
2 parents dc268fa + c66ac0f commit 3eab644

3 files changed

Lines changed: 142 additions & 18 deletions

File tree

.github/workflows/pre-commit.yml

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,39 @@ jobs:
88
pre-commit:
99
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/checkout@v7
12-
- uses: actions/setup-python@v6
13-
- uses: pre-commit/action@v3.0.1
14-
env:
15-
SKIP: rstcheck
11+
- name: "Check out repository"
12+
uses: actions/checkout@v7
13+
with:
14+
# Fetch the previous commit to be able to check for changes
15+
fetch-depth: 2
1616

17-
- name: "Generate patch file"
18-
if: failure()
19-
run: |
20-
git diff-index -p HEAD > "${PATCH_FILE}"
21-
[ -s "${PATCH_FILE}" ] && echo "UPLOAD_PATCH_FILE=${PATCH_FILE}" >> "${GITHUB_ENV}"
22-
env:
23-
PATCH_FILE: pre-commit.patch
17+
- name: "Detect code style issues (push)"
18+
uses: pre-commit/action@v3.0.1
19+
if: github.event_name == 'push'
20+
env:
21+
SKIP: rstcheck,ignore-pot-creation-date
2422

25-
- name: "Upload patch artifact"
26-
if: failure() && env.UPLOAD_PATCH_FILE != null
27-
uses: actions/upload-artifact@v7
28-
with:
29-
name: ${{ env.UPLOAD_PATCH_FILE }}
30-
path: ${{ env.UPLOAD_PATCH_FILE }}
23+
- name: "Detect code style issues (pull_request)"
24+
uses: pre-commit/action@v3.0.1
25+
if: github.event_name == 'pull_request'
26+
env:
27+
SKIP: rstcheck
28+
with:
29+
# HEAD is the not yet integrated PR merge commit +refs/pull/xxxx/merge
30+
# HEAD^1 is the PR target branch and HEAD^2 is the HEAD of the source branch
31+
extra_args: --from-ref HEAD^1 --to-ref HEAD
32+
33+
- name: "Generate patch file"
34+
if: failure()
35+
run: |
36+
git diff-index -p HEAD > "${PATCH_FILE}"
37+
[ -s "${PATCH_FILE}" ] && echo "UPLOAD_PATCH_FILE=${PATCH_FILE}" >> "${GITHUB_ENV}"
38+
env:
39+
PATCH_FILE: pre-commit.patch
40+
41+
- name: "Upload patch artifact"
42+
if: failure() && env.UPLOAD_PATCH_FILE != null
43+
uses: actions/upload-artifact@v7
44+
with:
45+
name: ${{ env.UPLOAD_PATCH_FILE }}
46+
path: ${{ env.UPLOAD_PATCH_FILE }}

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@ repos:
1515
types: [rst]
1616
entry: python tools/fixup_gh_wiki_anchors.py
1717
language: python
18+
- id: ignore-pot-creation-date
19+
name: Ignore POT-Creation-Date
20+
entry: python tools/ignore_pot_creation_date.py
21+
language: python
22+
files: ^.*\.po$
1823
- repo: https://github.com/pre-commit/pre-commit-hooks
1924
rev: v5.0.0
2025
hooks:
2126
- id: check-byte-order-marker
2227
- id: check-case-conflict
2328
- id: end-of-file-fixer
29+
exclude: ^\.tx/config$
2430
- id: mixed-line-ending
2531
- id: trailing-whitespace
2632
exclude: ^source/locale/.*$

tools/ignore_pot_creation_date.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import argparse
2+
import logging
3+
import os
4+
import subprocess
5+
import sys
6+
import typing
7+
import pathlib
8+
9+
"""
10+
This script reverts changes in PO files when only the timestamp has changed.
11+
It helps to create meaningful commits by ignoring unnecessary changes.
12+
"""
13+
14+
15+
def get_git_changeset(from_ref, to_ref) -> str:
16+
"""
17+
Constructs the changeset string for `git diff` based on from_ref and
18+
to_ref.
19+
"""
20+
from_ref = (
21+
from_ref
22+
or os.getenv("PRE_COMMIT_FROM_REF")
23+
or os.getenv("PRE_COMMIT_SOURCE")
24+
or "HEAD"
25+
)
26+
to_ref = (
27+
to_ref
28+
or os.getenv("PRE_COMMIT_TO_REF")
29+
or os.getenv("PRE_COMMIT_ORIGIN")
30+
)
31+
return f"{from_ref}...{to_ref}" if to_ref else from_ref
32+
33+
34+
def count_meaningful_changes(changeset: str, po_file: pathlib.Path) -> int:
35+
"""
36+
Counts meaningful changes in the diff for a given PO file.
37+
"""
38+
cmd = [
39+
"git",
40+
"diff",
41+
"--patch",
42+
"--unified=0",
43+
changeset,
44+
"--",
45+
os.fspath(po_file),
46+
]
47+
output = subprocess.check_output(cmd, text=True)
48+
49+
diff_lines = output.splitlines()
50+
return sum(
51+
1
52+
for line in diff_lines
53+
if (line.startswith("-") or line.startswith("+"))
54+
and "POT-Creation-Date:" not in line
55+
and "PO-Revision-Date:" not in line
56+
and str(po_file) not in line
57+
)
58+
59+
60+
def revert_po_file(changeset, po_file: pathlib.Path) -> None:
61+
"""
62+
Reverts a PO file to its original state in the given changeset.
63+
"""
64+
# Use the first part of the changeset as the reference
65+
ref = changeset.split("...", 1)[0]
66+
logger = logging.getLogger(__name__)
67+
logger.info(f"{po_file} has no meaningful changes, reverting to {ref}")
68+
cmd = ["git", "show", f"{ref}:{po_file}"]
69+
output = subprocess.check_output(cmd, text=True)
70+
71+
with po_file.open(mode="w") as file:
72+
file.write(output)
73+
74+
75+
def main(argv: typing.Optional[typing.List[str]] = None) -> int:
76+
logging.basicConfig(
77+
format="[%(levelname)s] %(message)s", level=logging.INFO
78+
)
79+
parser = argparse.ArgumentParser(
80+
description="Revert PO files with only timestamp changes."
81+
)
82+
parser.add_argument("--from-ref", help="Use changes since this commit.")
83+
parser.add_argument("--to-ref", help="Use changes until this commit.")
84+
parser.add_argument(
85+
"files", nargs="*", type=pathlib.Path, help="Only check these files."
86+
)
87+
args = parser.parse_args(argv)
88+
89+
files_to_process = args.files if args.files else []
90+
91+
changeset = get_git_changeset(args.from_ref, args.to_ref)
92+
93+
for po_file in files_to_process:
94+
count = count_meaningful_changes(changeset, po_file)
95+
if count == 0:
96+
revert_po_file(changeset, po_file)
97+
98+
return 0
99+
100+
101+
if __name__ == "__main__":
102+
sys.exit(main())

0 commit comments

Comments
 (0)