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:
Jan Vaclav
2025-04-24 10:30:33 +00:00
4 changed files with 143 additions and 12 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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)