summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2016-07-14 09:04:25 +1200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-07-20 10:28:49 +0100
commitd62fd7711d508a4bd926e46a235d2511401f543d (patch)
tree9968d72a87dc9176a45a7c2b596a2b71404f6753 /scripts
parent10a5af5eb4f928abe1fe12e63520f656b682d55d (diff)
downloadpoky-d62fd7711d508a4bd926e46a235d2511401f543d.tar.gz
devtool: add finish subcommand
Add a subcommand which will "finish" the work on a recipe. This is effectively the same as update-recipe followed by reset, except that the destination layer is required and it will do the right thing depending on the situation - if the recipe file itself is in the workspace (e.g. as a result of devtool add), the recipe file and any associated files will be moved to the destination layer; or if the destination layer is the one containing the original recipe, the recipe will be overwritten; otherwise a bbappend will be created to apply the changes. In all cases the layer path can be loosely specified - it could be a layer name, or a partial path into a recipe. In the case of upgrades, devtool finish will also take care of deleting the old recipe. This avoids the user having to figure out the correct actions when they're done - they just do "devtool finish recipename layername" and it saves their work and then removes the recipe from the workspace. Addresses [YOCTO #8594]. (From OE-Core rev: fa550fcb9333d59b28fc0e4aebde888831410f5c) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/lib/devtool/standard.py111
1 files changed, 110 insertions, 1 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 5a5995f664..9c09533b54 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -1,6 +1,6 @@
1# Development tool - standard commands plugin 1# Development tool - standard commands plugin
2# 2#
3# Copyright (C) 2014-2015 Intel Corporation 3# Copyright (C) 2014-2016 Intel Corporation
4# 4#
5# This program is free software; you can redistribute it and/or modify 5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 2 as 6# it under the terms of the GNU General Public License version 2 as
@@ -1394,6 +1394,106 @@ def reset(args, config, basepath, workspace):
1394 return 0 1394 return 0
1395 1395
1396 1396
1397def _get_layer(layername, d):
1398 """Determine the base layer path for the specified layer name/path"""
1399 layerdirs = d.getVar('BBLAYERS', True).split()
1400 layers = {os.path.basename(p): p for p in layerdirs}
1401 # Provide some shortcuts
1402 if layername.lower() in ['oe-core', 'openembedded-core']:
1403 layerdir = layers.get('meta', None)
1404 else:
1405 layerdir = layers.get(layername, None)
1406 if layerdir:
1407 layerdir = os.path.abspath(layerdir)
1408 return layerdir or layername
1409
1410def finish(args, config, basepath, workspace):
1411 """Entry point for the devtool 'finish' subcommand"""
1412 import bb
1413 import oe.recipeutils
1414
1415 check_workspace_recipe(workspace, args.recipename)
1416
1417 tinfoil = setup_tinfoil(basepath=basepath, tracking=True)
1418 try:
1419 rd = parse_recipe(config, tinfoil, args.recipename, True)
1420 if not rd:
1421 return 1
1422
1423 destlayerdir = _get_layer(args.destination, tinfoil.config_data)
1424 origlayerdir = oe.recipeutils.find_layerdir(rd.getVar('FILE', True))
1425
1426 if not os.path.isdir(destlayerdir):
1427 raise DevtoolError('Unable to find layer or directory matching "%s"' % args.destination)
1428
1429 if os.path.abspath(destlayerdir) == config.workspace_path:
1430 raise DevtoolError('"%s" specifies the workspace layer - that is not a valid destination' % args.destination)
1431
1432 # If it's an upgrade, grab the original path
1433 origpath = None
1434 origfilelist = None
1435 append = workspace[args.recipename]['bbappend']
1436 with open(append, 'r') as f:
1437 for line in f:
1438 if line.startswith('# original_path:'):
1439 origpath = line.split(':')[1].strip()
1440 elif line.startswith('# original_files:'):
1441 origfilelist = line.split(':')[1].split()
1442
1443 if origlayerdir == config.workspace_path:
1444 # Recipe file itself is in workspace, update it there first
1445 appendlayerdir = None
1446 origrelpath = None
1447 if origpath:
1448 origlayerpath = oe.recipeutils.find_layerdir(origpath)
1449 if origlayerpath:
1450 origrelpath = os.path.relpath(origpath, origlayerpath)
1451 destpath = oe.recipeutils.get_bbfile_path(rd, destlayerdir, origrelpath)
1452 if not destpath:
1453 raise DevtoolError("Unable to determine destination layer path - check that %s specifies an actual layer and %s/conf/layer.conf specifies BBFILES. You may also need to specify a more complete path." % (args.destination, destlayerdir))
1454 elif destlayerdir == origlayerdir:
1455 # Same layer, update the original recipe
1456 appendlayerdir = None
1457 destpath = None
1458 else:
1459 # Create/update a bbappend in the specified layer
1460 appendlayerdir = destlayerdir
1461 destpath = None
1462
1463 # Remove any old files in the case of an upgrade
1464 if origpath and origfilelist and oe.recipeutils.find_layerdir(origpath) == oe.recipeutils.find_layerdir(destlayerdir):
1465 for fn in origfilelist:
1466 fnp = os.path.join(origpath, fn)
1467 try:
1468 os.remove(fnp)
1469 except FileNotFoundError:
1470 pass
1471
1472 # Actually update the recipe / bbappend
1473 _update_recipe(args.recipename, workspace, rd, args.mode, appendlayerdir, wildcard_version=True, no_remove=False, initial_rev=args.initial_rev)
1474
1475 if origlayerdir == config.workspace_path and destpath:
1476 # Recipe file itself is in the workspace - need to move it and any
1477 # associated files to the specified layer
1478 logger.info('Moving recipe file to %s' % destpath)
1479 recipedir = os.path.dirname(rd.getVar('FILE', True))
1480 for root, _, files in os.walk(recipedir):
1481 for fn in files:
1482 srcpath = os.path.join(root, fn)
1483 relpth = os.path.relpath(os.path.dirname(srcpath), recipedir)
1484 destdir = os.path.abspath(os.path.join(destpath, relpth))
1485 bb.utils.mkdirhier(destdir)
1486 shutil.move(srcpath, os.path.join(destdir, fn))
1487
1488 finally:
1489 tinfoil.shutdown()
1490
1491 # Everything else has succeeded, we can now reset
1492 _reset([args.recipename], no_clean=False, config=config, basepath=basepath, workspace=workspace)
1493
1494 return 0
1495
1496
1397def get_default_srctree(config, recipename=''): 1497def get_default_srctree(config, recipename=''):
1398 """Get the default srctree path""" 1498 """Get the default srctree path"""
1399 srctreeparent = config.get('General', 'default_source_parent_dir', config.workspace_path) 1499 srctreeparent = config.get('General', 'default_source_parent_dir', config.workspace_path)
@@ -1481,3 +1581,12 @@ def register_commands(subparsers, context):
1481 parser_reset.add_argument('--all', '-a', action="store_true", help='Reset all recipes (clear workspace)') 1581 parser_reset.add_argument('--all', '-a', action="store_true", help='Reset all recipes (clear workspace)')
1482 parser_reset.add_argument('--no-clean', '-n', action="store_true", help='Don\'t clean the sysroot to remove recipe output') 1582 parser_reset.add_argument('--no-clean', '-n', action="store_true", help='Don\'t clean the sysroot to remove recipe output')
1483 parser_reset.set_defaults(func=reset) 1583 parser_reset.set_defaults(func=reset)
1584
1585 parser_finish = subparsers.add_parser('finish', help='Finish working on a recipe in your workspace',
1586 description='Pushes any committed changes to the specified recipe to the specified layer and removes it from your workspace. Roughly equivalent to an update-recipe followed by reset, except the update-recipe step will do the "right thing" depending on the recipe and the destination layer specified.',
1587 group='working', order=-100)
1588 parser_finish.add_argument('recipename', help='Recipe to finish')
1589 parser_finish.add_argument('destination', help='Layer/path to put recipe into. Can be the name of a layer configured in your bblayers.conf, the path to the base of a layer, or a partial path inside a layer. %(prog)s will attempt to complete the path based on the layer\'s structure.')
1590 parser_finish.add_argument('--mode', '-m', choices=['patch', 'srcrev', 'auto'], default='auto', help='Update mode (where %(metavar)s is %(choices)s; default is %(default)s)', metavar='MODE')
1591 parser_finish.add_argument('--initial-rev', help='Override starting revision for patches')
1592 parser_finish.set_defaults(func=finish)