1# Development tool - search command plugin 2# 3# Copyright (C) 2015 Intel Corporation 4# 5# SPDX-License-Identifier: GPL-2.0-only 6# 7 8"""Devtool search plugin""" 9 10import os 11import bb 12import logging 13import argparse 14import re 15from devtool import setup_tinfoil, parse_recipe, DevtoolError 16 17logger = logging.getLogger('devtool') 18 19def search(args, config, basepath, workspace): 20 """Entry point for the devtool 'search' subcommand""" 21 22 tinfoil = setup_tinfoil(config_only=False, basepath=basepath) 23 try: 24 pkgdata_dir = tinfoil.config_data.getVar('PKGDATA_DIR') 25 defsummary = tinfoil.config_data.getVar('SUMMARY', False) or '' 26 27 keyword_rc = re.compile(args.keyword) 28 29 def print_match(pn): 30 rd = parse_recipe(config, tinfoil, pn, True) 31 if not rd: 32 return 33 summary = rd.getVar('SUMMARY') 34 if summary == rd.expand(defsummary): 35 summary = '' 36 print("%s %s" % (pn.ljust(20), summary)) 37 38 39 matches = [] 40 if os.path.exists(pkgdata_dir): 41 for fn in os.listdir(pkgdata_dir): 42 pfn = os.path.join(pkgdata_dir, fn) 43 if not os.path.isfile(pfn): 44 continue 45 46 packages = [] 47 match = False 48 if keyword_rc.search(fn): 49 match = True 50 51 if not match: 52 with open(pfn, 'r') as f: 53 for line in f: 54 if line.startswith('PACKAGES:'): 55 packages = line.split(':', 1)[1].strip().split() 56 57 for pkg in packages: 58 if keyword_rc.search(pkg): 59 match = True 60 break 61 if os.path.exists(os.path.join(pkgdata_dir, 'runtime', pkg + '.packaged')): 62 with open(os.path.join(pkgdata_dir, 'runtime', pkg), 'r') as f: 63 for line in f: 64 if ': ' in line: 65 splitline = line.split(': ', 1) 66 key = splitline[0] 67 value = splitline[1].strip() 68 key = key.replace(":" + pkg, "") 69 if key in ['PKG', 'DESCRIPTION', 'FILES_INFO', 'FILERPROVIDES']: 70 if keyword_rc.search(value): 71 match = True 72 break 73 if match: 74 print_match(fn) 75 matches.append(fn) 76 else: 77 logger.warning('Package data is not available, results may be limited') 78 79 for recipe in tinfoil.all_recipes(): 80 if args.fixed_setup and 'nativesdk' in recipe.inherits(): 81 continue 82 83 match = False 84 if keyword_rc.search(recipe.pn): 85 match = True 86 else: 87 for prov in recipe.provides: 88 if keyword_rc.search(prov): 89 match = True 90 break 91 if not match: 92 for rprov in recipe.rprovides: 93 if keyword_rc.search(rprov): 94 match = True 95 break 96 if match and not recipe.pn in matches: 97 print_match(recipe.pn) 98 finally: 99 tinfoil.shutdown() 100 101 return 0 102 103def register_commands(subparsers, context): 104 """Register devtool subcommands from this plugin""" 105 parser_search = subparsers.add_parser('search', help='Search available recipes', 106 description='Searches for available recipes. Matches on recipe name, package name, description and installed files, and prints the recipe name and summary on match.', 107 group='info') 108 parser_search.add_argument('keyword', help='Keyword to search for (regular expression syntax allowed, use quotes to avoid shell expansion)') 109 parser_search.set_defaults(func=search, no_workspace=True, fixed_setup=context.fixed_setup) 110