summaryrefslogtreecommitdiffstats
path: root/scripts/oe-pkgdata-util
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2015-02-05 15:08:22 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-02-14 08:41:01 +0000
commit9f03969994797220663280ef13fcb187446335ee (patch)
treed1baa9a8e0c30c86de653f70ec566c253e7af63f /scripts/oe-pkgdata-util
parent675aa5f57a83f1e5712139e90d57d4946d78b6db (diff)
downloadpoky-9f03969994797220663280ef13fcb187446335ee.tar.gz
oe-pkgdata-util: improve command-line usage
* Use argparse instead of optparse for standardised help output, options and a much cleaner code structure * Look up pkgdata directory automatically so the user doesn't have to specify it * Use standard logging NOTE: this does mean a slight change in syntax - if you do want to specify the pkgdata directory (usually only necessary if you're calling it from within the build process) you need to use the parameter -p (or --pkgdata-dir) and specify this before the command, not after it. Examples: oe-pkgdata-util find-path /sbin/mke2fs oe-pkgdata-util lookup-recipe libelf1 oe-pkgdata-util read-value PKGSIZE libc6 oe-pkgdata-util -p /home/user/oe/build/tmp/sysroots/qemux86-64/pkgdata read-value PKGSIZE libc6 (From OE-Core rev: 04dc571ac7c26f0dcf1a1fcd466482e22519998d) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/oe-pkgdata-util')
-rwxr-xr-xscripts/oe-pkgdata-util264
1 files changed, 128 insertions, 136 deletions
diff --git a/scripts/oe-pkgdata-util b/scripts/oe-pkgdata-util
index bf8754749e..f70f85e147 100755
--- a/scripts/oe-pkgdata-util
+++ b/scripts/oe-pkgdata-util
@@ -4,7 +4,7 @@
4# 4#
5# Written by: Paul Eggleton <paul.eggleton@linux.intel.com> 5# Written by: Paul Eggleton <paul.eggleton@linux.intel.com>
6# 6#
7# Copyright 2012-2013 Intel Corporation 7# Copyright 2012-2015 Intel Corporation
8# 8#
9# This program is free software; you can redistribute it and/or modify 9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as 10# it under the terms of the GNU General Public License version 2 as
@@ -25,30 +25,40 @@ import os
25import os.path 25import os.path
26import fnmatch 26import fnmatch
27import re 27import re
28import optparse 28import argparse
29import logging
29from collections import defaultdict 30from collections import defaultdict
30 31
31def glob(args, usage, debug=False): 32scripts_path = os.path.dirname(os.path.realpath(__file__))
32 if len(args) < 3: 33lib_path = scripts_path + '/lib'
33 usage() 34sys.path = sys.path + [lib_path]
34 sys.exit(1) 35import scriptutils
36logger = scriptutils.logger_create('pkgdatautil')
35 37
36 pkgdata_dir = args[0] 38def tinfoil_init():
37 pkglist_file = args[1] 39 import bb.tinfoil
38 globs = args[2].split() 40 import logging
41 tinfoil = bb.tinfoil.Tinfoil()
42 tinfoil.prepare(True)
43
44 tinfoil.logger.setLevel(logging.WARNING)
45 return tinfoil
39 46
40 if not os.path.exists(pkgdata_dir):
41 print('ERROR: Unable to find pkgdata directory %s' % pkgdata_dir)
42 sys.exit(1)
43 47
44 if not os.path.exists(pkglist_file): 48def glob(args):
45 print('ERROR: Unable to find package list file %s' % pkglist_file) 49 # Handle both multiple arguments and multiple values within an arg (old syntax)
50 globs = []
51 for globitem in args.glob:
52 globs.extend(globitem.split())
53
54 if not os.path.exists(args.pkglistfile):
55 logger.error('Unable to find package list file %s' % args.pkglistfile)
46 sys.exit(1) 56 sys.exit(1)
47 57
48 skipregex = re.compile("-locale-|^locale-base-|-dev$|-doc$|-dbg$|-staticdev$|^kernel-module-") 58 skipregex = re.compile("-locale-|^locale-base-|-dev$|-doc$|-dbg$|-staticdev$|^kernel-module-")
49 59
50 mappedpkgs = set() 60 mappedpkgs = set()
51 with open(pkglist_file, 'r') as f: 61 with open(args.pkglistfile, 'r') as f:
52 for line in f: 62 for line in f:
53 fields = line.rstrip().split() 63 fields = line.rstrip().split()
54 if not fields: 64 if not fields:
@@ -59,8 +69,7 @@ def glob(args, usage, debug=False):
59 69
60 # Skip packages for which there is no point applying globs 70 # Skip packages for which there is no point applying globs
61 if skipregex.search(pkg): 71 if skipregex.search(pkg):
62 if debug: 72 logger.debug("%s -> !!" % pkg)
63 print("%s -> !!" % pkg)
64 continue 73 continue
65 74
66 # Skip packages that already match the globs, so if e.g. a dev package 75 # Skip packages that already match the globs, so if e.g. a dev package
@@ -72,15 +81,14 @@ def glob(args, usage, debug=False):
72 already = True 81 already = True
73 break 82 break
74 if already: 83 if already:
75 if debug: 84 logger.debug("%s -> !" % pkg)
76 print("%s -> !" % pkg)
77 continue 85 continue
78 86
79 # Define some functions 87 # Define some functions
80 def revpkgdata(pkgn): 88 def revpkgdata(pkgn):
81 return os.path.join(pkgdata_dir, "runtime-reverse", pkgn) 89 return os.path.join(args.pkgdata_dir, "runtime-reverse", pkgn)
82 def fwdpkgdata(pkgn): 90 def fwdpkgdata(pkgn):
83 return os.path.join(pkgdata_dir, "runtime", pkgn) 91 return os.path.join(args.pkgdata_dir, "runtime", pkgn)
84 def readpn(pkgdata_file): 92 def readpn(pkgdata_file):
85 pn = "" 93 pn = ""
86 with open(pkgdata_file, 'r') as f: 94 with open(pkgdata_file, 'r') as f:
@@ -130,81 +138,61 @@ def glob(args, usage, debug=False):
130 mappedpkg = "" 138 mappedpkg = ""
131 else: 139 else:
132 # Package doesn't even exist... 140 # Package doesn't even exist...
133 if debug: 141 logger.debug("%s is not a valid package!" % (pkg))
134 print "%s is not a valid package!" % (pkg)
135 break 142 break
136 143
137 if mappedpkg: 144 if mappedpkg:
138 if debug: 145 logger.debug("%s (%s) -> %s" % (pkg, g, mappedpkg))
139 print "%s (%s) -> %s" % (pkg, g, mappedpkg)
140 mappedpkgs.add(mappedpkg) 146 mappedpkgs.add(mappedpkg)
141 else: 147 else:
142 if debug: 148 logger.debug("%s (%s) -> ?" % (pkg, g))
143 print "%s (%s) -> ?" % (pkg, g)
144 149
145 if debug: 150 logger.debug("------")
146 print "------"
147 151
148 print("\n".join(mappedpkgs)) 152 print("\n".join(mappedpkgs))
149 153
150def read_value(args, usage, debug=False): 154def read_value(args):
151 if len(args) < 3: 155 # Handle both multiple arguments and multiple values within an arg (old syntax)
152 usage() 156 packages = []
153 sys.exit(1) 157 for pkgitem in args.pkg:
154 158 packages.extend(pkgitem.split())
155 pkgdata_dir = args[0]
156 var = args[1]
157 packages = args[2].split()
158 159
159 if not os.path.exists(pkgdata_dir): 160 def readvar(pkgdata_file, valuename):
160 print('ERROR: Unable to find pkgdata directory %s' % pkgdata_dir)
161 sys.exit(1)
162
163 def readvar(pkgdata_file, var):
164 val = "" 161 val = ""
165 with open(pkgdata_file, 'r') as f: 162 with open(pkgdata_file, 'r') as f:
166 for line in f: 163 for line in f:
167 if line.startswith(var + ":"): 164 if line.startswith(valuename + ":"):
168 val = line.split(': ')[1].rstrip() 165 val = line.split(': ')[1].rstrip()
169 return val 166 return val
170 167
171 if debug: 168 logger.debug("read-value('%s', '%s' '%s'" % (args.pkgdata_dir, args.valuename, packages))
172 print "read-value('%s', '%s' '%s'" % (pkgdata_dir, var, packages)
173 for package in packages: 169 for package in packages:
174 pkg_split = package.split('_') 170 pkg_split = package.split('_')
175 pkg_name = pkg_split[0] 171 pkg_name = pkg_split[0]
176 if debug: 172 logger.debug("package: '%s'" % pkg_name)
177 print "package: '%s'" % pkg_name 173 revlink = os.path.join(args.pkgdata_dir, "runtime-reverse", pkg_name)
178 revlink = os.path.join(pkgdata_dir, "runtime-reverse", pkg_name) 174 logger.debug(revlink)
179 if debug:
180 print(revlink)
181 if os.path.exists(revlink): 175 if os.path.exists(revlink):
182 mappedpkg = os.path.basename(os.readlink(revlink)) 176 mappedpkg = os.path.basename(os.readlink(revlink))
183 qvar = var 177 qvar = args.valuename
184 if qvar == "PKGSIZE": 178 if qvar == "PKGSIZE":
185 # append packagename 179 # append packagename
186 qvar = "%s_%s" % (var, mappedpkg) 180 qvar = "%s_%s" % (args.valuename, mappedpkg)
187 # PKGSIZE is now in bytes, but we we want it in KB 181 # PKGSIZE is now in bytes, but we we want it in KB
188 pkgsize = (int(readvar(revlink, qvar)) + 1024 // 2) // 1024 182 pkgsize = (int(readvar(revlink, qvar)) + 1024 // 2) // 1024
189 print("%d" % pkgsize) 183 print("%d" % pkgsize)
190 else: 184 else:
191 print(readvar(revlink, qvar)) 185 print(readvar(revlink, qvar))
192 186
193def lookup_pkg(args, usage, debug=False): 187def lookup_pkg(args):
194 if len(args) < 2: 188 # Handle both multiple arguments and multiple values within an arg (old syntax)
195 usage() 189 pkgs = []
196 sys.exit(1) 190 for pkgitem in args.recipepkg:
197 191 pkgs.extend(pkgitem.split())
198 pkgdata_dir = args[0]
199 pkgs = args[1].split()
200
201 if not os.path.exists(pkgdata_dir):
202 print('ERROR: Unable to find pkgdata directory %s' % pkgdata_dir)
203 sys.exit(1)
204 192
205 mappings = defaultdict(list) 193 mappings = defaultdict(list)
206 for pkg in pkgs: 194 for pkg in pkgs:
207 pkgfile = os.path.join(pkgdata_dir, 'runtime', pkg) 195 pkgfile = os.path.join(args.pkgdata_dir, 'runtime', pkg)
208 if os.path.exists(pkgfile): 196 if os.path.exists(pkgfile):
209 with open(pkgfile, 'r') as f: 197 with open(pkgfile, 'r') as f:
210 for line in f: 198 for line in f:
@@ -214,29 +202,23 @@ def lookup_pkg(args, usage, debug=False):
214 break 202 break
215 if len(mappings) < len(pkgs): 203 if len(mappings) < len(pkgs):
216 missing = list(set(pkgs) - set(mappings.keys())) 204 missing = list(set(pkgs) - set(mappings.keys()))
217 sys.stderr.write("ERROR: the following packages could not be found: %s\n" % ', '.join(missing)) 205 logger.error("The following packages could not be found: %s" % ', '.join(missing))
218 sys.exit(1) 206 sys.exit(1)
219 207
220 items = [] 208 items = []
221 for pkg in pkgs: 209 for pkg in pkgs:
222 items.extend(mappings.get(pkg, [])) 210 items.extend(mappings.get(pkg, []))
223 print '\n'.join(items) 211 print('\n'.join(items))
224 212
225def lookup_recipe(args, usage, debug=False): 213def lookup_recipe(args):
226 if len(args) < 2: 214 # Handle both multiple arguments and multiple values within an arg (old syntax)
227 usage() 215 pkgs = []
228 sys.exit(1) 216 for pkgitem in args.pkg:
229 217 pkgs.extend(pkgitem.split())
230 pkgdata_dir = args[0]
231 pkgs = args[1].split()
232
233 if not os.path.exists(pkgdata_dir):
234 print('ERROR: Unable to find pkgdata directory %s' % pkgdata_dir)
235 sys.exit(1)
236 218
237 mappings = defaultdict(list) 219 mappings = defaultdict(list)
238 for pkg in pkgs: 220 for pkg in pkgs:
239 pkgfile = os.path.join(pkgdata_dir, 'runtime-reverse', pkg) 221 pkgfile = os.path.join(args.pkgdata_dir, 'runtime-reverse', pkg)
240 if os.path.exists(pkgfile): 222 if os.path.exists(pkgfile):
241 with open(pkgfile, 'r') as f: 223 with open(pkgfile, 'r') as f:
242 for line in f: 224 for line in f:
@@ -246,30 +228,18 @@ def lookup_recipe(args, usage, debug=False):
246 break 228 break
247 if len(mappings) < len(pkgs): 229 if len(mappings) < len(pkgs):
248 missing = list(set(pkgs) - set(mappings.keys())) 230 missing = list(set(pkgs) - set(mappings.keys()))
249 sys.stderr.write("ERROR: the following packages could not be found: %s\n" % ', '.join(missing)) 231 logger.error("The following packages could not be found: %s" % ', '.join(missing))
250 sys.exit(1) 232 sys.exit(1)
251 233
252 items = [] 234 items = []
253 for pkg in pkgs: 235 for pkg in pkgs:
254 items.extend(mappings.get(pkg, [])) 236 items.extend(mappings.get(pkg, []))
255 print '\n'.join(items) 237 print('\n'.join(items))
256
257def find_path(args, usage, debug=False):
258 if len(args) < 2:
259 usage()
260 sys.exit(1)
261
262 pkgdata_dir = args[0]
263 targetpath = args[1]
264
265 if not os.path.exists(pkgdata_dir):
266 print('ERROR: Unable to find pkgdata directory %s' % pkgdata_dir)
267 sys.exit(1)
268 238
239def find_path(args):
269 import json 240 import json
270 import fnmatch
271 241
272 for root, dirs, files in os.walk(os.path.join(pkgdata_dir, 'runtime')): 242 for root, dirs, files in os.walk(os.path.join(args.pkgdata_dir, 'runtime')):
273 for fn in files: 243 for fn in files:
274 with open(os.path.join(root,fn)) as f: 244 with open(os.path.join(root,fn)) as f:
275 for line in f: 245 for line in f:
@@ -277,55 +247,77 @@ def find_path(args, usage, debug=False):
277 val = line.split(':', 1)[1].strip() 247 val = line.split(':', 1)[1].strip()
278 dictval = json.loads(val) 248 dictval = json.loads(val)
279 for fullpth in dictval.keys(): 249 for fullpth in dictval.keys():
280 if fnmatch.fnmatchcase(fullpth, targetpath): 250 if fnmatch.fnmatchcase(fullpth, args.targetpath):
281 print("%s: %s" % (fn, fullpth)) 251 print("%s: %s" % (fn, fullpth))
282 break 252 break
283 253
284 254
285def main(): 255def main():
286 parser = optparse.OptionParser( 256 parser = argparse.ArgumentParser(description="OpenEmbedded pkgdata tool - queries the pkgdata files written out during do_package",
287 usage = '''%prog [options] <command> <arguments> 257 epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
288 258 parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
289Available commands: 259 parser.add_argument('-p', '--pkgdata-dir', help='Path to pkgdata directory (determined automatically if not specified)')
290 glob <pkgdatadir> <pkglistfile> "<globs>" 260 subparsers = parser.add_subparsers(title='subcommands', metavar='<subcommand>')
291 expand one or more glob expressions over the packages listed in 261
292 pkglistfile (one package per line) 262 parser_lookup_pkg = subparsers.add_parser('lookup-pkg',
293 lookup-pkg <pkgdatadir> "<recipe-pkgs>" 263 help='Translate recipe-space package names to runtime package names',
294 look up the specified recipe-space package name(s) to see what the 264 description='Looks up the specified recipe-space package name(s) to see what the final runtime package name is (e.g. glibc becomes libc6)')
295 final runtime package name is (e.g. eglibc becomes libc6) 265 parser_lookup_pkg.add_argument('recipepkg', nargs='+', help='Recipe-space package name to look up')
296 lookup-recipe <pkgdatadir> "<pkgs>" 266 parser_lookup_pkg.set_defaults(func=lookup_pkg)
297 look up the specified package(s) to see which recipe they were 267
298 produced by 268 parser_lookup_recipe = subparsers.add_parser('lookup-recipe',
299 find-path <pkgdatadir> <path> 269 help='Find recipe producing one or more packages',
300 find the package providing the specified path (wildcards * ? allowed) 270 description='Looks up the specified runtime package(s) to see which recipe they were produced by')
301 read-value <pkgdatadir> <value-name> "<pkgs>" 271 parser_lookup_recipe.add_argument('pkg', nargs='+', help='Runtime package name to look up')
302 read the named value from the pkgdata files for the specified 272 parser_lookup_recipe.set_defaults(func=lookup_recipe)
303 packages''') 273
304 274 parser_find_path = subparsers.add_parser('find-path',
305 parser.add_option("-d", "--debug", 275 help='Find package providing a target path',
306 help = "Enable debug output", 276 description='Finds the recipe-space package providing the specified target path')
307 action="store_true", dest="debug", default=False) 277 parser_find_path.add_argument('targetpath', help='Path to find (wildcards * ? allowed, use quotes to avoid shell expansion)')
308 278 parser_find_path.set_defaults(func=find_path)
309 options, args = parser.parse_args(sys.argv) 279
310 args = args[1:] 280 parser_read_value = subparsers.add_parser('read-value',
311 281 help='Read any pkgdata value for one or more packages',
312 if len(args) < 1: 282 description='Reads the named value from the pkgdata files for the specified packages')
313 parser.print_help() 283 parser_read_value.add_argument('valuename', help='Name of the value to look up')
284 parser_read_value.add_argument('pkg', nargs='+', help='Runtime package name to look up')
285 parser_read_value.set_defaults(func=read_value)
286
287 parser_glob = subparsers.add_parser('glob',
288 help='Expand package name glob expression',
289 description='Expands one or more glob expressions over the packages listed in pkglistfile')
290 parser_glob.add_argument('pkglistfile', help='File listing packages (one package name per line)')
291 parser_glob.add_argument('glob', nargs="+", help='Glob expression for package names, e.g. *-dev')
292 parser_glob.set_defaults(func=glob)
293
294
295 args = parser.parse_args()
296
297 if args.debug:
298 logger.setLevel(logging.DEBUG)
299
300 if not args.pkgdata_dir:
301 import scriptpath
302 bitbakepath = scriptpath.add_bitbake_lib_path()
303 if not bitbakepath:
304 logger.error("Unable to find bitbake by searching parent directory of this script or PATH")
305 sys.exit(1)
306 logger.debug('Found bitbake path: %s' % bitbakepath)
307 tinfoil = tinfoil_init()
308 args.pkgdata_dir = tinfoil.config_data.getVar('PKGDATA_DIR', True)
309 logger.debug('Value of PKGDATA_DIR is "%s"' % args.pkgdata_dir)
310 if not args.pkgdata_dir:
311 logger.error('Unable to determine pkgdata directory from PKGDATA_DIR')
312 sys.exit(1)
313
314 if not os.path.exists(args.pkgdata_dir):
315 logger.error('Unable to find pkgdata directory %s' % pkgdata_dir)
314 sys.exit(1) 316 sys.exit(1)
315 317
316 if args[0] == "glob": 318 ret = args.func(args)
317 glob(args[1:], parser.print_help, options.debug) 319
318 elif args[0] == "lookup-pkg": 320 return ret
319 lookup_pkg(args[1:], parser.print_help, options.debug)
320 elif args[0] == "lookup-recipe":
321 lookup_recipe(args[1:], parser.print_help, options.debug)
322 elif args[0] == "find-path":
323 find_path(args[1:], parser.print_help, options.debug)
324 elif args[0] == "read-value":
325 read_value(args[1:], parser.print_help, options.debug)
326 else:
327 parser.print_help()
328 sys.exit(1)
329 321
330 322
331if __name__ == "__main__": 323if __name__ == "__main__":