#!/usr/bin/env python

# This script has subcommands which operate against your bitbake layers, either
# displaying useful information, or acting against them.
# See the help output for details on available commands.

# Copyright (C) 2011 Mentor Graphics Corporation
# Copyright (C) 2011-2015 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import logging
import os
import sys
import fnmatch
from collections import defaultdict
import argparse
import re
import httplib, urlparse, json
import subprocess

bindir = os.path.dirname(__file__)
topdir = os.path.dirname(bindir)
sys.path[0:0] = [os.path.join(topdir, 'lib')]

import bb.cache
import bb.cooker
import bb.providers
import bb.utils
import bb.tinfoil


def logger_create(name, output=sys.stderr):
    logger = logging.getLogger(name)
    console = logging.StreamHandler(output)
    format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
    if output.isatty():
        format.enable_color()
    console.setFormatter(format)
    logger.addHandler(console)
    logger.setLevel(logging.INFO)
    return logger

logger = logger_create('bitbake-layers', sys.stdout)

class UserError(Exception):
    pass

class Commands():
    def __init__(self):
        self.bbhandler = None
        self.bblayers = []

    def init_bbhandler(self, config_only = False):
        if not self.bbhandler:
            self.bbhandler = bb.tinfoil.Tinfoil(tracking=True)
            self.bblayers = (self.bbhandler.config_data.getVar('BBLAYERS', True) or "").split()
            self.bbhandler.prepare(config_only)
            layerconfs = self.bbhandler.config_data.varhistory.get_variable_items_files('BBFILE_COLLECTIONS', self.bbhandler.config_data)
            self.bbfile_collections = {layer: os.path.dirname(os.path.dirname(path)) for layer, path in layerconfs.iteritems()}


    def do_show_layers(self, args):
        """show current configured layers"""
        self.init_bbhandler(config_only = True)
        logger.plain("%s  %s  %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
        logger.plain('=' * 74)
        for layer, _, regex, pri in self.bbhandler.cooker.recipecache.bbfile_config_priorities:
            layerdir = self.bbfile_collections.get(layer, None)
            layername = self.get_layer_name(layerdir)
            logger.plain("%s  %s  %d" % (layername.ljust(20), layerdir.ljust(40), pri))


    def do_add_layer(self, args):
        """Add a layer to bblayers.conf

Adds the specified layer to bblayers.conf
"""
        layerdir = os.path.abspath(args.layerdir)
        if not os.path.exists(layerdir):
            sys.stderr.write("Specified layer directory doesn't exist\n")
            return 1

        layer_conf = os.path.join(layerdir, 'conf', 'layer.conf')
        if not os.path.exists(layer_conf):
            sys.stderr.write("Specified layer directory doesn't contain a conf/layer.conf file\n")
            return 1

        bblayers_conf = os.path.join('conf', 'bblayers.conf')
        if not os.path.exists(bblayers_conf):
            sys.stderr.write("Unable to find bblayers.conf\n")
            return 1

        (notadded, _) = bb.utils.edit_bblayers_conf(bblayers_conf, layerdir, None)
        if notadded:
            for item in notadded:
                sys.stderr.write("Specified layer %s is already in BBLAYERS\n" % item)


    def do_remove_layer(self, args):
        """Remove a layer from bblayers.conf

Removes the specified layer from bblayers.conf
"""
        bblayers_conf = os.path.join('conf', 'bblayers.conf')
        if not os.path.exists(bblayers_conf):
            sys.stderr.write("Unable to find bblayers.conf\n")
            return 1

        if args.layerdir.startswith('*'):
            layerdir = args.layerdir
        elif not '/' in args.layerdir:
            layerdir = '*/%s' % args.layerdir
        else:
            layerdir = os.path.abspath(args.layerdir)
        (_, notremoved) = bb.utils.edit_bblayers_conf(bblayers_conf, None, layerdir)
        if notremoved:
            for item in notremoved:
                sys.stderr.write("No layers matching %s found in BBLAYERS\n" % item)
            return 1


    def get_json_data(self, apiurl):
        proxy_settings = os.environ.get("http_proxy", None)
        conn = None
        _parsedurl = urlparse.urlparse(apiurl)
        path = _parsedurl.path
        query = _parsedurl.query
        def parse_url(url):
            parsedurl = urlparse.urlparse(url)
            if parsedurl.netloc[0] == '[':
                host, port = parsedurl.netloc[1:].split(']', 1)
                if ':' in port:
                    port = port.rsplit(':', 1)[1]
                else:
                    port = None
            else:
                if parsedurl.netloc.count(':') == 1:
                    (host, port) = parsedurl.netloc.split(":")
                else:
                    host = parsedurl.netloc
                    port = None
            return (host, 80 if port is None else int(port))

        if proxy_settings is None:
            host, port = parse_url(apiurl)
            conn = httplib.HTTPConnection(host, port)
            conn.request("GET", path + "?" + query)
        else:
            host, port = parse_url(proxy_settings)
            conn = httplib.HTTPConnection(host, port)
            conn.request("GET", apiurl)

        r = conn.getresponse()
        if r.status != 200:
            raise Exception("Failed to read " + path + ": %d %s" % (r.status, r.reason))
        return json.loads(r.read())


    def get_layer_deps(self, layername, layeritems, layerbranches, layerdependencies, branchnum, selfname=False):
        def layeritems_info_id(items_name, layeritems):
            litems_id = None
            for li in layeritems:
                if li['name'] == items_name:
                    litems_id = li['id']
                    break
            return litems_id

        def layerbranches_info(items_id, layerbranches):
            lbranch = {}
            for lb in layerbranches:
                if lb['layer'] == items_id and lb['branch'] == branchnum:
                    lbranch['id'] = lb['id']
                    lbranch['vcs_subdir'] = lb['vcs_subdir']
                    break
            return lbranch

        def layerdependencies_info(lb_id, layerdependencies):
            ld_deps = []
            for ld in layerdependencies:
                if ld['layerbranch'] == lb_id and not ld['dependency'] in ld_deps:
                    ld_deps.append(ld['dependency'])
            if not ld_deps:
                logger.error("The dependency of layerDependencies is not found.")
            return ld_deps

        def layeritems_info_name_subdir(items_id, layeritems):
            litems = {}
            for li in layeritems:
                if li['id'] == items_id:
                    litems['vcs_url'] = li['vcs_url']
                    litems['name'] = li['name']
                    break
            return litems

        if selfname:
            selfid = layeritems_info_id(layername, layeritems)
            lbinfo = layerbranches_info(selfid, layerbranches)
            if lbinfo:
                selfsubdir = lbinfo['vcs_subdir']
            else:
                logger.error("%s is not found in the specified branch" % layername)
                return
            selfurl = layeritems_info_name_subdir(selfid, layeritems)['vcs_url']
            if selfurl:
                return selfurl, selfsubdir
            else:
                logger.error("Cannot get layer %s git repo and subdir" % layername)
                return
        ldict = {}
        itemsid = layeritems_info_id(layername, layeritems)
        if not itemsid:
            return layername, None
        lbid = layerbranches_info(itemsid, layerbranches)
        if lbid:
            lbid = layerbranches_info(itemsid, layerbranches)['id']
        else:
            logger.error("%s is not found in the specified branch" % layername)
            return None, None
        for dependency in layerdependencies_info(lbid, layerdependencies):
            lname = layeritems_info_name_subdir(dependency, layeritems)['name']
            lurl = layeritems_info_name_subdir(dependency, layeritems)['vcs_url']
            lsubdir = layerbranches_info(dependency, layerbranches)['vcs_subdir']
            ldict[lname] = lurl, lsubdir
        return None, ldict


    def get_fetch_layer(self, fetchdir, url, subdir, fetch_layer):
        layername = self.get_layer_name(url)
        if os.path.splitext(layername)[1] == '.git':
            layername = os.path.splitext(layername)[0]
        repodir = os.path.join(fetchdir, layername)
        layerdir = os.path.join(repodir, subdir)
        if not os.path.exists(repodir):
            if fetch_layer:
                result = subprocess.call('git clone %s %s' % (url, repodir), shell = True)
                if result:
                    logger.error("Failed to download %s" % url)
                    return None, None
                else:
                    return layername, layerdir
            else:
                logger.plain("Repository %s needs to be fetched" % url)
                return layername, layerdir
        elif os.path.exists(layerdir):
            return layername, layerdir
        else:
            logger.error("%s is not in %s" % (url, subdir))
        return None, None


    def do_layerindex_fetch(self, args):
        """Fetches a layer from a layer index along with its dependent layers, and adds them to conf/bblayers.conf.
"""
        self.init_bbhandler(config_only = True)
        apiurl = self.bbhandler.config_data.getVar('BBLAYERS_LAYERINDEX_URL', True)
        if not apiurl:
            logger.error("Cannot get BBLAYERS_LAYERINDEX_URL")
            return 1
        else:
            if apiurl[-1] != '/':
                apiurl += '/'
            apiurl += "api/"
        apilinks = self.get_json_data(apiurl)
        branches = self.get_json_data(apilinks['branches'])

        branchnum = 0
        for branch in branches:
            if branch['name'] == args.branch:
                branchnum = branch['id']
                break
        if branchnum == 0:
            validbranches = ', '.join([branch['name'] for branch in branches])
            logger.error('Invalid layer branch name "%s". Valid branches: %s' % (args.branch, validbranches))
            return 1

        ignore_layers = []
        for collection in self.bbhandler.config_data.getVar('BBFILE_COLLECTIONS', True).split():
            lname = self.bbhandler.config_data.getVar('BBLAYERS_LAYERINDEX_NAME_%s' % collection, True)
            if lname:
                ignore_layers.append(lname)

        if args.ignore:
            ignore_layers.extend(args.ignore.split(','))

        layeritems = self.get_json_data(apilinks['layerItems'])
        layerbranches = self.get_json_data(apilinks['layerBranches'])
        layerdependencies = self.get_json_data(apilinks['layerDependencies'])
        invaluenames = []
        repourls = {}
        printlayers = []
        def query_dependencies(layers, layeritems, layerbranches, layerdependencies, branchnum):
            depslayer = []
            for layername in layers:
                invaluename, layerdict = self.get_layer_deps(layername, layeritems, layerbranches, layerdependencies, branchnum)
                if layerdict:
                    repourls[layername] = self.get_layer_deps(layername, layeritems, layerbranches, layerdependencies, branchnum, selfname=True)
                    for layer in layerdict:
                        if not layer in ignore_layers:
                            depslayer.append(layer)
                        printlayers.append((layername, layer, layerdict[layer][0], layerdict[layer][1]))
                        if not layer in ignore_layers and not layer in repourls:
                            repourls[layer] = (layerdict[layer][0], layerdict[layer][1])
                if invaluename and not invaluename in invaluenames:
                    invaluenames.append(invaluename)
            return depslayer

        depslayers = query_dependencies(args.layername, layeritems, layerbranches, layerdependencies, branchnum)
        while depslayers:
            depslayer = query_dependencies(depslayers, layeritems, layerbranches, layerdependencies, branchnum)
            depslayers = depslayer
        if invaluenames:
            for invaluename in invaluenames:
                logger.error('Layer "%s" not found in layer index' % invaluename)
            return 1
        logger.plain("%s  %s  %s  %s" % ("Layer".ljust(19), "Required by".ljust(19), "Git repository".ljust(54), "Subdirectory"))
        logger.plain('=' * 115)
        for layername in args.layername:
            layerurl = repourls[layername]
            logger.plain("%s %s %s %s" % (layername.ljust(20), '-'.ljust(20), layerurl[0].ljust(55), layerurl[1]))
        printedlayers = []
        for layer, dependency, gitrepo, subdirectory in printlayers:
            if dependency in printedlayers:
                continue
            logger.plain("%s %s %s %s" % (dependency.ljust(20), layer.ljust(20), gitrepo.ljust(55), subdirectory))
            printedlayers.append(dependency)

        if repourls:
            fetchdir = self.bbhandler.config_data.getVar('BBLAYERS_FETCH_DIR', True)
            if not fetchdir:
                logger.error("Cannot get BBLAYERS_FETCH_DIR")
                return 1
            if not os.path.exists(fetchdir):
                os.makedirs(fetchdir)
            addlayers = []
            for repourl, subdir in repourls.values():
                name, layerdir = self.get_fetch_layer(fetchdir, repourl, subdir, not args.show_only)
                if not name:
                    # Error already shown
                    return 1
                addlayers.append((subdir, name, layerdir))
        if not args.show_only:
            for subdir, name, layerdir in set(addlayers):
                if os.path.exists(layerdir):
                    if subdir:
                        logger.plain("Adding layer \"%s\" to conf/bblayers.conf" % subdir)
                    else:
                        logger.plain("Adding layer \"%s\" to conf/bblayers.conf" % name)
                    localargs = argparse.Namespace()
                    localargs.layerdir = layerdir
                    self.do_add_layer(localargs)
                else:
                    break


    def do_layerindex_show_depends(self, args):
        """Find layer dependencies from layer index.
"""
        args.show_only = True
        args.ignore = []
        self.do_layerindex_fetch(args)


    def version_str(self, pe, pv, pr = None):
        verstr = "%s" % pv
        if pr:
            verstr = "%s-%s" % (verstr, pr)
        if pe:
            verstr = "%s:%s" % (pe, verstr)
        return verstr


    def do_show_overlayed(self, args):
        """list overlayed recipes (where the same recipe exists in another layer)

Lists the names of overlayed recipes and the available versions in each
layer, with the preferred version first. Note that skipped recipes that
are overlayed will also be listed, with a " (skipped)" suffix.
"""
        self.init_bbhandler()

        items_listed = self.list_recipes('Overlayed recipes', None, True, args.same_version, args.filenames, True, None)

        # Check for overlayed .bbclass files
        classes = defaultdict(list)
        for layerdir in self.bblayers:
            classdir = os.path.join(layerdir, 'classes')
            if os.path.exists(classdir):
                for classfile in os.listdir(classdir):
                    if os.path.splitext(classfile)[1] == '.bbclass':
                        classes[classfile].append(classdir)

        # Locating classes and other files is a bit more complicated than recipes -
        # layer priority is not a factor; instead BitBake uses the first matching
        # file in BBPATH, which is manipulated directly by each layer's
        # conf/layer.conf in turn, thus the order of layers in bblayers.conf is a
        # factor - however, each layer.conf is free to either prepend or append to
        # BBPATH (or indeed do crazy stuff with it). Thus the order in BBPATH might
        # not be exactly the order present in bblayers.conf either.
        bbpath = str(self.bbhandler.config_data.getVar('BBPATH', True))
        overlayed_class_found = False
        for (classfile, classdirs) in classes.items():
            if len(classdirs) > 1:
                if not overlayed_class_found:
                    logger.plain('=== Overlayed classes ===')
                    overlayed_class_found = True

                mainfile = bb.utils.which(bbpath, os.path.join('classes', classfile))
                if args.filenames:
                    logger.plain('%s' % mainfile)
                else:
                    # We effectively have to guess the layer here
                    logger.plain('%s:' % classfile)
                    mainlayername = '?'
                    for layerdir in self.bblayers:
                        classdir = os.path.join(layerdir, 'classes')
                        if mainfile.startswith(classdir):
                            mainlayername = self.get_layer_name(layerdir)
                    logger.plain('  %s' % mainlayername)
                for classdir in classdirs:
                    fullpath = os.path.join(classdir, classfile)
                    if fullpath != mainfile:
                        if args.filenames:
                            print('  %s' % fullpath)
                        else:
                            print('  %s' % self.get_layer_name(os.path.dirname(classdir)))

        if overlayed_class_found:
            items_listed = True;

        if not items_listed:
            logger.plain('No overlayed files found.')


    def do_show_recipes(self, args):
        """list available recipes, showing the layer they are provided by

Lists the names of recipes and the available versions in each
layer, with the preferred version first. Optionally you may specify
pnspec to match a specified recipe name (supports wildcards). Note that
skipped recipes will also be listed, with a " (skipped)" suffix.
"""
        self.init_bbhandler()

        inheritlist = args.inherits.split(',') if args.inherits else []
        if inheritlist or args.pnspec or args.multiple:
            title = 'Matching recipes:'
        else:
            title = 'Available recipes:'
        self.list_recipes(title, args.pnspec, False, False, args.filenames, args.multiple, inheritlist)


    def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only, inherits):
        if inherits:
            bbpath = str(self.bbhandler.config_data.getVar('BBPATH', True))
            for classname in inherits:
                classfile = 'classes/%s.bbclass' % classname
                if not bb.utils.which(bbpath, classfile, history=False):
                    raise UserError('No class named %s found in BBPATH' % classfile)

        pkg_pn = self.bbhandler.cooker.recipecache.pkg_pn
        (latest_versions, preferred_versions) = bb.providers.findProviders(self.bbhandler.config_data, self.bbhandler.cooker.recipecache, pkg_pn)
        allproviders = bb.providers.allProviders(self.bbhandler.cooker.recipecache)

        # Ensure we list skipped recipes
        # We are largely guessing about PN, PV and the preferred version here,
        # but we have no choice since skipped recipes are not fully parsed
        skiplist = self.bbhandler.cooker.skiplist.keys()
        skiplist.sort( key=lambda fileitem: self.bbhandler.cooker.collection.calc_bbfile_priority(fileitem) )
        skiplist.reverse()
        for fn in skiplist:
            recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
            p = recipe_parts[0]
            if len(recipe_parts) > 1:
                ver = (None, recipe_parts[1], None)
            else:
                ver = (None, 'unknown', None)
            allproviders[p].append((ver, fn))
            if not p in pkg_pn:
                pkg_pn[p] = 'dummy'
                preferred_versions[p] = (ver, fn)

        def print_item(f, pn, ver, layer, ispref):
            if f in skiplist:
                skipped = ' (skipped)'
            else:
                skipped = ''
            if show_filenames:
                if ispref:
                    logger.plain("%s%s", f, skipped)
                else:
                    logger.plain("  %s%s", f, skipped)
            else:
                if ispref:
                    logger.plain("%s:", pn)
                logger.plain("  %s %s%s", layer.ljust(20), ver, skipped)

        global_inherit = (self.bbhandler.config_data.getVar('INHERIT', True) or "").split()
        cls_re = re.compile('classes/')

        preffiles = []
        items_listed = False
        for p in sorted(pkg_pn):
            if pnspec:
                if not fnmatch.fnmatch(p, pnspec):
                    continue

            if len(allproviders[p]) > 1 or not show_multi_provider_only:
                pref = preferred_versions[p]
                realfn = bb.cache.Cache.virtualfn2realfn(pref[1])
                preffile = realfn[0]

                # We only display once per recipe, we should prefer non extended versions of the
                # recipe if present (so e.g. in OpenEmbedded, openssl rather than nativesdk-openssl
                # which would otherwise sort first).
                if realfn[1] and realfn[0] in self.bbhandler.cooker.recipecache.pkg_fn:
                    continue

                if inherits:
                    matchcount = 0
                    recipe_inherits = self.bbhandler.cooker_data.inherits.get(preffile, [])
                    for cls in recipe_inherits:
                        if cls_re.match(cls):
                            continue
                        classname = os.path.splitext(os.path.basename(cls))[0]
                        if classname in global_inherit:
                            continue
                        elif classname in inherits:
                            matchcount += 1
                    if matchcount != len(inherits):
                        # No match - skip this recipe
                        continue

                if preffile not in preffiles:
                    preflayer = self.get_file_layer(preffile)
                    multilayer = False
                    same_ver = True
                    provs = []
                    for prov in allproviders[p]:
                        provfile = bb.cache.Cache.virtualfn2realfn(prov[1])[0]
                        provlayer = self.get_file_layer(provfile)
                        provs.append((provfile, provlayer, prov[0]))
                        if provlayer != preflayer:
                            multilayer = True
                        if prov[0] != pref[0]:
                            same_ver = False

                    if (multilayer or not show_overlayed_only) and (same_ver or not show_same_ver_only):
                        if not items_listed:
                            logger.plain('=== %s ===' % title)
                            items_listed = True
                        print_item(preffile, p, self.version_str(pref[0][0], pref[0][1]), preflayer, True)
                        for (provfile, provlayer, provver) in provs:
                            if provfile != preffile:
                                print_item(provfile, p, self.version_str(provver[0], provver[1]), provlayer, False)
                        # Ensure we don't show two entries for BBCLASSEXTENDed recipes
                        preffiles.append(preffile)

        return items_listed


    def do_flatten(self, args):
        """flatten layer configuration into a separate output directory.

Takes the specified layers (or all layers in the current layer
configuration if none are specified) and builds a "flattened" directory
containing the contents of all layers, with any overlayed recipes removed
and bbappends appended to the corresponding recipes. Note that some manual
cleanup may still be necessary afterwards, in particular:

* where non-recipe files (such as patches) are overwritten (the flatten
  command will show a warning for these)
* where anything beyond the normal layer setup has been added to
  layer.conf (only the lowest priority number layer's layer.conf is used)
* overridden/appended items from bbappends will need to be tidied up
* when the flattened layers do not have the same directory structure (the
  flatten command should show a warning when this will cause a problem)

Warning: if you flatten several layers where another layer is intended to
be used "inbetween" them (in layer priority order) such that recipes /
bbappends in the layers interact, and then attempt to use the new output
layer together with that other layer, you may no longer get the same
build results (as the layer priority order has effectively changed).
"""
        if len(args.layer) == 1:
            logger.error('If you specify layers to flatten you must specify at least two')
            return 1

        outputdir = args.outputdir
        if os.path.exists(outputdir) and os.listdir(outputdir):
            logger.error('Directory %s exists and is non-empty, please clear it out first' % outputdir)
            return 1

        self.init_bbhandler()
        layers = self.bblayers
        if len(args.layer) > 2:
            layernames = args.layer
            found_layernames = []
            found_layerdirs = []
            for layerdir in layers:
                layername = self.get_layer_name(layerdir)
                if layername in layernames:
                    found_layerdirs.append(layerdir)
                    found_layernames.append(layername)

            for layername in layernames:
                if not layername in found_layernames:
                    logger.error('Unable to find layer %s in current configuration, please run "%s show-layers" to list configured layers' % (layername, os.path.basename(sys.argv[0])))
                    return
            layers = found_layerdirs
        else:
            layernames = []

        # Ensure a specified path matches our list of layers
        def layer_path_match(path):
            for layerdir in layers:
                if path.startswith(os.path.join(layerdir, '')):
                    return layerdir
            return None

        applied_appends = []
        for layer in layers:
            overlayed = []
            for f in self.bbhandler.cooker.collection.overlayed.iterkeys():
                for of in self.bbhandler.cooker.collection.overlayed[f]:
                    if of.startswith(layer):
                        overlayed.append(of)

            logger.plain('Copying files from %s...' % layer )
            for root, dirs, files in os.walk(layer):
                for f1 in files:
                    f1full = os.sep.join([root, f1])
                    if f1full in overlayed:
                        logger.plain('  Skipping overlayed file %s' % f1full )
                    else:
                        ext = os.path.splitext(f1)[1]
                        if ext != '.bbappend':
                            fdest = f1full[len(layer):]
                            fdest = os.path.normpath(os.sep.join([outputdir,fdest]))
                            bb.utils.mkdirhier(os.path.dirname(fdest))
                            if os.path.exists(fdest):
                                if f1 == 'layer.conf' and root.endswith('/conf'):
                                    logger.plain('  Skipping layer config file %s' % f1full )
                                    continue
                                else:
                                    logger.warn('Overwriting file %s', fdest)
                            bb.utils.copyfile(f1full, fdest)
                            if ext == '.bb':
                                for append in self.bbhandler.cooker.collection.get_file_appends(f1full):
                                    if layer_path_match(append):
                                        logger.plain('  Applying append %s to %s' % (append, fdest))
                                        self.apply_append(append, fdest)
                                        applied_appends.append(append)

        # Take care of when some layers are excluded and yet we have included bbappends for those recipes
        for b in self.bbhandler.cooker.collection.bbappends:
            (recipename, appendname) = b
            if appendname not in applied_appends:
                first_append = None
                layer = layer_path_match(appendname)
                if layer:
                    if first_append:
                        self.apply_append(appendname, first_append)
                    else:
                        fdest = appendname[len(layer):]
                        fdest = os.path.normpath(os.sep.join([outputdir,fdest]))
                        bb.utils.mkdirhier(os.path.dirname(fdest))
                        bb.utils.copyfile(appendname, fdest)
                        first_append = fdest

        # Get the regex for the first layer in our list (which is where the conf/layer.conf file will
        # have come from)
        first_regex = None
        layerdir = layers[0]
        for layername, pattern, regex, _ in self.bbhandler.cooker.recipecache.bbfile_config_priorities:
            if regex.match(os.path.join(layerdir, 'test')):
                first_regex = regex
                break

        if first_regex:
            # Find the BBFILES entries that match (which will have come from this conf/layer.conf file)
            bbfiles = str(self.bbhandler.config_data.getVar('BBFILES', True)).split()
            bbfiles_layer = []
            for item in bbfiles:
                if first_regex.match(item):
                    newpath = os.path.join(outputdir, item[len(layerdir)+1:])
                    bbfiles_layer.append(newpath)

            if bbfiles_layer:
                # Check that all important layer files match BBFILES
                for root, dirs, files in os.walk(outputdir):
                    for f1 in files:
                        ext = os.path.splitext(f1)[1]
                        if ext in ['.bb', '.bbappend']:
                            f1full = os.sep.join([root, f1])
                            entry_found = False
                            for item in bbfiles_layer:
                                if fnmatch.fnmatch(f1full, item):
                                    entry_found = True
                                    break
                            if not entry_found:
                                logger.warning("File %s does not match the flattened layer's BBFILES setting, you may need to edit conf/layer.conf or move the file elsewhere" % f1full)

    def get_file_layer(self, filename):
        layerdir = self.get_file_layerdir(filename)
        if layerdir:
            return self.get_layer_name(layerdir)
        else:
            return '?'

    def get_file_layerdir(self, filename):
        layer = bb.utils.get_file_layer(filename, self.bbhandler.config_data)
        return self.bbfile_collections.get(layer, None)

    def remove_layer_prefix(self, f):
        """Remove the layer_dir prefix, e.g., f = /path/to/layer_dir/foo/blah, the
           return value will be: layer_dir/foo/blah"""
        f_layerdir = self.get_file_layerdir(f)
        if not f_layerdir:
            return f
        prefix = os.path.join(os.path.dirname(f_layerdir), '')
        return f[len(prefix):] if f.startswith(prefix) else f

    def get_layer_name(self, layerdir):
        return os.path.basename(layerdir.rstrip(os.sep))

    def apply_append(self, appendname, recipename):
        with open(appendname, 'r') as appendfile:
            with open(recipename, 'a') as recipefile:
                recipefile.write('\n')
                recipefile.write('##### bbappended from %s #####\n' % self.get_file_layer(appendname))
                recipefile.writelines(appendfile.readlines())

    def do_show_appends(self, args):
        """list bbappend files and recipe files they apply to

Lists recipes with the bbappends that apply to them as subitems.
"""
        self.init_bbhandler()

        logger.plain('=== Appended recipes ===')

        pnlist = list(self.bbhandler.cooker_data.pkg_pn.keys())
        pnlist.sort()
        appends = False
        for pn in pnlist:
            if self.show_appends_for_pn(pn):
                appends = True

        if self.show_appends_for_skipped():
            appends = True

        if not appends:
            logger.plain('No append files found')

    def show_appends_for_pn(self, pn):
        filenames = self.bbhandler.cooker_data.pkg_pn[pn]

        best = bb.providers.findBestProvider(pn,
                                             self.bbhandler.config_data,
                                             self.bbhandler.cooker_data,
                                             self.bbhandler.cooker_data.pkg_pn)
        best_filename = os.path.basename(best[3])

        return self.show_appends_output(filenames, best_filename)

    def show_appends_for_skipped(self):
        filenames = [os.path.basename(f)
                    for f in self.bbhandler.cooker.skiplist.iterkeys()]
        return self.show_appends_output(filenames, None, " (skipped)")

    def show_appends_output(self, filenames, best_filename, name_suffix = ''):
        appended, missing = self.get_appends_for_files(filenames)
        if appended:
            for basename, appends in appended:
                logger.plain('%s%s:', basename, name_suffix)
                for append in appends:
                    logger.plain('  %s', append)

            if best_filename:
                if best_filename in missing:
                    logger.warn('%s: missing append for preferred version',
                                best_filename)
            return True
        else:
            return False

    def get_appends_for_files(self, filenames):
        appended, notappended = [], []
        for filename in filenames:
            _, cls = bb.cache.Cache.virtualfn2realfn(filename)
            if cls:
                continue

            basename = os.path.basename(filename)
            appends = self.bbhandler.cooker.collection.get_file_appends(basename)
            if appends:
                appended.append((basename, list(appends)))
            else:
                notappended.append(basename)
        return appended, notappended

    def do_show_cross_depends(self, args):
        """Show dependencies between recipes that cross layer boundaries.

Figure out the dependencies between recipes that cross layer boundaries.

NOTE: .bbappend files can impact the dependencies.
"""
        ignore_layers = (args.ignore or '').split(',')

        self.init_bbhandler()

        pkg_fn = self.bbhandler.cooker_data.pkg_fn
        bbpath = str(self.bbhandler.config_data.getVar('BBPATH', True))
        self.require_re = re.compile(r"require\s+(.+)")
        self.include_re = re.compile(r"include\s+(.+)")
        self.inherit_re = re.compile(r"inherit\s+(.+)")

        global_inherit = (self.bbhandler.config_data.getVar('INHERIT', True) or "").split()

        # The bb's DEPENDS and RDEPENDS
        for f in pkg_fn:
            f = bb.cache.Cache.virtualfn2realfn(f)[0]
            # Get the layername that the file is in
            layername = self.get_file_layer(f)

            # The DEPENDS
            deps = self.bbhandler.cooker_data.deps[f]
            for pn in deps:
                if pn in self.bbhandler.cooker_data.pkg_pn:
                    best = bb.providers.findBestProvider(pn,
                            self.bbhandler.config_data,
                            self.bbhandler.cooker_data,
                            self.bbhandler.cooker_data.pkg_pn)
                    self.check_cross_depends("DEPENDS", layername, f, best[3], args.filenames, ignore_layers)

            # The RDPENDS
            all_rdeps = self.bbhandler.cooker_data.rundeps[f].values()
            # Remove the duplicated or null one.
            sorted_rdeps = {}
            # The all_rdeps is the list in list, so we need two for loops
            for k1 in all_rdeps:
                for k2 in k1:
                    sorted_rdeps[k2] = 1
            all_rdeps = sorted_rdeps.keys()
            for rdep in all_rdeps:
                all_p = bb.providers.getRuntimeProviders(self.bbhandler.cooker_data, rdep)
                if all_p:
                    if f in all_p:
                        # The recipe provides this one itself, ignore
                        continue
                    best = bb.providers.filterProvidersRunTime(all_p, rdep,
                                    self.bbhandler.config_data,
                                    self.bbhandler.cooker_data)[0][0]
                    self.check_cross_depends("RDEPENDS", layername, f, best, args.filenames, ignore_layers)

            # The RRECOMMENDS
            all_rrecs = self.bbhandler.cooker_data.runrecs[f].values()
            # Remove the duplicated or null one.
            sorted_rrecs = {}
            # The all_rrecs is the list in list, so we need two for loops
            for k1 in all_rrecs:
                for k2 in k1:
                    sorted_rrecs[k2] = 1
            all_rrecs = sorted_rrecs.keys()
            for rrec in all_rrecs:
                all_p = bb.providers.getRuntimeProviders(self.bbhandler.cooker_data, rrec)
                if all_p:
                    if f in all_p:
                        # The recipe provides this one itself, ignore
                        continue
                    best = bb.providers.filterProvidersRunTime(all_p, rrec,
                                    self.bbhandler.config_data,
                                    self.bbhandler.cooker_data)[0][0]
                    self.check_cross_depends("RRECOMMENDS", layername, f, best, args.filenames, ignore_layers)

            # The inherit class
            cls_re = re.compile('classes/')
            if f in self.bbhandler.cooker_data.inherits:
                inherits = self.bbhandler.cooker_data.inherits[f]
                for cls in inherits:
                    # The inherits' format is [classes/cls, /path/to/classes/cls]
                    # ignore the classes/cls.
                    if not cls_re.match(cls):
                        classname = os.path.splitext(os.path.basename(cls))[0]
                        if classname in global_inherit:
                            continue
                        inherit_layername = self.get_file_layer(cls)
                        if inherit_layername != layername and not inherit_layername in ignore_layers:
                            if not args.filenames:
                                f_short = self.remove_layer_prefix(f)
                                cls = self.remove_layer_prefix(cls)
                            else:
                                f_short = f
                            logger.plain("%s inherits %s" % (f_short, cls))

            # The 'require/include xxx' in the bb file
            pv_re = re.compile(r"\${PV}")
            with open(f, 'r') as fnfile:
                line = fnfile.readline()
                while line:
                    m, keyword = self.match_require_include(line)
                    # Found the 'require/include xxxx'
                    if m:
                        needed_file = m.group(1)
                        # Replace the ${PV} with the real PV
                        if pv_re.search(needed_file) and f in self.bbhandler.cooker_data.pkg_pepvpr:
                            pv = self.bbhandler.cooker_data.pkg_pepvpr[f][1]
                            needed_file = re.sub(r"\${PV}", pv, needed_file)
                        self.print_cross_files(bbpath, keyword, layername, f, needed_file, args.filenames, ignore_layers)
                    line = fnfile.readline()

        # The "require/include xxx" in conf/machine/*.conf, .inc and .bbclass
        conf_re = re.compile(".*/conf/machine/[^\/]*\.conf$")
        inc_re = re.compile(".*\.inc$")
        # The "inherit xxx" in .bbclass
        bbclass_re = re.compile(".*\.bbclass$")
        for layerdir in self.bblayers:
            layername = self.get_layer_name(layerdir)
            for dirpath, dirnames, filenames in os.walk(layerdir):
                for name in filenames:
                    f = os.path.join(dirpath, name)
                    s = conf_re.match(f) or inc_re.match(f) or bbclass_re.match(f)
                    if s:
                        with open(f, 'r') as ffile:
                            line = ffile.readline()
                            while line:
                                m, keyword = self.match_require_include(line)
                                # Only bbclass has the "inherit xxx" here.
                                bbclass=""
                                if not m and f.endswith(".bbclass"):
                                    m, keyword = self.match_inherit(line)
                                    bbclass=".bbclass"
                                # Find a 'require/include xxxx'
                                if m:
                                    self.print_cross_files(bbpath, keyword, layername, f, m.group(1) + bbclass, args.filenames, ignore_layers)
                                line = ffile.readline()

    def print_cross_files(self, bbpath, keyword, layername, f, needed_filename, show_filenames, ignore_layers):
        """Print the depends that crosses a layer boundary"""
        needed_file = bb.utils.which(bbpath, needed_filename)
        if needed_file:
            # Which layer is this file from
            needed_layername = self.get_file_layer(needed_file)
            if needed_layername != layername and not needed_layername in ignore_layers:
                if not show_filenames:
                    f = self.remove_layer_prefix(f)
                    needed_file = self.remove_layer_prefix(needed_file)
                logger.plain("%s %s %s" %(f, keyword, needed_file))

    def match_inherit(self, line):
        """Match the inherit xxx line"""
        return (self.inherit_re.match(line), "inherits")

    def match_require_include(self, line):
        """Match the require/include xxx line"""
        m = self.require_re.match(line)
        keyword = "requires"
        if not m:
            m = self.include_re.match(line)
            keyword = "includes"
        return (m, keyword)

    def check_cross_depends(self, keyword, layername, f, needed_file, show_filenames, ignore_layers):
        """Print the DEPENDS/RDEPENDS file that crosses a layer boundary"""
        best_realfn = bb.cache.Cache.virtualfn2realfn(needed_file)[0]
        needed_layername = self.get_file_layer(best_realfn)
        if needed_layername != layername and not needed_layername in ignore_layers:
            if not show_filenames:
                f = self.remove_layer_prefix(f)
                best_realfn = self.remove_layer_prefix(best_realfn)

            logger.plain("%s %s %s" % (f, keyword, best_realfn))


def main():

    cmds = Commands()

    def add_command(cmdname, function, *args, **kwargs):
        # Convert docstring for function to help (one-liner shown in main --help) and description (shown in subcommand --help)
        docsplit = function.__doc__.splitlines()
        help = docsplit[0]
        if len(docsplit) > 1:
            desc = '\n'.join(docsplit[1:])
        else:
            desc = help
        subparser = subparsers.add_parser(cmdname, *args, help=help, description=desc, formatter_class=argparse.RawTextHelpFormatter, **kwargs)
        subparser.set_defaults(func=function)
        return subparser

    parser = argparse.ArgumentParser(description="BitBake layers utility",
                                     epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
    parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
    parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
    subparsers = parser.add_subparsers(title='subcommands', metavar='<subcommand>')

    parser_show_layers = add_command('show-layers', cmds.do_show_layers)

    parser_add_layer = add_command('add-layer', cmds.do_add_layer)
    parser_add_layer.add_argument('layerdir', help='Layer directory to add')

    parser_remove_layer = add_command('remove-layer', cmds.do_remove_layer)
    parser_remove_layer.add_argument('layerdir', help='Layer directory to remove (wildcards allowed, enclose in quotes to avoid shell expansion)')
    parser_remove_layer.set_defaults(func=cmds.do_remove_layer)

    parser_show_overlayed = add_command('show-overlayed', cmds.do_show_overlayed)
    parser_show_overlayed.add_argument('-f', '--filenames', help='instead of the default formatting, list filenames of higher priority recipes with the ones they overlay indented underneath', action='store_true')
    parser_show_overlayed.add_argument('-s', '--same-version', help='only list overlayed recipes where the version is the same', action='store_true')

    parser_show_recipes = add_command('show-recipes', cmds.do_show_recipes)
    parser_show_recipes.add_argument('-f', '--filenames', help='instead of the default formatting, list filenames of higher priority recipes with the ones they overlay indented underneath', action='store_true')
    parser_show_recipes.add_argument('-m', '--multiple', help='only list where multiple recipes (in the same layer or different layers) exist for the same recipe name', action='store_true')
    parser_show_recipes.add_argument('-i', '--inherits', help='only list recipes that inherit the named class', metavar='CLASS', default='')
    parser_show_recipes.add_argument('pnspec', nargs='?', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')

    parser_show_appends = add_command('show-appends', cmds.do_show_appends)

    parser_flatten = add_command('flatten', cmds.do_flatten)
    parser_flatten.add_argument('layer', nargs='*', help='Optional layer(s) to flatten (otherwise all are flattened)')
    parser_flatten.add_argument('outputdir', help='Output directory')

    parser_show_cross_depends = add_command('show-cross-depends', cmds.do_show_cross_depends)
    parser_show_cross_depends.add_argument('-f', '--filenames', help='show full file path', action='store_true')
    parser_show_cross_depends.add_argument('-i', '--ignore', help='ignore dependencies on items in the specified layer(s) (split multiple layer names with commas, no spaces)', metavar='LAYERNAME')

    parser_layerindex_fetch = add_command('layerindex-fetch', cmds.do_layerindex_fetch)
    parser_layerindex_fetch.add_argument('-n', '--show-only', help='show dependencies and do nothing else', action='store_true')
    parser_layerindex_fetch.add_argument('-b', '--branch', help='branch name to fetch (default %(default)s)', default='master')
    parser_layerindex_fetch.add_argument('-i', '--ignore', help='assume the specified layers do not need to be fetched/added (separate multiple layers with commas, no spaces)', metavar='LAYER')
    parser_layerindex_fetch.add_argument('layername', nargs='+', help='layer to fetch')

    parser_layerindex_show_depends = add_command('layerindex-show-depends', cmds.do_layerindex_show_depends)
    parser_layerindex_show_depends.add_argument('-b', '--branch', help='branch name to fetch (default %(default)s)', default='master')
    parser_layerindex_show_depends.add_argument('layername', nargs='+', help='layer to query')

    args = parser.parse_args()

    if args.debug:
        logger.setLevel(logging.DEBUG)
    elif args.quiet:
        logger.setLevel(logging.ERROR)

    try:
        ret = args.func(args)
    except UserError as err:
        logger.error(str(err))
        ret = 1

    return ret


if __name__ == "__main__":
    try:
        ret = main()
    except Exception:
        ret = 1
        import traceback
        traceback.print_exc()
    sys.exit(ret)
