diff options
Diffstat (limited to 'scripts/lib')
-rw-r--r-- | scripts/lib/devtool/standard.py | 230 |
1 files changed, 144 insertions, 86 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py index 9b5a0855b2..3a8c66c131 100644 --- a/scripts/lib/devtool/standard.py +++ b/scripts/lib/devtool/standard.py @@ -359,104 +359,162 @@ def update_recipe(args, config, basepath, workspace): from oe.patch import GitApplyTree import oe.recipeutils - srctree = workspace[args.recipename] - commits = [] - update_rev = None - if args.initial_rev: - initial_rev = args.initial_rev - else: - initial_rev = None - with open(appends[0], 'r') as f: - for line in f: - if line.startswith('# initial_rev:'): - initial_rev = line.split(':')[-1].strip() - elif line.startswith('# commit:'): - commits.append(line.split(':')[-1].strip()) - - if initial_rev: - # Find first actually changed revision - (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_rev, cwd=srctree) - newcommits = stdout.split() - for i in xrange(min(len(commits), len(newcommits))): - if newcommits[i] == commits[i]: - update_rev = commits[i] - - if not initial_rev: - logger.error('Unable to find initial revision - please specify it with --initial-rev') - return -1 - - if not update_rev: - update_rev = initial_rev - - # Find list of existing patches in recipe file recipefile = _get_recipe_file(tinfoil.cooker, args.recipename) if not recipefile: # Error already logged return -1 rd = oe.recipeutils.parse_recipe(recipefile, tinfoil.config_data) - existing_patches = oe.recipeutils.get_recipe_patches(rd) - removepatches = [] - if not args.no_remove: - # Get all patches from source tree and check if any should be removed + orig_src_uri = rd.getVar('SRC_URI', False) or '' + if args.mode == 'auto': + if 'git://' in orig_src_uri: + mode = 'srcrev' + else: + mode = 'patch' + else: + mode = args.mode + + def remove_patches(srcuri, patchlist): + # Remove any patches that we don't need + updated = False + for patch in patchlist: + patchfile = os.path.basename(patch) + for i in xrange(len(srcuri)): + if srcuri[i].startswith('file://') and os.path.basename(srcuri[i]).split(';')[0] == patchfile: + logger.info('Removing patch %s' % patchfile) + srcuri.pop(i) + # FIXME "git rm" here would be nice if the file in question is tracked + # FIXME there's a chance that this file is referred to by another recipe, in which case deleting wouldn't be the right thing to do + if patch.startswith(os.path.dirname(recipefile)): + os.remove(patch) + updated = True + break + return updated + + srctree = workspace[args.recipename] + if mode == 'srcrev': + (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree) + srcrev = stdout.strip() + if len(srcrev) != 40: + logger.error('Invalid hash returned by git: %s' % stdout) + return 1 + + logger.info('Updating SRCREV in recipe %s' % os.path.basename(recipefile)) + patchfields = {} + patchfields['SRCREV'] = srcrev + if not args.no_remove: + # Find list of existing patches in recipe file + existing_patches = oe.recipeutils.get_recipe_patches(rd) + + old_srcrev = (rd.getVar('SRCREV', False) or '') + tempdir = tempfile.mkdtemp(prefix='devtool') + removepatches = [] + try: + GitApplyTree.extractPatches(srctree, old_srcrev, tempdir) + newpatches = os.listdir(tempdir) + for patch in existing_patches: + patchfile = os.path.basename(patch) + if patchfile in newpatches: + removepatches.append(patch) + finally: + shutil.rmtree(tempdir) + if removepatches: + srcuri = (rd.getVar('SRC_URI', False) or '').split() + if remove_patches(srcuri, removepatches): + patchfields['SRC_URI'] = ' '.join(srcuri) + + oe.recipeutils.patch_recipe(rd, recipefile, patchfields) + + if not 'git://' in orig_src_uri: + logger.info('You will need to update SRC_URI within the recipe to point to a git repository where you have pushed your changes') + + elif mode == 'patch': + commits = [] + update_rev = None + if args.initial_rev: + initial_rev = args.initial_rev + else: + initial_rev = None + with open(appends[0], 'r') as f: + for line in f: + if line.startswith('# initial_rev:'): + initial_rev = line.split(':')[-1].strip() + elif line.startswith('# commit:'): + commits.append(line.split(':')[-1].strip()) + + if initial_rev: + # Find first actually changed revision + (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_rev, cwd=srctree) + newcommits = stdout.split() + for i in xrange(min(len(commits), len(newcommits))): + if newcommits[i] == commits[i]: + update_rev = commits[i] + + if not initial_rev: + logger.error('Unable to find initial revision - please specify it with --initial-rev') + return -1 + + if not update_rev: + update_rev = initial_rev + + # Find list of existing patches in recipe file + existing_patches = oe.recipeutils.get_recipe_patches(rd) + + removepatches = [] + if not args.no_remove: + # Get all patches from source tree and check if any should be removed + tempdir = tempfile.mkdtemp(prefix='devtool') + try: + GitApplyTree.extractPatches(srctree, initial_rev, tempdir) + newpatches = os.listdir(tempdir) + for patch in existing_patches: + patchfile = os.path.basename(patch) + if patchfile not in newpatches: + removepatches.append(patch) + finally: + shutil.rmtree(tempdir) + + # Get updated patches from source tree tempdir = tempfile.mkdtemp(prefix='devtool') try: - GitApplyTree.extractPatches(srctree, initial_rev, tempdir) + GitApplyTree.extractPatches(srctree, update_rev, tempdir) + + # Match up and replace existing patches with corresponding new patches + updatepatches = False + updaterecipe = False newpatches = os.listdir(tempdir) for patch in existing_patches: patchfile = os.path.basename(patch) - if patchfile not in newpatches: - removepatches.append(patch) + if patchfile in newpatches: + logger.info('Updating patch %s' % patchfile) + shutil.move(os.path.join(tempdir, patchfile), patch) + newpatches.remove(patchfile) + updatepatches = True + srcuri = (rd.getVar('SRC_URI', False) or '').split() + if newpatches: + # Add any patches left over + patchdir = os.path.join(os.path.dirname(recipefile), rd.getVar('BPN', True)) + bb.utils.mkdirhier(patchdir) + for patchfile in newpatches: + logger.info('Adding new patch %s' % patchfile) + shutil.move(os.path.join(tempdir, patchfile), os.path.join(patchdir, patchfile)) + srcuri.append('file://%s' % patchfile) + updaterecipe = True + if removepatches: + if remove_patches(srcuri, removepatches): + updaterecipe = True + if updaterecipe: + logger.info('Updating recipe %s' % os.path.basename(recipefile)) + oe.recipeutils.patch_recipe(rd, recipefile, {'SRC_URI': ' '.join(srcuri)}) + elif not updatepatches: + # Neither patches nor recipe were updated + logger.info('No patches need updating') finally: shutil.rmtree(tempdir) - # Get updated patches from source tree - tempdir = tempfile.mkdtemp(prefix='devtool') - try: - GitApplyTree.extractPatches(srctree, update_rev, tempdir) - - # Match up and replace existing patches with corresponding new patches - updatepatches = False - updaterecipe = False - newpatches = os.listdir(tempdir) - for patch in existing_patches: - patchfile = os.path.basename(patch) - if patchfile in newpatches: - logger.info('Updating patch %s' % patchfile) - shutil.move(os.path.join(tempdir, patchfile), patch) - newpatches.remove(patchfile) - updatepatches = True - srcuri = (rd.getVar('SRC_URI', False) or '').split() - if newpatches: - # Add any patches left over - patchdir = os.path.join(os.path.dirname(recipefile), rd.getVar('BPN', True)) - bb.utils.mkdirhier(patchdir) - for patchfile in newpatches: - logger.info('Adding new patch %s' % patchfile) - shutil.move(os.path.join(tempdir, patchfile), os.path.join(patchdir, patchfile)) - srcuri.append('file://%s' % patchfile) - updaterecipe = True - if removepatches: - # Remove any patches that we don't need - for patch in removepatches: - patchfile = os.path.basename(patch) - for i in xrange(len(srcuri)): - if srcuri[i].startswith('file://') and os.path.basename(srcuri[i]).split(';')[0] == patchfile: - logger.info('Removing patch %s' % patchfile) - srcuri.pop(i) - # FIXME "git rm" here would be nice if the file in question is tracked - # FIXME there's a chance that this file is referred to by another recipe, in which case deleting wouldn't be the right thing to do - os.remove(patch) - updaterecipe = True - break - if updaterecipe: - logger.info('Updating recipe %s' % os.path.basename(recipefile)) - oe.recipeutils.patch_recipe(rd, recipefile, {'SRC_URI': ' '.join(srcuri)}) - elif not updatepatches: - # Neither patches nor recipe were updated - logger.info('No patches need updating') - finally: - shutil.rmtree(tempdir) + else: + logger.error('update_recipe: invalid mode %s' % mode) + return 1 return 0 @@ -539,9 +597,9 @@ def register_commands(subparsers, context): parser_add.set_defaults(func=extract) parser_add = subparsers.add_parser('update-recipe', help='Apply changes from external source tree to recipe', - description='Applies changes from external source tree to a recipe (updating/adding/removing patches as necessary)', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) + description='Applies changes from external source tree to a recipe (updating/adding/removing patches as necessary, or by updating SRCREV)') parser_add.add_argument('recipename', help='Name of recipe to update') + parser_add.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') parser_add.add_argument('--initial-rev', help='Starting revision for patches') parser_add.add_argument('--no-remove', '-n', action="store_true", help='Don\'t remove patches, only add or update') parser_add.set_defaults(func=update_recipe) |