Beispiel #1
0
def add(args, config, basepath, workspace):
    """Entry point for the devtool 'add' subcommand"""
    import bb
    import oe.recipeutils

    if args.recipename in workspace:
        raise DevtoolError("recipe %s is already in your workspace" %
                            args.recipename)

    reason = oe.recipeutils.validate_pn(args.recipename)
    if reason:
        raise DevtoolError(reason)

    srctree = os.path.abspath(args.srctree)
    if os.path.exists(srctree):
        if args.fetch:
            if not os.path.isdir(srctree):
                raise DevtoolError("Cannot fetch into source tree path %s as "
                                   "it exists and is not a directory" %
                                   srctree)
            elif os.listdir(srctree):
                raise DevtoolError("Cannot fetch into source tree path %s as "
                                   "it already exists and is non-empty" %
                                   srctree)
    elif not args.fetch:
        raise DevtoolError("Specified source tree %s could not be found" %
                           srctree)

    appendpath = os.path.join(config.workspace_path, 'appends')
    if not os.path.exists(appendpath):
        os.makedirs(appendpath)

    recipedir = os.path.join(config.workspace_path, 'recipes', args.recipename)
    bb.utils.mkdirhier(recipedir)
    rfv = None
    if args.version:
        if '_' in args.version or ' ' in args.version:
            raise DevtoolError('Invalid version string "%s"' % args.version)
        rfv = args.version
    if args.fetch:
        if args.fetch.startswith('git://'):
            rfv = 'git'
        elif args.fetch.startswith('svn://'):
            rfv = 'svn'
        elif args.fetch.startswith('hg://'):
            rfv = 'hg'
    if rfv:
        bp = "%s_%s" % (args.recipename, rfv)
    else:
        bp = args.recipename
    recipefile = os.path.join(recipedir, "%s.bb" % bp)
    if args.color == 'auto' and sys.stdout.isatty():
        color = 'always'
    else:
        color = args.color
    extracmdopts = ''
    if args.fetch:
        source = args.fetch
        extracmdopts = '-x %s' % srctree
    else:
        source = srctree
    if args.version:
        extracmdopts += ' -V %s' % args.version
    if args.binary:
        extracmdopts += ' -b'
    try:
        stdout, _ = exec_build_env_command(config.init_path, basepath, 'recipetool --color=%s create -o %s "%s" %s' % (color, recipefile, source, extracmdopts))
    except bb.process.ExecutionError as e:
        raise DevtoolError('Command \'%s\' failed:\n%s' % (e.command, e.stdout))

    _add_md5(config, args.recipename, recipefile)

    if args.fetch and not args.no_git:
        setup_git_repo(srctree, args.version, 'devtool')

    initial_rev = None
    if os.path.exists(os.path.join(srctree, '.git')):
        (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree)
        initial_rev = stdout.rstrip()

    tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
    rd = oe.recipeutils.parse_recipe(recipefile, None, tinfoil.config_data)
    if not rd:
        return 1

    appendfile = os.path.join(appendpath, '%s.bbappend' % bp)
    with open(appendfile, 'w') as f:
        f.write('inherit externalsrc\n')
        f.write('EXTERNALSRC = "%s"\n' % srctree)

        b_is_s = use_external_build(args.same_dir, args.no_same_dir, rd)
        if b_is_s:
            f.write('EXTERNALSRC_BUILD = "%s"\n' % srctree)
        if initial_rev:
            f.write('\n# initial_rev: %s\n' % initial_rev)

        if args.binary:
            f.write('do_install_append() {\n')
            f.write('    rm -rf ${D}/.git\n')
            f.write('    rm -f ${D}/singletask.lock\n')
            f.write('}\n')

    _add_md5(config, args.recipename, appendfile)

    logger.info('Recipe %s has been automatically created; further editing may be required to make it fully functional' % recipefile)

    tinfoil.shutdown()

    return 0
Beispiel #2
0
def _extract_source(srctree, keep_temp, devbranch, d):
    """Extract sources of a recipe"""
    import bb.event
    import oe.recipeutils

    def eventfilter(name, handler, event, d):
        """Bitbake event filter for devtool extract operation"""
        if name == 'base_eventhandler':
            return True
        else:
            return False

    if hasattr(bb.event, 'set_eventfilter'):
        bb.event.set_eventfilter(eventfilter)

    pn = d.getVar('PN', True)

    _check_compatible_recipe(pn, d)

    if os.path.exists(srctree):
        if not os.path.isdir(srctree):
            raise DevtoolError("output path %s exists and is not a directory" %
                               srctree)
        elif os.listdir(srctree):
            raise DevtoolError("output path %s already exists and is "
                               "non-empty" % srctree)

    if 'noexec' in (d.getVarFlags('do_unpack', False) or []):
        raise DevtoolError("The %s recipe has do_unpack disabled, unable to "
                           "extract source" % pn)

    # Prepare for shutil.move later on
    bb.utils.mkdirhier(srctree)
    os.rmdir(srctree)

    # We don't want notes to be printed, they are too verbose
    origlevel = bb.logger.getEffectiveLevel()
    if logger.getEffectiveLevel() > logging.DEBUG:
        bb.logger.setLevel(logging.WARNING)

    initial_rev = None
    tempdir = tempfile.mkdtemp(prefix='devtool')
    try:
        crd = d.createCopy()
        # Make a subdir so we guard against WORKDIR==S
        workdir = os.path.join(tempdir, 'workdir')
        crd.setVar('WORKDIR', workdir)
        crd.setVar('T', os.path.join(tempdir, 'temp'))
        if not crd.getVar('S', True).startswith(workdir):
            # Usually a shared workdir recipe (kernel, gcc)
            # Try to set a reasonable default
            if bb.data.inherits_class('kernel', d):
                crd.setVar('S', '${WORKDIR}/source')
            else:
                crd.setVar('S', '${WORKDIR}/%s' % os.path.basename(d.getVar('S', True)))
        if bb.data.inherits_class('kernel', d):
            # We don't want to move the source to STAGING_KERNEL_DIR here
            crd.setVar('STAGING_KERNEL_DIR', '${S}')

        task_executor = BbTaskExecutor(crd)

        crd.setVar('EXTERNALSRC_forcevariable', '')

        logger.info('Fetching %s...' % pn)
        task_executor.exec_func('do_fetch', False)
        logger.info('Unpacking...')
        task_executor.exec_func('do_unpack', False)
        if bb.data.inherits_class('kernel-yocto', d):
            # Extra step for kernel to populate the source directory
            logger.info('Doing kernel checkout...')
            task_executor.exec_func('do_kernel_checkout', False)
        srcsubdir = crd.getVar('S', True)

        # Move local source files into separate subdir
        recipe_patches = [os.path.basename(patch) for patch in
                          oe.recipeutils.get_recipe_patches(crd)]
        local_files = oe.recipeutils.get_recipe_local_files(crd)
        local_files = [fname for fname in local_files if
                       os.path.exists(os.path.join(workdir, fname))]
        if local_files:
            for fname in local_files:
                _move_file(os.path.join(workdir, fname),
                           os.path.join(tempdir, 'oe-local-files', fname))
            with open(os.path.join(tempdir, 'oe-local-files', '.gitignore'),
                      'w') as f:
                f.write('# Ignore local files, by default. Remove this file '
                        'if you want to commit the directory to Git\n*\n')

        if srcsubdir == workdir:
            # Find non-patch non-local sources that were "unpacked" to srctree
            # directory
            src_files = [fname for fname in _ls_tree(workdir) if
                         os.path.basename(fname) not in recipe_patches]
            # Force separate S so that patch files can be left out from srctree
            srcsubdir = tempfile.mkdtemp(dir=workdir)
            crd.setVar('S', srcsubdir)
            # Move source files to S
            for path in src_files:
                _move_file(os.path.join(workdir, path),
                           os.path.join(srcsubdir, path))
        elif os.path.dirname(srcsubdir) != workdir:
            # Handle if S is set to a subdirectory of the source
            srcsubdir = os.path.join(workdir, os.path.relpath(srcsubdir, workdir).split(os.sep)[0])

        scriptutils.git_convert_standalone_clone(srcsubdir)

        patchdir = os.path.join(srcsubdir, 'patches')
        haspatches = False
        if os.path.exists(patchdir):
            if os.listdir(patchdir):
                haspatches = True
            else:
                os.rmdir(patchdir)
        # Make sure that srcsubdir exists
        bb.utils.mkdirhier(srcsubdir)
        if not os.path.exists(srcsubdir) or not os.listdir(srcsubdir):
            logger.warning("no source unpacked to S, either the %s recipe "
                           "doesn't use any source or the correct source "
                           "directory could not be determined" % pn)

        setup_git_repo(srcsubdir, crd.getVar('PV', True), devbranch)

        (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srcsubdir)
        initial_rev = stdout.rstrip()

        crd.setVar('PATCHTOOL', 'git')

        logger.info('Patching...')
        task_executor.exec_func('do_patch', False)

        bb.process.run('git tag -f devtool-patched', cwd=srcsubdir)

        if os.path.exists(patchdir):
            shutil.rmtree(patchdir)
            if haspatches:
                bb.process.run('git checkout patches', cwd=srcsubdir)

        # Move oe-local-files directory to srctree
        if os.path.exists(os.path.join(tempdir, 'oe-local-files')):
            logger.info('Adding local source files to srctree...')
            shutil.move(os.path.join(tempdir, 'oe-local-files'), srcsubdir)


        shutil.move(srcsubdir, srctree)
    finally:
        bb.logger.setLevel(origlevel)

        if keep_temp:
            logger.info('Preserving temporary directory %s' % tempdir)
        else:
            shutil.rmtree(tempdir)
    return initial_rev