-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathbuild_xrplib_version.py
More file actions
135 lines (105 loc) · 5.04 KB
/
Copy pathbuild_xrplib_version.py
File metadata and controls
135 lines (105 loc) · 5.04 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
133
134
135
#!/usr/bin/env python3
"""
Assemble a new XRPLib version directory inside a checked-out XRP_Firmware repo.
Called by .github/workflows/publish-to-firmware.yml on a XRP_MicroPython release.
It copies this release's XRPLib/ and XRPExamples/ into boards/XRPLib/<version>/,
carries ble/ and phew/ forward from the previous version (they do not live in this
repo), regenerates files.json, and registers the version in index.json.
board-only.json travels with the release so consumers do not need their own list of
which files are board-specific; see BOARD_ONLY_MANIFEST below.
The files.json format and device-path convention are defined in the firmware repo's
boards/spec.md; this reproduces the generator that normally lives in XRPWeb.
"""
import json
import os
import shutil
import sys
# Directories whose files land under /lib on the robot; everything else keeps its path.
LIB_DIRS = ("XRPLib", "AgXRPLib", "ble", "phew")
# Never bundled: version.py is synthesized on-device from the registry version.
EXCLUDE_NAMES = ("version.py",)
EXCLUDE_DIRS = ("__pycache__",)
# Declares which library files belong only on boards that have the hardware (the
# NanoXRP's buzzer). Copied into the release so every consumer reads the list from
# the release itself instead of hardcoding filenames.
BOARD_ONLY_MANIFEST = "board-only.json"
def read_board_only(src_repo):
"""Return the set of release-relative paths that are not part of the shared bundle."""
path = os.path.join(src_repo, BOARD_ONLY_MANIFEST)
if not os.path.isfile(path):
return set()
with open(path) as f:
return set(json.load(f).get("boardOnly", []))
def die(msg):
print("ERROR: {}".format(msg), file=sys.stderr)
sys.exit(1)
def copy_tree(src, dst):
if not os.path.isdir(src):
die("expected source directory does not exist: {}".format(src))
shutil.copytree(
src, dst,
ignore=shutil.ignore_patterns(*EXCLUDE_DIRS, "*.pyc", *EXCLUDE_NAMES),
)
def device_path(rel_path):
# rel_path is POSIX-style, relative to the version dir, e.g. "XRPLib/board.py".
top = rel_path.split("/", 1)[0]
return "/lib/" + rel_path if top in LIB_DIRS else "/" + rel_path
def generate_files_json(version_dir, board_only):
pairs = []
for root, dirs, files in os.walk(version_dir):
dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS and not d.startswith(".")]
for name in files:
if name in EXCLUDE_NAMES or name.endswith(".pyc") or name.startswith("."):
continue
if name in ("files.json", BOARD_ONLY_MANIFEST):
continue
abs_path = os.path.join(root, name)
rel = os.path.relpath(abs_path, version_dir).replace(os.sep, "/")
if rel in board_only:
continue
pairs.append([device_path(rel), rel])
# files.json is a plain ascending sort by source path (see spec.md / existing releases).
pairs.sort(key=lambda pair: pair[1])
with open(os.path.join(version_dir, "files.json"), "w", newline="\n") as f:
json.dump(pairs, f, indent=4)
f.write("\n")
def main():
version = os.environ["XRPLIB_VERSION"].strip()
src_repo = os.environ.get("SRC_REPO", ".")
firmware = os.environ["FIRMWARE_REPO"]
store = os.path.join(firmware, "boards", "XRPLib")
index_path = os.path.join(store, "index.json")
version_dir = os.path.join(store, version)
with open(index_path) as f:
index = json.load(f)
version_id = "xrplib-{}".format(version)
if any(v.get("id") == version_id or v.get("dir") == version for v in index["versions"]):
print("Version {} already registered in index.json; nothing to do.".format(version))
return
if os.path.exists(version_dir):
die("{} already exists but is not in index.json; refusing to overwrite".format(version_dir))
if not index["versions"]:
die("no existing versions to source ble/ and phew/ from; seed one manually first")
previous_dir = os.path.join(store, index["versions"][0]["dir"])
# This release supplies XRPLib and XRPExamples; ble/phew are carried forward unchanged.
os.makedirs(version_dir)
copy_tree(os.path.join(src_repo, "XRPLib"), os.path.join(version_dir, "XRPLib"))
copy_tree(os.path.join(src_repo, "XRPExamples"), os.path.join(version_dir, "XRPExamples"))
for carried in ("ble", "phew"):
copy_tree(os.path.join(previous_dir, carried), os.path.join(version_dir, carried))
board_only_src = os.path.join(src_repo, BOARD_ONLY_MANIFEST)
if os.path.isfile(board_only_src):
shutil.copyfile(board_only_src, os.path.join(version_dir, BOARD_ONLY_MANIFEST))
generate_files_json(version_dir, read_board_only(src_repo))
index["versions"].insert(0, {
"id": version_id,
"name": "XRPLib {}".format(version),
"dir": version,
"version": version,
})
with open(index_path, "w", newline="\n") as f:
json.dump(index, f, indent=4)
f.write("\n")
print("Created {} and registered {}".format(version_dir, version_id))
if __name__ == "__main__":
main()