Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tc version check #29

Merged
merged 25 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,11 @@
entry: minimize-id-changes
language: python
files: .*\.plcproj$
- id: check-twincat-versions
name: Check if all TwinCAT versions match
description: Checks if TwinCAT versions match in different tsproj files, or if it matches the targeted one.
entry: check-twincat-versions
# All files need to be passed at once, else not all files are compared to eachother
require_serial: true
language: python
files: .*\.tsproj$
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ repos:
files: \.(TcPOU|TcDUT|TcGVL)$

- repo: https://github.com/pcdshub/pre-commit-hooks.git
rev: v1.6.0
rev: v1.7.0
hooks:
- id: twincat-leading-tabs-remover
- id: twincat-lineids-remover
Expand All @@ -36,6 +36,15 @@ repos:
# Check if minimize id changes is selected in the plc project file.
# See https://www.youtube.com/watch?v=KKpBtaYjfWo&t=935s why to do this.
- id: minimize-id-changes
# Checks if TwinCAT versions match in different tsproj files, or if it matches the targeted one.
- id: check-twincat-versions
# Possible optional arguments
# --target-version: Set a version that you want the tsproj file to have
# --fix: Fix the version numbers if a target version is set
# --reason: Add a reason to the error message in case of a non-matching version.
# --pinned: Require the TwinCAT version to be pinned. Apply pinning if combined with --fix.
# --no-pinned: Require the TwinCAT version to not be pinned. Remove pinning if combined with --fix.
args: [--target-version=3.1.4024.20, --pinned, --fix, --reason="This version has a crucial new feature"]
# Optional, if you use pytmc to generate EPICS IOCs:
# - id: pytmc-pragma-linter
```
Expand Down
11 changes: 10 additions & 1 deletion forTwinCatRepos/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repos:
files: \.(TcPOU|TcDUT|TcGVL)$

- repo: https://github.com/pcdshub/pre-commit-hooks.git
rev: v1.5.0
rev: v1.7.0
hooks:
- id: twincat-leading-tabs-remover
- id: twincat-lineids-remover
Expand All @@ -20,5 +20,14 @@ repos:
# Check if minimize id changes is selected in the plc project file.
# See https://www.youtube.com/watch?v=KKpBtaYjfWo&t=935s why to do this.
- id: minimize-id-changes
# Checks if TwinCAT versions match in different tsproj files, or if it matches the targeted one.
- id: check-twincat-versions
# Possible optional arguments
# --target-version: Set a version that you want the tsproj file to have
# --fix: Fix the version numbers if a target version is set
# --reason: Add a reason to the error message in case of a non-matching version.
# --pinned: Require the TwinCAT version to be pinned. Apply pinning if combined with --fix.
# --no-pinned: Require the TwinCAT version to not be pinned. Remove pinning if combined with --fix.
args: [--target-version=3.1.4024.20, --pinned, --fix, --reason="This version has a crucial new feature"]
# Optional, if you use pytmc to generate EPICS IOCs:
# - id: pytmc-pragma-linter
4 changes: 1 addition & 3 deletions pre_commit_hooks/check_fixed_library_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

from lxml import etree


class PreCommitException(Exception):
pass
from pre_commit_hooks.exceptions import PreCommitException


def check_file(filename):
Expand Down
145 changes: 145 additions & 0 deletions pre_commit_hooks/check_twincat_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import argparse
import re
import xml.etree.ElementTree as ET

from pre_commit_hooks.exceptions import PreCommitException


def tc_version_pinned(xml_content: str) -> bool:
root = ET.fromstring(xml_content)

return (
"TcVersionFixed" in root.attrib and root.attrib.get("TcVersionFixed") == "true"
)


def get_tc_version(xml_content: str) -> str:
root = ET.fromstring(xml_content)

return root.attrib.get("TcVersion")


def fix_tc_version(xml_content: str, new_version: str) -> str:
pattern = r'(TcVersion=")([^"]*)(")'
new_xml_content = re.sub(pattern, r"\g<1>" + new_version + r"\g<3>", xml_content)

return new_xml_content


def fix_pinned_version(xml_content: str, pin_version: bool) -> str:
rruiter87 marked this conversation as resolved.
Show resolved Hide resolved
new_value = "true" if pin_version else "false"

pattern = r'(TcVersionFixed=")([^"]*)(")'

if re.search(pattern, xml_content):
new_xml_content = re.sub(pattern, r"\g<1>" + new_value + r"\g<3>", xml_content)
else:
version_pattern = r'(TcVersion="[^"]*")'
new_xml_content = re.sub(
version_pattern, r'\g<1> TcVersionFixed="' + new_value + r'"', xml_content
)

return new_xml_content


def main(args=None):
if args is None:
parser = argparse.ArgumentParser()
parser.add_argument(
"filenames", nargs="+", help="List of tsproj filenames to process."
)
parser.add_argument(
"--target-version", type=str, help="Target TwinCAT version to enforce."
)
parser.add_argument(
"--fix",
action="store_true",
help="Fix the versions if they do not match the target version and fix the pinned state if combined with --pinned/no-pinned.",
)
parser.add_argument(
"--reason", type=str, help="Reason for targeting a specific version."
)
parser.add_argument(
"--pinned",
action=argparse.BooleanOptionalAction,
help="Check if the TwinCAT version should be pinned. Applies or removes pinning if combined with --fix.",
)

args = parser.parse_args()

try:
versions = {}
pinned = {}
for filename in args.filenames:
with open(filename, "r") as file:
xml_content = file.read()
versions[filename] = get_tc_version(xml_content)
pinned[filename] = tc_version_pinned(xml_content)

itemize = "\n -"
exception_message = ""
if args.target_version:
mismatched_files = [
fname for fname, ver in versions.items() if ver != args.target_version
]
if mismatched_files:
reason_msg = f"\nReason: {args.reason}" if args.reason else ""
if args.fix:
for filename in mismatched_files:
with open(filename, "r") as file:
xml_content = file.read()
fixed_content = fix_tc_version(xml_content, args.target_version)
with open(filename, "w") as file:
file.write(fixed_content)

print(
f"Fixed TwinCAT versions for:{itemize}{itemize.join(mismatched_files)}{reason_msg}"
)
else:
exception_message += (
"The following files are not set to the targeted TwinCAT version "
f"{args.target_version}:{itemize}{itemize.join(mismatched_files)}{reason_msg}"
)
else:
unique_versions = set(versions.values())
if len(unique_versions) > 1:
exception_message += (
"Not all files have the same TwinCAT version:"
f"{itemize}"
+ itemize.join(f"{fname}: {ver}" for fname, ver in versions.items())
)

if args.pinned is not None:
mismatched_files = [
fname for fname, pin in pinned.items() if pin != args.pinned
]
if mismatched_files:
if args.fix:
for filename in mismatched_files:
with open(filename, "r") as file:
xml_content = file.read()
fixed_content = fix_pinned_version(xml_content, args.pinned)
with open(filename, "w") as file:
file.write(fixed_content)
print(
f"Fixed pinned state for:{itemize}{itemize.join(mismatched_files)}"
)
else:
should_be_pinned_message = (
"The following files should have a pinned TwinCAT version"
if args.pinned
else "The following files should NOT have a pinned TwinCAT version"
)
exception_message += "\n\n" if len(exception_message) > 0 else ""
exception_message += f"{should_be_pinned_message}{itemize}{itemize.join(mismatched_files)}"
if len(exception_message) > 0:
raise PreCommitException(exception_message)

return 0
except Exception as exc:
print(exc)
return 1


if __name__ == "__main__":
exit(main())
2 changes: 2 additions & 0 deletions pre_commit_hooks/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class PreCommitException(Exception):
rruiter87 marked this conversation as resolved.
Show resolved Hide resolved
pass
4 changes: 1 addition & 3 deletions pre_commit_hooks/minimize_id_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
from importlib.abc import Traversable
from typing import Union


class PreCommitException(Exception):
pass
from pre_commit_hooks.exceptions import PreCommitException


def minimize_id_changes_checked(filename: Union[Traversable, str]) -> None:
Expand Down
4 changes: 1 addition & 3 deletions pre_commit_hooks/no_product_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

from lxml import etree


class PreCommitException(Exception):
pass
from pre_commit_hooks.exceptions import PreCommitException


def check_file(filename):
Expand Down
Loading