forked from wpilibsuite/vendor-json-repo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate_bundles.py
More file actions
132 lines (110 loc) · 4.22 KB
/
generate_bundles.py
File metadata and controls
132 lines (110 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import argparse
import json
import shutil
from pathlib import Path
def check_languages(vendordep_data: dict) -> list[str]:
# Check if json explicitly specifies and use that first
if "languages" in vendordep_data:
return vendordep_data["languages"]
languages = []
if (
"javaDependencies" in vendordep_data
and len(vendordep_data["javaDependencies"]) != 0
):
languages.append("java")
if (
"cppDependencies" in vendordep_data
and len(vendordep_data["cppDependencies"]) != 0
):
languages.append("cpp")
return languages
def check_metadata_schema(metadata: list[dict]):
required_keys = {"uuid", "name", "website", "description"}
for entry in metadata:
# no nested types, so just check root keys
if not required_keys.issubset(entry.keys()):
raise KeyError(
f"Missing one or more required keys: {required_keys - entry.keys()}, metadata listing: {entry}"
)
def load_metadata(file: Path) -> dict[str, dict]:
json_metadata = json.loads(file.read_text())
check_metadata_schema(json_metadata)
out = {}
for entry in json_metadata:
out[entry["uuid"]] = entry
return out
def generate_entry(
file: Path, path_prefix: str, metadata_database: dict[str, dict]
) -> dict[str, str]:
vendordep_data = json.loads(file.read_text())
if path_prefix and not path_prefix.endswith("/"):
path_prefix += "/"
uuid = vendordep_data["uuid"]
if uuid not in metadata_database.keys():
raise KeyError(f"UUID for {file} not found in metadata.")
metadata = metadata_database[uuid]
# Metadata schemas have already been checked for required keys, so we can just add all the values to the output
# This allows optional keys to be added as necessary without changing generation
return metadata | {
"path": path_prefix + file.name,
"version": vendordep_data["version"],
"languages": check_languages(vendordep_data),
}
def generate_manifest_file(
json_files: list[Path],
metadata_file: Path,
path_prefix: str,
outfile: Path,
pretty=False,
):
"""Generates a manifest for all vendordep json files in json_files."""
metadata_database = load_metadata(metadata_file)
entries = []
for file in json_files:
entries.append(generate_entry(file, path_prefix, metadata_database))
format_args = {"indent": 2} if pretty else {"separators": (",", ":")}
outfile.write_text(json.dumps(entries, **format_args), newline="\n")
def generate_bundle(year: str, root: Path, outdir: Path, pretty=False):
"""Generates a 'bundle' consisting of a YEAR.json manifest and a directory named YEAR containing all of the vendordep files
Requires a metadata file YEAR_metadata.json, and a directory named YEAR containing the input vendordeps.
"""
json_dir = root / year
metadata = root / f"{year}_metadata.json"
path_prefix = year
outdir.mkdir(parents=True, exist_ok=True)
manifest_file = Path(outdir) / f"{year}.json"
vendordeps = [file for file in json_dir.glob("*.json")]
generate_manifest_file(vendordeps, metadata, path_prefix, manifest_file, pretty)
# Copy all vendordeps to outdir/YEAR
depsdir = outdir / year
depsdir.mkdir(exist_ok=True)
for file in vendordeps:
shutil.copy(file, depsdir)
def main():
parser = argparse.ArgumentParser(
"Generates one or more vendordep repository bundles for publication"
)
parser.add_argument(
"--output", "-o", type=Path, default="bundles", help="Directory to place the output bundles in"
)
parser.add_argument(
"--root",
"-r",
type=Path,
default=Path(),
help="Root directory to find metadata files and year folders. Defaults to '.'",
)
parser.add_argument(
"year", nargs="+", type=str, help="Years to generate bundles for"
)
parser.add_argument(
"--pretty",
"-p",
action="store_true",
help="Pretty-print the output. Without this option, output is minified.",
)
args = parser.parse_args()
for year in args.year:
generate_bundle(year, args.root, args.output, args.pretty)
if __name__ == "__main__":
main()