blob: 9cc78d110498dc2133639165a0b899f0d1d418f1 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002
3# OpenEmbedded pkgdata utility
4#
5# Written by: Paul Eggleton <paul.eggleton@linux.intel.com>
6#
7# Copyright 2012-2015 Intel Corporation
8#
Brad Bishopc342db32019-05-15 21:57:59 -04009# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
11
12import sys
13import os
14import os.path
15import fnmatch
16import re
17import argparse
18import logging
19from collections import defaultdict, OrderedDict
20
21scripts_path = os.path.dirname(os.path.realpath(__file__))
22lib_path = scripts_path + '/lib'
23sys.path = sys.path + [lib_path]
24import scriptutils
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050025import argparse_oe
Patrick Williamsc124f4f2015-09-15 14:41:29 -050026logger = scriptutils.logger_create('pkgdatautil')
27
28def tinfoil_init():
29 import bb.tinfoil
30 import logging
31 tinfoil = bb.tinfoil.Tinfoil()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050032 tinfoil.logger.setLevel(logging.WARNING)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050033 tinfoil.prepare(True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050034 return tinfoil
35
36
37def glob(args):
38 # Handle both multiple arguments and multiple values within an arg (old syntax)
39 globs = []
40 for globitem in args.glob:
41 globs.extend(globitem.split())
42
43 if not os.path.exists(args.pkglistfile):
44 logger.error('Unable to find package list file %s' % args.pkglistfile)
45 sys.exit(1)
46
47 skipval = "-locale-|^locale-base-|-dev$|-doc$|-dbg$|-staticdev$|^kernel-module-"
48 if args.exclude:
49 skipval += "|" + args.exclude
50 skipregex = re.compile(skipval)
51
Patrick Williamsf1e5d692016-03-30 15:21:19 -050052 skippedpkgs = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050053 mappedpkgs = set()
54 with open(args.pkglistfile, 'r') as f:
55 for line in f:
56 fields = line.rstrip().split()
57 if not fields:
58 continue
59 pkg = fields[0]
60 # We don't care about other args (used to need the package architecture but the
61 # new pkgdata structure avoids the need for that)
62
63 # Skip packages for which there is no point applying globs
64 if skipregex.search(pkg):
65 logger.debug("%s -> !!" % pkg)
Patrick Williamsf1e5d692016-03-30 15:21:19 -050066 skippedpkgs.add(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067 continue
68
69 # Skip packages that already match the globs, so if e.g. a dev package
70 # is already installed and thus in the list, we don't process it any further
71 # Most of these will be caught by skipregex already, but just in case...
72 already = False
73 for g in globs:
74 if fnmatch.fnmatchcase(pkg, g):
75 already = True
76 break
77 if already:
Patrick Williamsf1e5d692016-03-30 15:21:19 -050078 skippedpkgs.add(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050079 logger.debug("%s -> !" % pkg)
80 continue
81
82 # Define some functions
83 def revpkgdata(pkgn):
84 return os.path.join(args.pkgdata_dir, "runtime-reverse", pkgn)
85 def fwdpkgdata(pkgn):
86 return os.path.join(args.pkgdata_dir, "runtime", pkgn)
87 def readpn(pkgdata_file):
88 pn = ""
89 with open(pkgdata_file, 'r') as f:
90 for line in f:
91 if line.startswith("PN:"):
92 pn = line.split(': ')[1].rstrip()
93 return pn
94 def readrenamed(pkgdata_file):
95 renamed = ""
96 pn = os.path.basename(pkgdata_file)
97 with open(pkgdata_file, 'r') as f:
98 for line in f:
99 if line.startswith("PKG_%s:" % pn):
100 renamed = line.split(': ')[1].rstrip()
101 return renamed
102
103 # Main processing loop
104 for g in globs:
105 mappedpkg = ""
106 # First just try substitution (i.e. packagename -> packagename-dev)
107 newpkg = g.replace("*", pkg)
108 revlink = revpkgdata(newpkg)
109 if os.path.exists(revlink):
110 mappedpkg = os.path.basename(os.readlink(revlink))
111 fwdfile = fwdpkgdata(mappedpkg)
112 if os.path.exists(fwdfile):
113 mappedpkg = readrenamed(fwdfile)
114 if not os.path.exists(fwdfile + ".packaged"):
115 mappedpkg = ""
116 else:
117 revlink = revpkgdata(pkg)
118 if os.path.exists(revlink):
119 # Check if we can map after undoing the package renaming (by resolving the symlink)
120 origpkg = os.path.basename(os.readlink(revlink))
121 newpkg = g.replace("*", origpkg)
122 fwdfile = fwdpkgdata(newpkg)
123 if os.path.exists(fwdfile):
124 mappedpkg = readrenamed(fwdfile)
125 else:
126 # That didn't work, so now get the PN, substitute that, then map in the other direction
127 pn = readpn(revlink)
128 newpkg = g.replace("*", pn)
129 fwdfile = fwdpkgdata(newpkg)
130 if os.path.exists(fwdfile):
131 mappedpkg = readrenamed(fwdfile)
132 if not os.path.exists(fwdfile + ".packaged"):
133 mappedpkg = ""
134 else:
135 # Package doesn't even exist...
136 logger.debug("%s is not a valid package!" % (pkg))
137 break
138
139 if mappedpkg:
140 logger.debug("%s (%s) -> %s" % (pkg, g, mappedpkg))
141 mappedpkgs.add(mappedpkg)
142 else:
143 logger.debug("%s (%s) -> ?" % (pkg, g))
144
145 logger.debug("------")
146
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500147 print("\n".join(mappedpkgs - skippedpkgs))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500148
149def read_value(args):
150 # Handle both multiple arguments and multiple values within an arg (old syntax)
151 packages = []
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500152 if args.file:
153 with open(args.file, 'r') as f:
154 for line in f:
155 splitline = line.split()
156 if splitline:
157 packages.append(splitline[0])
158 else:
159 for pkgitem in args.pkg:
160 packages.extend(pkgitem.split())
161 if not packages:
162 logger.error("No packages specified")
163 sys.exit(1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500164
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500165 def readvar(pkgdata_file, valuename, mappedpkg):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500166 val = ""
167 with open(pkgdata_file, 'r') as f:
168 for line in f:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500169 if (line.startswith(valuename + ":") or
170 line.startswith(valuename + "_" + mappedpkg + ":")):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500171 val = line.split(': ', 1)[1].rstrip()
172 return val
173
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500174 logger.debug("read-value('%s', '%s' '%s')" % (args.pkgdata_dir, args.valuename, packages))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500175 for package in packages:
176 pkg_split = package.split('_')
177 pkg_name = pkg_split[0]
178 logger.debug("package: '%s'" % pkg_name)
179 revlink = os.path.join(args.pkgdata_dir, "runtime-reverse", pkg_name)
180 logger.debug(revlink)
181 if os.path.exists(revlink):
182 mappedpkg = os.path.basename(os.readlink(revlink))
183 qvar = args.valuename
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500184 value = readvar(revlink, qvar, mappedpkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500185 if qvar == "PKGSIZE":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186 # PKGSIZE is now in bytes, but we we want it in KB
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500187 pkgsize = (int(value) + 1024 // 2) // 1024
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500188 value = "%d" % pkgsize
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500189 if args.unescape:
190 import codecs
191 # escape_decode() unescapes backslash encodings in byte streams
192 value = codecs.escape_decode(bytes(value, "utf-8"))[0].decode("utf-8")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500193 if args.prefix_name:
194 print('%s %s' % (pkg_name, value))
195 else:
196 print(value)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500197 else:
198 logger.debug("revlink %s does not exist", revlink)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500199
200def lookup_pkglist(pkgs, pkgdata_dir, reverse):
201 if reverse:
202 mappings = OrderedDict()
203 for pkg in pkgs:
204 revlink = os.path.join(pkgdata_dir, "runtime-reverse", pkg)
205 logger.debug(revlink)
206 if os.path.exists(revlink):
207 mappings[pkg] = os.path.basename(os.readlink(revlink))
208 else:
209 mappings = defaultdict(list)
210 for pkg in pkgs:
211 pkgfile = os.path.join(pkgdata_dir, 'runtime', pkg)
212 if os.path.exists(pkgfile):
213 with open(pkgfile, 'r') as f:
214 for line in f:
215 fields = line.rstrip().split(': ')
216 if fields[0] == 'PKG_%s' % pkg:
217 mappings[pkg].append(fields[1])
218 break
219 return mappings
220
221def lookup_pkg(args):
222 # Handle both multiple arguments and multiple values within an arg (old syntax)
223 pkgs = []
224 for pkgitem in args.pkg:
225 pkgs.extend(pkgitem.split())
226
227 mappings = lookup_pkglist(pkgs, args.pkgdata_dir, args.reverse)
228
229 if len(mappings) < len(pkgs):
230 missing = list(set(pkgs) - set(mappings.keys()))
231 logger.error("The following packages could not be found: %s" % ', '.join(missing))
232 sys.exit(1)
233
234 if args.reverse:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600235 items = list(mappings.values())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500236 else:
237 items = []
238 for pkg in pkgs:
239 items.extend(mappings.get(pkg, []))
240
241 print('\n'.join(items))
242
243def lookup_recipe(args):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400244 def parse_pkgdatafile(pkgdatafile):
245 with open(pkgdatafile, 'r') as f:
246 found = False
247 for line in f:
248 if line.startswith('PN:'):
249 print("%s" % line.split(':', 1)[1].strip())
250 found = True
251 break
252 if not found:
253 logger.error("Unable to find PN entry in %s" % pkgdatafile)
254 sys.exit(1)
255
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500256 # Handle both multiple arguments and multiple values within an arg (old syntax)
257 pkgs = []
258 for pkgitem in args.pkg:
259 pkgs.extend(pkgitem.split())
260
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500261 for pkg in pkgs:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400262 providepkgpath = os.path.join(args.pkgdata_dir, "runtime-rprovides", pkg)
263 if os.path.exists(providepkgpath):
264 for f in os.listdir(providepkgpath):
265 if f != pkg:
266 print("%s is in the RPROVIDES of %s:" % (pkg, f))
267 pkgdatafile = os.path.join(args.pkgdata_dir, "runtime", f)
268 parse_pkgdatafile(pkgdatafile)
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700269 continue
Brad Bishop316dfdd2018-06-25 12:45:53 -0400270 pkgdatafile = os.path.join(args.pkgdata_dir, 'runtime-reverse', pkg)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800271 if os.path.exists(pkgdatafile):
272 parse_pkgdatafile(pkgdatafile)
273 else:
274 if args.carryon:
275 print("The following packages could not be found: %s" % pkg)
276 else:
277 logger.error("The following packages could not be found: %s" % pkg)
278 sys.exit(1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500279
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600280def package_info(args):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400281 def parse_pkgdatafile(pkgdatafile):
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700282 vars = ['PKGV', 'PKGE', 'PKGR', 'PN', 'PV', 'PE', 'PR', 'PKGSIZE']
283 if args.extra:
284 vars += args.extra
Brad Bishop316dfdd2018-06-25 12:45:53 -0400285 with open(pkgdatafile, 'r') as f:
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700286 vals = dict()
287 extra = ''
Brad Bishop316dfdd2018-06-25 12:45:53 -0400288 for line in f:
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700289 for var in vars:
290 m = re.match(var + '(?:_\S+)?:\s*(.+?)\s*$', line)
291 if m:
292 vals[var] = m.group(1)
293 pkg_version = vals['PKGV'] or ''
294 recipe = vals['PN'] or ''
295 recipe_version = vals['PV'] or ''
296 pkg_size = vals['PKGSIZE'] or ''
297 if 'PKGE' in vals:
298 pkg_version = vals['PKGE'] + ":" + pkg_version
299 if 'PKGR' in vals:
300 pkg_version = pkg_version + "-" + vals['PKGR']
301 if 'PE' in vals:
302 recipe_version = vals['PE'] + ":" + recipe_version
303 if 'PR' in vals:
304 recipe_version = recipe_version + "-" + vals['PR']
305 if args.extra:
306 for var in args.extra:
307 if var in vals:
308 val = re.sub(r'\s+', ' ', vals[var])
309 extra += ' "%s"' % val
310 print("%s %s %s %s %s%s" % (pkg, pkg_version, recipe, recipe_version, pkg_size, extra))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400311
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600312 # Handle both multiple arguments and multiple values within an arg (old syntax)
313 packages = []
314 if args.file:
315 with open(args.file, 'r') as f:
316 for line in f:
317 splitline = line.split()
318 if splitline:
319 packages.append(splitline[0])
320 else:
321 for pkgitem in args.pkg:
322 packages.extend(pkgitem.split())
323 if not packages:
324 logger.error("No packages specified")
325 sys.exit(1)
326
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600327 for pkg in packages:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400328 providepkgpath = os.path.join(args.pkgdata_dir, "runtime-rprovides", pkg)
329 if os.path.exists(providepkgpath):
330 for f in os.listdir(providepkgpath):
331 if f != pkg:
332 print("%s is in the RPROVIDES of %s:" % (pkg, f))
333 pkgdatafile = os.path.join(args.pkgdata_dir, "runtime", f)
334 parse_pkgdatafile(pkgdatafile)
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700335 continue
Brad Bishop316dfdd2018-06-25 12:45:53 -0400336 pkgdatafile = os.path.join(args.pkgdata_dir, "runtime-reverse", pkg)
337 if not os.path.exists(pkgdatafile):
338 logger.error("Unable to find any built runtime package named %s" % pkg)
339 sys.exit(1)
340 parse_pkgdatafile(pkgdatafile)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600341
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500342def get_recipe_pkgs(pkgdata_dir, recipe, unpackaged):
343 recipedatafile = os.path.join(pkgdata_dir, recipe)
344 if not os.path.exists(recipedatafile):
345 logger.error("Unable to find packaged recipe with name %s" % recipe)
346 sys.exit(1)
347 packages = []
348 with open(recipedatafile, 'r') as f:
349 for line in f:
350 fields = line.rstrip().split(': ')
351 if fields[0] == 'PACKAGES':
352 packages = fields[1].split()
353 break
354
355 if not unpackaged:
356 pkglist = []
357 for pkg in packages:
358 if os.path.exists(os.path.join(pkgdata_dir, 'runtime', '%s.packaged' % pkg)):
359 pkglist.append(pkg)
360 return pkglist
361 else:
362 return packages
363
364def list_pkgs(args):
365 found = False
366
367 def matchpkg(pkg):
368 if args.pkgspec:
369 matched = False
370 for pkgspec in args.pkgspec:
371 if fnmatch.fnmatchcase(pkg, pkgspec):
372 matched = True
373 break
374 if not matched:
375 return False
376 if not args.unpackaged:
377 if args.runtime:
378 revlink = os.path.join(args.pkgdata_dir, "runtime-reverse", pkg)
379 if os.path.exists(revlink):
380 # We're unlikely to get here if the package was not packaged, but just in case
381 # we add the symlinks for unpackaged files in the future
382 mappedpkg = os.path.basename(os.readlink(revlink))
383 if not os.path.exists(os.path.join(args.pkgdata_dir, 'runtime', '%s.packaged' % mappedpkg)):
384 return False
385 else:
386 return False
387 else:
388 if not os.path.exists(os.path.join(args.pkgdata_dir, 'runtime', '%s.packaged' % pkg)):
389 return False
390 return True
391
392 if args.recipe:
393 packages = get_recipe_pkgs(args.pkgdata_dir, args.recipe, args.unpackaged)
394
395 if args.runtime:
396 pkglist = []
397 runtime_pkgs = lookup_pkglist(packages, args.pkgdata_dir, False)
398 for rtpkgs in runtime_pkgs.values():
399 pkglist.extend(rtpkgs)
400 else:
401 pkglist = packages
402
403 for pkg in pkglist:
404 if matchpkg(pkg):
405 found = True
406 print("%s" % pkg)
407 else:
408 if args.runtime:
409 searchdir = 'runtime-reverse'
410 else:
411 searchdir = 'runtime'
412
413 for root, dirs, files in os.walk(os.path.join(args.pkgdata_dir, searchdir)):
414 for fn in files:
415 if fn.endswith('.packaged'):
416 continue
417 if matchpkg(fn):
418 found = True
419 print("%s" % fn)
420 if not found:
421 if args.pkgspec:
422 logger.error("Unable to find any package matching %s" % args.pkgspec)
423 else:
424 logger.error("No packages found")
425 sys.exit(1)
426
427def list_pkg_files(args):
428 import json
Brad Bishop316dfdd2018-06-25 12:45:53 -0400429 def parse_pkgdatafile(pkgdatafile, long=False):
430 with open(pkgdatafile, 'r') as f:
431 found = False
432 for line in f:
433 if line.startswith('FILES_INFO:'):
434 found = True
435 val = line.split(':', 1)[1].strip()
436 dictval = json.loads(val)
437 if long:
438 width = max(map(len, dictval), default=0)
439 for fullpth in sorted(dictval):
440 print("\t{:{width}}\t{}".format(fullpth, dictval[fullpth], width=width))
441 else:
442 for fullpth in sorted(dictval):
443 print("\t%s" % fullpth)
444 break
445 if not found:
446 logger.error("Unable to find FILES_INFO entry in %s" % pkgdatafile)
447 sys.exit(1)
448
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500449
450 if args.recipe:
451 if args.pkg:
452 logger.error("list-pkg-files: If -p/--recipe is specified then a package name cannot be specified")
453 sys.exit(1)
454 recipepkglist = get_recipe_pkgs(args.pkgdata_dir, args.recipe, args.unpackaged)
455 if args.runtime:
456 pkglist = []
457 runtime_pkgs = lookup_pkglist(recipepkglist, args.pkgdata_dir, False)
458 for rtpkgs in runtime_pkgs.values():
459 pkglist.extend(rtpkgs)
460 else:
461 pkglist = recipepkglist
462 else:
463 if not args.pkg:
464 logger.error("list-pkg-files: If -p/--recipe is not specified then at least one package name must be specified")
465 sys.exit(1)
466 pkglist = args.pkg
467
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500468 for pkg in sorted(pkglist):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500469 print("%s:" % pkg)
470 if args.runtime:
471 pkgdatafile = os.path.join(args.pkgdata_dir, "runtime-reverse", pkg)
472 if not os.path.exists(pkgdatafile):
473 if args.recipe:
474 # This package was empty and thus never packaged, ignore
475 continue
476 logger.error("Unable to find any built runtime package named %s" % pkg)
477 sys.exit(1)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400478 parse_pkgdatafile(pkgdatafile, args.long)
479
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500480 else:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400481 providepkgpath = os.path.join(args.pkgdata_dir, "runtime-rprovides", pkg)
482 if os.path.exists(providepkgpath):
483 for f in os.listdir(providepkgpath):
484 if f != pkg:
485 print("%s is in the RPROVIDES of %s:" % (pkg, f))
486 pkgdatafile = os.path.join(args.pkgdata_dir, "runtime", f)
487 parse_pkgdatafile(pkgdatafile, args.long)
488 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500489 pkgdatafile = os.path.join(args.pkgdata_dir, "runtime", pkg)
490 if not os.path.exists(pkgdatafile):
491 logger.error("Unable to find any built recipe-space package named %s" % pkg)
492 sys.exit(1)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400493 parse_pkgdatafile(pkgdatafile, args.long)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500494
495def find_path(args):
496 import json
497
498 found = False
499 for root, dirs, files in os.walk(os.path.join(args.pkgdata_dir, 'runtime')):
500 for fn in files:
501 with open(os.path.join(root,fn)) as f:
502 for line in f:
503 if line.startswith('FILES_INFO:'):
504 val = line.split(':', 1)[1].strip()
505 dictval = json.loads(val)
506 for fullpth in dictval.keys():
507 if fnmatch.fnmatchcase(fullpth, args.targetpath):
508 found = True
509 print("%s: %s" % (fn, fullpth))
510 break
511 if not found:
512 logger.error("Unable to find any package producing path %s" % args.targetpath)
513 sys.exit(1)
514
515
516def main():
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500517 parser = argparse_oe.ArgumentParser(description="OpenEmbedded pkgdata tool - queries the pkgdata files written out during do_package",
518 epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500519 parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
520 parser.add_argument('-p', '--pkgdata-dir', help='Path to pkgdata directory (determined automatically if not specified)')
521 subparsers = parser.add_subparsers(title='subcommands', metavar='<subcommand>')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600522 subparsers.required = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500523
524 parser_lookup_pkg = subparsers.add_parser('lookup-pkg',
525 help='Translate between recipe-space package names and runtime package names',
526 description='Looks up the specified recipe-space package name(s) to see what the final runtime package name is (e.g. glibc becomes libc6), or with -r/--reverse looks up the other way.')
527 parser_lookup_pkg.add_argument('pkg', nargs='+', help='Package name to look up')
528 parser_lookup_pkg.add_argument('-r', '--reverse', help='Switch to looking up recipe-space package names from runtime package names', action='store_true')
529 parser_lookup_pkg.set_defaults(func=lookup_pkg)
530
531 parser_list_pkgs = subparsers.add_parser('list-pkgs',
532 help='List packages',
533 description='Lists packages that have been built')
534 parser_list_pkgs.add_argument('pkgspec', nargs='*', help='Package name to search for (wildcards * ? allowed, use quotes to avoid shell expansion)')
535 parser_list_pkgs.add_argument('-r', '--runtime', help='Show runtime package names instead of recipe-space package names', action='store_true')
536 parser_list_pkgs.add_argument('-p', '--recipe', help='Limit to packages produced by the specified recipe')
537 parser_list_pkgs.add_argument('-u', '--unpackaged', help='Include unpackaged (i.e. empty) packages', action='store_true')
538 parser_list_pkgs.set_defaults(func=list_pkgs)
539
540 parser_list_pkg_files = subparsers.add_parser('list-pkg-files',
541 help='List files within a package',
542 description='Lists files included in one or more packages')
543 parser_list_pkg_files.add_argument('pkg', nargs='*', help='Package name to report on (if -p/--recipe is not specified)')
544 parser_list_pkg_files.add_argument('-r', '--runtime', help='Specified package(s) are runtime package names instead of recipe-space package names', action='store_true')
545 parser_list_pkg_files.add_argument('-p', '--recipe', help='Report on all packages produced by the specified recipe')
546 parser_list_pkg_files.add_argument('-u', '--unpackaged', help='Include unpackaged (i.e. empty) packages (only useful with -p/--recipe)', action='store_true')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400547 parser_list_pkg_files.add_argument('-l', '--long', help='Show more information per file', action='store_true')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500548 parser_list_pkg_files.set_defaults(func=list_pkg_files)
549
550 parser_lookup_recipe = subparsers.add_parser('lookup-recipe',
551 help='Find recipe producing one or more packages',
552 description='Looks up the specified runtime package(s) to see which recipe they were produced by')
553 parser_lookup_recipe.add_argument('pkg', nargs='+', help='Runtime package name to look up')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800554 parser_lookup_recipe.add_argument('-c', '--continue', dest="carryon", help='Continue looking up recipes even if we can not find one', action='store_true')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500555 parser_lookup_recipe.set_defaults(func=lookup_recipe)
556
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600557 parser_package_info = subparsers.add_parser('package-info',
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500558 help='Show version, recipe and size information for one or more packages',
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600559 description='Looks up the specified runtime package(s) and display information')
560 parser_package_info.add_argument('pkg', nargs='*', help='Runtime package name to look up')
561 parser_package_info.add_argument('-f', '--file', help='Read package names from the specified file (one per line, first field only)')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500562 parser_package_info.add_argument('-e', '--extra', help='Extra variables to display, e.g., LICENSE (can be specified multiple times)', action='append')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600563 parser_package_info.set_defaults(func=package_info)
564
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500565 parser_find_path = subparsers.add_parser('find-path',
566 help='Find package providing a target path',
567 description='Finds the recipe-space package providing the specified target path')
568 parser_find_path.add_argument('targetpath', help='Path to find (wildcards * ? allowed, use quotes to avoid shell expansion)')
569 parser_find_path.set_defaults(func=find_path)
570
571 parser_read_value = subparsers.add_parser('read-value',
572 help='Read any pkgdata value for one or more packages',
573 description='Reads the named value from the pkgdata files for the specified packages')
574 parser_read_value.add_argument('valuename', help='Name of the value to look up')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500575 parser_read_value.add_argument('pkg', nargs='*', help='Runtime package name to look up')
576 parser_read_value.add_argument('-f', '--file', help='Read package names from the specified file (one per line, first field only)')
577 parser_read_value.add_argument('-n', '--prefix-name', help='Prefix output with package name', action='store_true')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500578 parser_read_value.add_argument('-u', '--unescape', help='Expand escapes such as \\n', action='store_true')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500579 parser_read_value.set_defaults(func=read_value)
580
581 parser_glob = subparsers.add_parser('glob',
582 help='Expand package name glob expression',
583 description='Expands one or more glob expressions over the packages listed in pkglistfile')
584 parser_glob.add_argument('pkglistfile', help='File listing packages (one package name per line)')
585 parser_glob.add_argument('glob', nargs="+", help='Glob expression for package names, e.g. *-dev')
586 parser_glob.add_argument('-x', '--exclude', help='Exclude packages matching specified regex from the glob operation')
587 parser_glob.set_defaults(func=glob)
588
589
590 args = parser.parse_args()
591
592 if args.debug:
593 logger.setLevel(logging.DEBUG)
594
595 if not args.pkgdata_dir:
596 import scriptpath
597 bitbakepath = scriptpath.add_bitbake_lib_path()
598 if not bitbakepath:
599 logger.error("Unable to find bitbake by searching parent directory of this script or PATH")
600 sys.exit(1)
601 logger.debug('Found bitbake path: %s' % bitbakepath)
602 tinfoil = tinfoil_init()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600603 try:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500604 args.pkgdata_dir = tinfoil.config_data.getVar('PKGDATA_DIR')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600605 finally:
606 tinfoil.shutdown()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500607 logger.debug('Value of PKGDATA_DIR is "%s"' % args.pkgdata_dir)
608 if not args.pkgdata_dir:
609 logger.error('Unable to determine pkgdata directory from PKGDATA_DIR')
610 sys.exit(1)
611
612 if not os.path.exists(args.pkgdata_dir):
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500613 logger.error('Unable to find pkgdata directory %s' % args.pkgdata_dir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500614 sys.exit(1)
615
616 ret = args.func(args)
617
618 return ret
619
620
621if __name__ == "__main__":
622 main()