merge: branch 'jv/po-check'
po: add test to check potfiles list contents https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2190
This commit is contained in:
@@ -149,6 +149,7 @@ src/libnmc-base/nm-secret-agent-simple.c
|
||||
src/libnmc-base/nm-vpn-helpers.c
|
||||
src/libnmc-setting/nm-meta-setting-access.c
|
||||
src/libnmc-setting/nm-meta-setting-desc.c
|
||||
src/libnmc-setting/nm-meta-setting-desc.h
|
||||
src/libnmc-setting/settings-docs.h.in
|
||||
src/libnmt-newt/nmt-newt-utils.c
|
||||
src/nm-online/nm-online.c
|
||||
|
@@ -5,19 +5,7 @@ data/NetworkManager-wait-online-initrd.service.in
|
||||
data/NetworkManager-initrd.service.in
|
||||
data/NetworkManager.service.in
|
||||
data/nm-priv-helper.service.in
|
||||
data/org.freedesktop.NetworkManager.policy.in
|
||||
examples/python/NetworkManager.py
|
||||
examples/python/systray/eggtrayicon.c
|
||||
src/contrib/nm-vpn-editor-plugin-call.h
|
||||
src/contrib/nm-vpn-plugin-utils.c
|
||||
src/libnm-systemd-shared/src/basic/parse-util.c
|
||||
src/nm-cloud-setup/nm-cloud-setup.service.in
|
||||
vpn-daemons/openvpn
|
||||
vpn-daemons/pptp
|
||||
vpn-daemons/vpnc
|
||||
|
||||
# https://bugs.launchpad.net/intltool/+bug/1117944
|
||||
sub/data/org.freedesktop.NetworkManager.policy.in
|
||||
|
||||
# from meson build directory:
|
||||
build/data/org.freedesktop.NetworkManager.policy.in
|
||||
|
@@ -1,3 +1,8 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
i18n.gettext(nm_name, preset: 'glib')
|
||||
|
||||
test(
|
||||
'check-potfile-list',
|
||||
find_program(join_paths(source_root, 'src/tests/check-potfile-list.py'))
|
||||
)
|
137
src/tests/check-potfile-list.py
Executable file
137
src/tests/check-potfile-list.py
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (C) 2025 Red Hat, Inc.
|
||||
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import itertools
|
||||
import shutil
|
||||
import sys
|
||||
import os
|
||||
|
||||
xgettext = shutil.which("xgettext")
|
||||
|
||||
# Paths relative to repo root which should be
|
||||
# excluded from pot->tree, or tree->pot checks.
|
||||
ignore_in_potfiles = ()
|
||||
ignore_in_tree = ()
|
||||
|
||||
|
||||
def err(s):
|
||||
print(f"ERR: {s}", file=sys.stderr)
|
||||
|
||||
|
||||
def read_potfile_list(root, path):
|
||||
with open(root / path, "r") as f:
|
||||
for line in f.readlines():
|
||||
stripped = line.strip()
|
||||
if stripped.startswith("#") or len(stripped) == 0:
|
||||
continue
|
||||
if stripped in ignore_in_potfiles:
|
||||
continue
|
||||
yield (root / stripped).resolve()
|
||||
|
||||
|
||||
def get_existing_entries(root):
|
||||
in_list = read_potfile_list(root, "po/POTFILES.in")
|
||||
skip_list = read_potfile_list(root, "po/POTFILES.skip")
|
||||
return set(itertools.chain(in_list, skip_list))
|
||||
|
||||
|
||||
def check_exists_in_tree(root, paths):
|
||||
is_ok = True
|
||||
|
||||
for path in paths:
|
||||
if not path.exists():
|
||||
err(
|
||||
f"{path.relative_to(root)} exists in POTFILES.in or POTFILES.skip, but missing in sources"
|
||||
)
|
||||
is_ok = False
|
||||
|
||||
return is_ok
|
||||
|
||||
|
||||
def get_gettext_args(root):
|
||||
arg_name = "XGETTEXT_OPTIONS ="
|
||||
with open(root / "po" / "Makevars", "r") as f:
|
||||
for line in f.readlines():
|
||||
if line.startswith(arg_name):
|
||||
return line[len(arg_name) :].strip().split(" ")
|
||||
|
||||
raise Exception("could not get gettext args")
|
||||
|
||||
|
||||
def list_c_sources(root):
|
||||
for path, _, files in os.walk(root / "src"):
|
||||
for file in files:
|
||||
relpath_str = str(Path(path).relative_to(root) / file)
|
||||
extension = file.replace(".in", "").split(".").pop()
|
||||
if extension in ["c", "h"] and relpath_str not in ignore_in_tree:
|
||||
full_path = root / path / file
|
||||
yield full_path.resolve()
|
||||
|
||||
|
||||
def gettext_dry_run(root, paths):
|
||||
args = get_gettext_args(root)
|
||||
process = subprocess.Popen(
|
||||
[xgettext, "--files-from=-", "--output=-"] + args,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
|
||||
for line in paths:
|
||||
process.stdin.write(f"{line.resolve()}\n")
|
||||
process.stdin.close()
|
||||
|
||||
seen = set()
|
||||
for line in process.stdout:
|
||||
if line.startswith("#: "):
|
||||
out_path = Path(line.replace("#: ", "").split(":")[0])
|
||||
if out_path not in seen:
|
||||
seen.add(out_path)
|
||||
yield out_path
|
||||
|
||||
process.stdout.close()
|
||||
assert process.wait() == 0
|
||||
|
||||
|
||||
def check_exists_in_potfiles(root, pot_paths):
|
||||
unseen_paths = filter(lambda path: path not in pot_paths, list_c_sources(root))
|
||||
|
||||
is_ok = True
|
||||
for path in gettext_dry_run(root, unseen_paths):
|
||||
err(
|
||||
f"{path.relative_to(root)} code contains gettext macros, but missing in POTFILES.in or POTFILES.skip"
|
||||
)
|
||||
is_ok = False
|
||||
|
||||
return is_ok
|
||||
|
||||
|
||||
def check_potfiles():
|
||||
root = (Path(os.path.dirname(__file__)) / "../../").resolve()
|
||||
file_entries = get_existing_entries(root)
|
||||
is_ok = True
|
||||
|
||||
# Let's first check that all the files that we
|
||||
# have in POTFILES.* actually exist.
|
||||
is_ok &= check_exists_in_tree(root, file_entries)
|
||||
|
||||
# Now the other direction -- check that all sources
|
||||
# that should be included in POTFILES, are included.
|
||||
is_ok &= check_exists_in_potfiles(root, file_entries)
|
||||
|
||||
return is_ok
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if xgettext is None:
|
||||
raise Exception("xgettext is missing")
|
||||
|
||||
out_msg = "POTFILES consistency check: %s"
|
||||
if check_potfiles():
|
||||
print(out_msg % "ok")
|
||||
else:
|
||||
print(out_msg % "failed", file=sys.stderr)
|
||||
sys.exit(1)
|
Reference in New Issue
Block a user