Skip to content

Commit c1f9550

Browse files
committed
common/Scripts: Add a script to validate AppStream
Adds a script to validate an AppStream metainfo XML file. It uses a bunch of overrides sourced from Flathub. I decided to use these to try to maintain the best compatibility; the idea is if a metainfo file works for Flathub, it should work for us. Some exceptions are commented out as they rely on patches to appstream (I think?), and I haven't looked into locating those yet. We can decide to pursue that at a later time and uncomment them, or just drop them. Signed-off-by: Evan Maddock <[email protected]>
1 parent 37845d6 commit c1f9550

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

common/Scripts/validate-appstream.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import subprocess
6+
import sys
7+
from typing import TypedDict
8+
9+
10+
class SubprocessResult(TypedDict):
11+
stdout: str
12+
stderr: str
13+
returncode: int
14+
15+
16+
def validate(path: str, *args: str) -> SubprocessResult:
17+
if not os.path.isfile(path):
18+
raise FileNotFoundError("AppStream file not found")
19+
20+
overrides = {
21+
"all-categories-ignored": "error",
22+
"category-invalid": "error",
23+
"cid-desktopapp-is-not-rdns": "error",
24+
# "cid-domain-not-lowercase": "info",
25+
"cid-has-number-prefix": "error",
26+
"cid-missing-affiliation-gnome": "error",
27+
"cid-rdns-contains-hyphen": "error",
28+
# "component-name-too-long": "info",
29+
"content-rating-missing": "error",
30+
# "description-has-plaintext-url": "info",
31+
"desktop-app-launchable-omitted": "error",
32+
"desktop-file-not-found": "error",
33+
# "developer-id-invalid": "info",
34+
"developer-id-missing": "error",
35+
"invalid-child-tag-name": "error",
36+
"metainfo-filename-cid-mismatch": "error",
37+
"metainfo-legacy-path": "error",
38+
"metainfo-multiple-components": "error",
39+
"name-has-dot-suffix": "info",
40+
"releases-info-missing": "error",
41+
# "summary-too-long": "info",
42+
"unknown-tag": "error",
43+
# "app-categories-missing": "info",
44+
}
45+
46+
overrides_value = ",".join([f"{k}={v}" for k, v in overrides.items()])
47+
48+
cmd = subprocess.run(
49+
["appstreamcli", "validate", f"--override={overrides_value}", *args, path],
50+
capture_output=True,
51+
check=False,
52+
)
53+
54+
ret: SubprocessResult = {
55+
"stdout": cmd.stdout.decode("utf-8"),
56+
"stderr": cmd.stderr.decode("utf-8"),
57+
"returncode": cmd.returncode,
58+
}
59+
60+
return ret
61+
62+
63+
def main():
64+
parser = argparse.ArgumentParser(
65+
description="A script to lint AppStream metainfo files",
66+
formatter_class=argparse.RawTextHelpFormatter,
67+
add_help=False,
68+
)
69+
70+
parser.add_argument(
71+
"-h",
72+
"--help",
73+
help="Show this help message and exit.",
74+
action="help",
75+
default=argparse.SUPPRESS,
76+
)
77+
78+
parser.add_argument(
79+
"path",
80+
help="Path to an AppStream metainfo file.",
81+
type=str,
82+
nargs=1,
83+
)
84+
85+
args = parser.parse_args()
86+
exit_code = 0
87+
88+
try:
89+
ret = validate(args.path, "--explain")
90+
print(ret["stdout"]) # noqa: T201
91+
print(ret["stderr"]) # noqa: T201
92+
exit_code = ret["returncode"]
93+
except Exception as e:
94+
print(f"Error validating {args.path}: {e}")
95+
sys.exit(1)
96+
97+
sys.exit(exit_code)
98+
99+
100+
if __name__ == "__main__":
101+
main()

0 commit comments

Comments
 (0)