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