devtool fixes
cover devtool fixes
This series rolls up 5 patches previously posted by Markus (with very minor tweaks to a couple of the commit messages), and adds three new patches from me.
The following changes since commit 166f2587468ae71988c610858aad3f7ef67eccba:
bison: don't depend on help2man (2015-04-21 11:29:30 +0100)
are available in the git repository at:
git://git.openembedded.org/openembedded-core-contrib paule/devtool-fixes2
http://cgit.openembedded.org/cgit.cgi/openembedded-core-contrib/log/?h=paule/devtool-fixes2
Markus Lehtonen (5):
devtool: modify: use B=S if that is the default for the recipe
devtool: modify: implement --no-same-dir
oe-selftest: devtool: fix update-recipe test after bd1aa28
devtool: extract: remove patches when S=WORKDIR
devtool: include bbappends in recipe parsing
Paul Eggleton (3):
devtool: handle . in recipe name
devtool: add: use correct bbappend file name with -V option
devtool: reset: avoid errors in case file no longer exists
meta/lib/oe/recipeutils.py | 10 ++--- meta/lib/oeqa/selftest/devtool.py | 15 +++++-- scripts/devtool | 2 +- scripts/lib/devtool/standard.py | 90 ++++++++++++++++++++++++++++++--------- 4 files changed, 86 insertions(+), 31 deletions(-)
Signature · 1 line
2.1.0
PATCH 1/8 devtool: modify: use B=S if that is the default for the recipe
From: Markus Lehtonen <[email protected]>
Makes the build succeed for packages which do not support separate build directory, e.g. zlib. The same outcome could be achieved with the --same-dir option, but, it's generally hard to tell if a random package would need that option. The negative side effect of this patch is that dev srctree (of some packages that build fine without this modification) gets dirtied by build artefacts.
--- scripts/lib/devtool/standard.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
scripts/lib/devtool/standard.py +12 -5
@@ -384,12 +384,19 @@ def modify(args, config, basepath, workspace): f.write('inherit externalsrc\n') f.write('# NOTE: We use pn- overrides here to avoid affecting multiple variants in the case where the recipe uses BBCLASSEXTEND\n') f.write('EXTERNALSRC_pn-%s = "%s"\n' % (args.recipename, srctree)) - if args.same_dir or bb.data.inherits_class('autotools-brokensep', rd): - if args.same_dir: - logger.info('using source tree as build directory since --same-dir specified') - else: - logger.info('using source tree as build directory since original recipe inherits autotools-brokensep') + + b_is_s = True + if args.same_dir: + logger.info('using source tree as build directory since --same-dir specified') + elif bb.data.inherits_class('autotools-brokensep', rd): + logger.info('using source tree as build directory since original recipe inherits autotools-brokensep') + elif rd.getVar('B', True) == s: + logger.info('using source tree as build directory since that is the default for this recipe') + else: + b_is_s = False + if b_is_s: f.write('EXTERNALSRC_BUILD_pn-%s = "%s"\n' % (args.recipename, srctree)) + if initial_rev: f.write('\n# initial_rev: %s\n' % initial_rev) for commit in commits:
Signature · 1 line
2.1.0
PATCH 2/8 devtool: modify: implement --no-same-dir
In reply to Paul EggletonFrom: Markus Lehtonen <[email protected]>
This option can be used to have a separate build directory, in order to keep the srctree directory clean for packages that do not need to be built in the source directory.
--- scripts/lib/devtool/standard.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
scripts/lib/devtool/standard.py +7 -2
@@ -386,7 +386,10 @@ def modify(args, config, basepath, workspace): f.write('EXTERNALSRC_pn-%s = "%s"\n' % (args.recipename, srctree)) b_is_s = True - if args.same_dir: + if args.no_same_dir: + logger.info('using separate build directory since --no-same-dir specified') + b_is_s = False + elif args.same_dir: logger.info('using source tree as build directory since --same-dir specified') elif bb.data.inherits_class('autotools-brokensep', rd): logger.info('using source tree as build directory since original recipe inherits autotools-brokensep')
@@ -664,7 +667,9 @@ def register_commands(subparsers, context): parser_modify.add_argument('srctree', help='Path to external source tree') parser_modify.add_argument('--wildcard', '-w', action="store_true", help='Use wildcard for unversioned bbappend') parser_modify.add_argument('--extract', '-x', action="store_true", help='Extract source as well') - parser_modify.add_argument('--same-dir', '-s', help='Build in same directory as source', action="store_true") + group = parser_modify.add_mutually_exclusive_group() + group.add_argument('--same-dir', '-s', help='Build in same directory as source', action="store_true") + group.add_argument('--no-same-dir', help='Force build in a separate build directory', action="store_true") parser_modify.add_argument('--branch', '-b', default="devtool", help='Name for development branch to checkout (only when using -x)') parser_modify.set_defaults(func=modify)
Signature · 1 line
2.1.0
PATCH 3/8 oe-selftest: devtool: fix update-recipe test after bd1aa28
In reply to Paul EggletonFrom: Markus Lehtonen <[email protected]>
Number of patches in mtd-utils changed in changeset bd1aa28.
--- meta/lib/oeqa/selftest/devtool.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
meta/lib/oeqa/selftest/devtool.py +9 -2
@@ -397,19 +397,26 @@ class DevtoolTests(oeSelfTest): result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) self.assertNotEqual(result.output.strip(), "", '%s recipe should be modified' % testrecipe) status = result.output.splitlines() - self.assertEqual(len(status), 3, 'Less/more files modified than expected. Entire status:\n%s' % result.output) + self.assertEqual(len(status), 4, 'Less/more files modified than expected. Entire status:\n%s' % result.output) for line in status: if line.endswith('add-exclusion-to-mkfs-jffs2-git-2.patch'): self.assertEqual(line[:3], ' D ', 'Unexpected status in line: %s' % line) elif line.endswith('fix-armv7-neon-alignment.patch'): self.assertEqual(line[:3], ' D ', 'Unexpected status in line: %s' % line) + elif line.endswith('-duplicate-hashtable_iterator_value-.patch'): + self.assertEqual(line[:3], ' D ', 'Unexpected status in line: %s' % line) elif re.search('%s_[^_]*.bb$' % testrecipe, line): self.assertEqual(line[:3], ' M ', 'Unexpected status in line: %s' % line) else: raise AssertionError('Unexpected modified file in status: %s' % line) result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile)) addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git"'] - removelines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git \\\\', 'file://add-exclusion-to-mkfs-jffs2-git-2.patch \\\\', 'file://fix-armv7-neon-alignment.patch \\\\', '"'] + removelines = ['SRCREV = ".*"', + 'SRC_URI = "git://git.infradead.org/mtd-utils.git \\\\', + 'file://add-exclusion-to-mkfs-jffs2-git-2.patch \\\\', + 'file://fix-armv7-neon-alignment.patch \\\\', + 'file://0001-hashtable-Remove-duplicate-hashtable_iterator_value-.patch \\\\', + '"'] for line in result.output.splitlines(): if line.startswith('+++') or line.startswith('---'): continue
Signature · 1 line
2.1.0
PATCH 4/8 devtool: extract: remove patches when S=WORKDIR
In reply to Paul EggletonFrom: Markus Lehtonen <[email protected]>
All local files from the layer, including patches, are added to to srctree repository when S==WORKDIR. The patch files are useless as they are automatically applied on top of the srctree by devtool.
This change causes devtool extract to not commit these unnecessary (and possibly confusing) patch file(s) into srctree repository.
[YOCTO #7602]
--- scripts/lib/devtool/standard.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
scripts/lib/devtool/standard.py +20 -0
@@ -153,6 +153,7 @@ def extract(args, config, basepath, workspace): def _extract_source(srctree, keep_temp, devbranch, d): import bb.event + import oe.recipeutils def eventfilter(name, handler, event, d): if name == 'base_eventhandler':
@@ -240,6 +241,13 @@ def _extract_source(srctree, keep_temp, devbranch, d): else: os.rmdir(patchdir) + # Find local patches that were "unpacked" to srctree directory + recipe_patches = [os.path.basename(patch) for patch in + oe.recipeutils.get_recipe_patches(crd)] + patches = [fname for fname in os.listdir(workdir) if fname in + recipe_patches] + + # Set-up srctree repo if bb.data.inherits_class('kernel-yocto', d): (stdout, _) = bb.process.run('git --git-dir="%s" rev-parse HEAD' % crd.expand('${WORKDIR}/git'), cwd=srcsubdir) initial_rev = stdout.rstrip()
@@ -251,6 +259,10 @@ def _extract_source(srctree, keep_temp, devbranch, d): if not os.path.exists(os.path.join(srcsubdir, '.git')): bb.process.run('git init', cwd=srcsubdir) bb.process.run('git add .', cwd=srcsubdir) + # Do not commit patches (would happend if S=WORKDIR) + if patches and srcsubdir == workdir: + bb.process.run('git reset -- %s' % " ".join(patches), + cwd=srcsubdir) bb.process.run('git commit -q -m "Initial commit from upstream at version %s"' % crd.getVar('PV', True), cwd=srcsubdir) (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srcsubdir)
@@ -266,6 +278,14 @@ def _extract_source(srctree, keep_temp, devbranch, d): bb.process.run('git tag -f devtool-patched', cwd=srcsubdir) + # Remove patches if S=WORKDIR so that stale patch files are not present + # in the srtree + if patches and srcsubdir == workdir: + logger.info('Removing patch files...') + for patch in patches: + os.unlink(os.path.join(workdir, patch)) + + if os.path.exists(patchdir): shutil.rmtree(patchdir) if haspatches:
Signature · 1 line
2.1.0
Re: [PATCH 4/8] devtool: extract: remove patches when S=WORKDIR
Hi,
Quoted 66 lines · Paul Eggleton
From: Markus Lehtonen <[email protected]>
All local files from the layer, including patches, are added to to srctree repository when S==WORKDIR. The patch files are useless as they are automatically applied on top of the srctree by devtool.
This change causes devtool extract to not commit these unnecessary (and possibly confusing) patch file(s) into srctree repository.
[YOCTO #7602]
Signed-off-by Markus Lehtonen <[email protected]>---
scripts/lib/devtool/standard.py| 20 ++++++++++++++++++++1 file changed, 20 insertions(+)scripts/lib/devtool/standard.py +0
-0@@ -153,6 +153,7 @@ def extract(args, config, basepath, workspace):def
_extract_source(srctree, keep_temp, devbranch, d):
import bb.eventscripts/lib/devtool/standard.py +1
-0+ import oe.recipeutils def eventfilter(name, handler, event, d): if name == 'base_eventhandler':@@ -240,6 +241,13 @@ def _extract_source(srctree, keep_temp, devbranch,d):
else:
os.rmdir(patchdir)scripts/lib/devtool/standard.py +7
-0+ # Find local patches that were "unpacked" to srctree directory + recipe_patches = [os.path.basename(patch) for patch in + oe.recipeutils.get_recipe_patches(crd)] + patches = [fname for fname in os.listdir(workdir) if fname in + recipe_patches] + + # Set-up srctree repo if bb.data.inherits_class('kernel-yocto', d): (stdout, _) = bb.process.run('git --git-dir="%s" rev-parseHEAD' %
crd.expand('${WORKDIR}/git'), cwd=srcsubdir)
initial_rev=stdout.rstrip()scripts/lib/devtool/standard.py +0
-0@@ -251,6 +259,10 @@ def _extract_source(srctree, keep_temp, devbranch,d):
if notos.path.exists(os.path.join(srcsubdir, '.git')):
bb.process.run('git init', cwd=srcsubdir)bb.process.run('git add .', cwd=srcsubdir)scripts/lib/devtool/standard.py +4
-0+ # Do not commit patches (would happend if S=WORKDIR) + if patches and srcsubdir == workdir: + bb.process.run('git reset -- %s' % " ".join(patches), + cwd=srcsubdir) bb.process.run('git commit -q -m "Initial commit fromupstream at version %s"' %
crd.getVar('PV', True), cwd=srcsubdir)(stdout, _) = bb.process.run('git rev-parse HEAD',
cwd=srcsubdir)scripts/lib/devtool/standard.py +0
-0@@ -266,6 +278,14 @@ def _extract_source(srctree, keep_temp, devbranch,d):
bb.process.run('git tag -f devtool-patched', cwd=srcsubdir)+ # Remove patches if S=WORKDIR so that stale patch files are not
present
scripts/lib/devtool/standard.py def _extract_source(srctree, keep_temp, devbranch, d): · line 291
Quoted 10 lines
scripts/lib/devtool/standard.py +7
-0+ # in the srtree + if patches and srcsubdir == workdir: + logger.info('Removing patch files...') + for patch in patches: + os.unlink(os.path.join(workdir, patch)) + + if os.path.exists(patchdir): shutil.rmtree(patchdir) if haspatches:
NACK! Please skip this patch for now. I just found out it doesn't work as expected. I'll submit a new version when I've worked around the problems.
Thanks,
Markus
Re: [PATCH 4/8] devtool: extract: remove patches when S=WORKDIR
Quoted 2 lines · On Friday 24 April 2015 11:38:45 Markus Lehtonen wrote:
NACK! Please skip this patch for now. I just found out it doesn't work as expected. I'll submit a new version when I've worked around the problems.
OK, I've re-pushed the branch with this patch removed.
Cheers,
Paul
Signature · 2 lines
Paul Eggleton Intel Open Source Technology Centre
PATCH 5/8 devtool: include bbappends in recipe parsing
In reply to Paul EggletonFrom: Markus Lehtonen <[email protected]>
In order to get correct metadata, SRCREV for example.
Fixes [YOCTO #7648].
--- meta/lib/oe/recipeutils.py | 6 +++--- scripts/lib/devtool/standard.py | 35 ++++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 16 deletions(-)
meta/lib/oe/recipeutils.py +3 -3
@@ -44,10 +44,10 @@ def get_unavailable_reasons(cooker, pn): return taskdata.get_reasons(pn) -def parse_recipe(fn, d): +def parse_recipe(fn, appends, d): """Parse an individual recipe""" import bb.cache - envdata = bb.cache.Cache.loadDataFull(fn, [], d) + envdata = bb.cache.Cache.loadDataFull(fn, appends, d) return envdata
@@ -55,7 +55,7 @@ def get_var_files(fn, varlist, d): """Find the file in which each of a list of variables is set. Note: requires variable history to be enabled when parsing. """ - envdata = parse_recipe(fn, d) + envdata = parse_recipe(fn, [], d) varfiles = {} for v in varlist: history = envdata.varhistory.variable(v)
scripts/lib/devtool/standard.py +22 -13
@@ -130,18 +130,29 @@ def _get_recipe_file(cooker, pn): logger.error("Unable to find any recipe file matching %s" % pn) return recipefile +def _parse_recipe(config, tinfoil, pn, appends): + """Parse recipe of a package""" + import oe.recipeutils + recipefile = _get_recipe_file(tinfoil.cooker, pn) + if not recipefile: + # Error already logged + return None + if appends: + append_files = tinfoil.cooker.collection.get_file_appends(recipefile) + # Filter out appends from the workspace + append_files = [path for path in append_files if + not path.startswith(config.workspace_path)] + return oe.recipeutils.parse_recipe(recipefile, append_files, + tinfoil.config_data) def extract(args, config, basepath, workspace): import bb - import oe.recipeutils tinfoil = setup_tinfoil() - recipefile = _get_recipe_file(tinfoil.cooker, args.recipename) - if not recipefile: - # Error already logged + rd = _parse_recipe(config, tinfoil, args.recipename, True) + if not rd: return -1 - rd = oe.recipeutils.parse_recipe(recipefile, tinfoil.config_data) srctree = os.path.abspath(args.srctree) initial_rev = _extract_source(srctree, args.keep_temp, args.branch, rd)
@@ -347,11 +358,10 @@ def modify(args, config, basepath, workspace): tinfoil = setup_tinfoil() - recipefile = _get_recipe_file(tinfoil.cooker, args.recipename) - if not recipefile: - # Error already logged + rd = _parse_recipe(config, tinfoil, args.recipename, True) + if not rd: return -1 - rd = oe.recipeutils.parse_recipe(recipefile, tinfoil.config_data) + recipefile = rd.getVar('FILE', True) if not _check_compatible_recipe(args.recipename, rd): return -1
@@ -448,11 +458,10 @@ def update_recipe(args, config, basepath, workspace): from oe.patch import GitApplyTree import oe.recipeutils - recipefile = _get_recipe_file(tinfoil.cooker, args.recipename) - if not recipefile: - # Error already logged + rd = _parse_recipe(config, tinfoil, args.recipename, True) + if not rd: return -1 - rd = oe.recipeutils.parse_recipe(recipefile, tinfoil.config_data) + recipefile = rd.getVar('FILE', True) orig_src_uri = rd.getVar('SRC_URI', False) or '' if args.mode == 'auto':
Signature · 1 line
2.1.0
PATCH 6/8 devtool: handle . in recipe name
In reply to Paul EggletonNames such as glib-2.0 are valid (and used) recipe names, so we need to support them.
Fixes [YOCTO #7643].
--- meta/lib/oe/recipeutils.py | 4 ++-- scripts/devtool | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
meta/lib/oe/recipeutils.py +2 -2
@@ -269,8 +269,8 @@ def get_recipe_patches(d): def validate_pn(pn): """Perform validation on a recipe name (PN) for a new recipe.""" reserved_names = ['forcevariable', 'append', 'prepend', 'remove'] - if not re.match('[0-9a-z-]+', pn): - return 'Recipe name "%s" is invalid: only characters 0-9, a-z and - are allowed' % pn + if not re.match('[0-9a-z-.]+', pn): + return 'Recipe name "%s" is invalid: only characters 0-9, a-z, - and . are allowed' % pn elif pn in reserved_names: return 'Recipe name "%s" is invalid: is a reserved keyword' % pn elif pn.startswith('pn-'):
scripts/devtool +1 -1
@@ -101,7 +101,7 @@ def read_workspace(): _create_workspace(config.workspace_path, config, basepath) logger.debug('Reading workspace in %s' % config.workspace_path) - externalsrc_re = re.compile(r'^EXTERNALSRC(_pn-[a-zA-Z0-9-]*)? =.*$') + externalsrc_re = re.compile(r'^EXTERNALSRC(_pn-[^ =]+)? =.*$') for fn in glob.glob(os.path.join(config.workspace_path, 'appends', '*.bbappend')): pn = os.path.splitext(os.path.basename(fn))[0].split('_')[0] with open(fn, 'r') as f:
Signature · 1 line
2.1.0
PATCH 7/8 devtool: add: use correct bbappend file name with -V option
In reply to Paul EggletonWe weren't adding the version into the bbappend file name which meant that building or resetting failed.
Also adjust one of the tests so that we're testing devtool add both with and without this option.
Fixes [YOCTO #7647].
--- meta/lib/oeqa/selftest/devtool.py | 4 ++-- scripts/lib/devtool/standard.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
meta/lib/oeqa/selftest/devtool.py +2 -2
@@ -150,10 +150,10 @@ class DevtoolTests(oeSelfTest): result = runCmd('tar xfv libftdi1-1.1.tar.bz2', cwd=tempdir) srcdir = os.path.join(tempdir, 'libftdi1-1.1') self.assertTrue(os.path.isfile(os.path.join(srcdir, 'CMakeLists.txt')), 'Unable to find CMakeLists.txt in source directory') - # Test devtool add + # Test devtool add (and use -V so we test that too) self.track_for_cleanup(workspacedir) self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') - result = runCmd('devtool add libftdi %s' % srcdir) + result = runCmd('devtool add libftdi %s -V 1.1' % srcdir) self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created') # Test devtool status result = runCmd('devtool status')
scripts/lib/devtool/standard.py +1 -1
@@ -73,7 +73,7 @@ def add(args, config, basepath, workspace): (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree) initial_rev = stdout.rstrip() - appendfile = os.path.join(appendpath, '%s.bbappend' % args.recipename) + 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)
Signature · 1 line
2.1.0
PATCH 8/8 devtool: reset: avoid errors in case file no longer exists
In reply to Paul EggletonIf you manually delete files in the workspace layer (which you really shouldn't) it was possible to get yourself into the situation where you couldn't reset because we were attempting to check if the file had been modified and erroring out if it couldn't be opened. If the file's not there anymore there's not much point checking if it needs to be preserved, just skip it.
--- scripts/lib/devtool/standard.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
scripts/lib/devtool/standard.py +8 -1
@@ -328,7 +328,14 @@ def _check_preserve(config, recipename): splitline = line.rstrip().split('|') if splitline[0] == recipename: removefile = os.path.join(config.workspace_path, splitline[1]) - md5 = bb.utils.md5_file(removefile) + try: + md5 = bb.utils.md5_file(removefile) + except IOError as err: + if err.errno == 2: + # File no longer exists, skip it + continue + else: + raise if splitline[2] != md5: bb.utils.mkdirhier(preservepath) preservefile = os.path.basename(removefile)
Signature · 1 line
2.1.0