summaryrefslogtreecommitdiffstats
path: root/scripts/bblock
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/bblock')
-rwxr-xr-xscripts/bblock184
1 files changed, 184 insertions, 0 deletions
diff --git a/scripts/bblock b/scripts/bblock
new file mode 100755
index 0000000000..0082059af8
--- /dev/null
+++ b/scripts/bblock
@@ -0,0 +1,184 @@
1#!/usr/bin/env python3
2# bblock
3# lock/unlock task to latest signature
4#
5# Copyright (c) 2023 BayLibre, SAS
6# Author: Julien Stepahn <jstephan@baylibre.com>
7#
8# SPDX-License-Identifier: GPL-2.0-only
9#
10
11import os
12import sys
13import logging
14
15scripts_path = os.path.dirname(os.path.realpath(__file__))
16lib_path = scripts_path + "/lib"
17sys.path = sys.path + [lib_path]
18
19import scriptpath
20
21scriptpath.add_bitbake_lib_path()
22
23import bb.tinfoil
24import bb.msg
25
26import argparse_oe
27
28myname = os.path.basename(sys.argv[0])
29logger = bb.msg.logger_create(myname)
30
31
32def getTaskSignatures(tinfoil, pn, tasks):
33 tinfoil.set_event_mask(
34 [
35 "bb.event.GetTaskSignatureResult",
36 "logging.LogRecord",
37 "bb.command.CommandCompleted",
38 "bb.command.CommandFailed",
39 ]
40 )
41 ret = tinfoil.run_command("getTaskSignatures", pn, tasks)
42 if ret:
43 while True:
44 event = tinfoil.wait_event(1)
45 if event:
46 if isinstance(event, bb.command.CommandCompleted):
47 break
48 elif isinstance(event, bb.command.CommandFailed):
49 logger.error(str(event))
50 sys.exit(2)
51 elif isinstance(event, bb.event.GetTaskSignatureResult):
52 sig = event.sig
53 elif isinstance(event, logging.LogRecord):
54 logger.handle(event)
55 else:
56 logger.error("No result returned from getTaskSignatures command")
57 sys.exit(2)
58 return sig
59
60
61def parseRecipe(tinfoil, recipe):
62 try:
63 tinfoil.parse_recipes()
64 d = tinfoil.parse_recipe(recipe)
65 except Exception:
66 logger.error("Failed to get recipe info for: %s" % recipe)
67 sys.exit(1)
68 return d
69
70
71def bblockDump(lockfile):
72 try:
73 with open(lockfile, "r") as lockfile:
74 for line in lockfile:
75 print(line.strip())
76 except IOError:
77 return 1
78 return 0
79
80
81def bblockReset(lockfile, pns, package_archs, tasks):
82 if not pns:
83 logger.info("Unlocking all recipes")
84 try:
85 os.remove(lockfile)
86 except FileNotFoundError:
87 pass
88 else:
89 logger.info("Unlocking {pns}".format(pns=pns))
90 tmp_lockfile = lockfile + ".tmp"
91 with open(lockfile, "r") as infile, open(tmp_lockfile, "w") as outfile:
92 for line in infile:
93 if not (
94 any(element in line for element in pns)
95 and any(element in line for element in package_archs.split())
96 ):
97 outfile.write(line)
98 else:
99 if tasks and not any(element in line for element in tasks):
100 outfile.write(line)
101 os.remove(lockfile)
102 os.rename(tmp_lockfile, lockfile)
103
104
105def main():
106 parser = argparse_oe.ArgumentParser(description="Lock and unlock a recipe")
107 parser.add_argument("pn", nargs="*", help="Space separated list of recipe to lock")
108 parser.add_argument(
109 "-t",
110 "--tasks",
111 help="Comma separated list of tasks",
112 type=lambda s: [
113 task if task.startswith("do_") else "do_" + task for task in s.split(",")
114 ],
115 )
116 parser.add_argument(
117 "-r",
118 "--reset",
119 action="store_true",
120 help="Unlock pn recipes, or all recipes if pn is empty",
121 )
122 parser.add_argument(
123 "-d",
124 "--dump",
125 action="store_true",
126 help="Dump generated bblock.conf file",
127 )
128
129 global_args, unparsed_args = parser.parse_known_args()
130
131 with bb.tinfoil.Tinfoil() as tinfoil:
132 tinfoil.prepare(config_only=True)
133
134 package_archs = tinfoil.config_data.getVar("PACKAGE_ARCHS")
135 builddir = tinfoil.config_data.getVar("TOPDIR")
136 lockfile = "{builddir}/conf/bblock.conf".format(builddir=builddir)
137
138 if global_args.dump:
139 bblockDump(lockfile)
140 return 0
141
142 if global_args.reset:
143 bblockReset(lockfile, global_args.pn, package_archs, global_args.tasks)
144 return 0
145
146 with open(lockfile, "a") as lockfile:
147 s = ""
148 if lockfile.tell() == 0:
149 s = "# Generated by bblock\n"
150 s += 'SIGGEN_LOCKEDSIGS_TASKSIG_CHECK = "info"\n'
151 s += 'SIGGEN_LOCKEDSIGS_TYPES += "${PACKAGE_ARCHS}"\n'
152 s += "\n"
153
154 for pn in global_args.pn:
155 d = parseRecipe(tinfoil, pn)
156 package_arch = d.getVar("PACKAGE_ARCH")
157 siggen_locked_sigs_package_arch = d.getVar(
158 "SIGGEN_LOCKEDSIGS_{package_arch}".format(package_arch=package_arch)
159 )
160 sigs = getTaskSignatures(tinfoil, [pn], global_args.tasks)
161 for sig in sigs:
162 new_entry = "{pn}:{taskname}:{sig}".format(
163 pn=sig[0], taskname=sig[1], sig=sig[2]
164 )
165 if (
166 siggen_locked_sigs_package_arch
167 and not new_entry in siggen_locked_sigs_package_arch
168 ) or not siggen_locked_sigs_package_arch:
169 s += 'SIGGEN_LOCKEDSIGS_{package_arch} += "{new_entry}"\n'.format(
170 package_arch=package_arch, new_entry=new_entry
171 )
172 lockfile.write(s)
173 return 0
174
175
176if __name__ == "__main__":
177 try:
178 ret = main()
179 except Exception:
180 ret = 1
181 import traceback
182
183 traceback.print_exc()
184 sys.exit(ret)