summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2015-02-19 16:40:00 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-02-23 17:35:29 +0000
commitefedd4323b719679b3f6c050e1c7c29e2804cd10 (patch)
treeefdbc21949d9b671e63cd3bb9ca78b4f3c68e230 /scripts
parent6015deb9f37d1e15bee0594252bfc474cca66902 (diff)
downloadpoky-efedd4323b719679b3f6c050e1c7c29e2804cd10.tar.gz
devtool: update-recipe: add handling for git recipes
When updating git-based recipes, in a lot of cases what you want is to push the changes to the repository and update SRCREV rather than to apply patches within the recipe. Updating SRCREV is now the default behaviour for recipes that fetch from git, but this can be overridden in both directions using a new -m/--mode option. (From OE-Core rev: 654792bb87610ee3569d02a85fa9ec071bf8ab6d) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/lib/devtool/standard.py230
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):
359 from oe.patch import GitApplyTree 359 from oe.patch import GitApplyTree
360 import oe.recipeutils 360 import oe.recipeutils
361 361
362 srctree = workspace[args.recipename]
363 commits = []
364 update_rev = None
365 if args.initial_rev:
366 initial_rev = args.initial_rev
367 else:
368 initial_rev = None
369 with open(appends[0], 'r') as f:
370 for line in f:
371 if line.startswith('# initial_rev:'):
372 initial_rev = line.split(':')[-1].strip()
373 elif line.startswith('# commit:'):
374 commits.append(line.split(':')[-1].strip())
375
376 if initial_rev:
377 # Find first actually changed revision
378 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_rev, cwd=srctree)
379 newcommits = stdout.split()
380 for i in xrange(min(len(commits), len(newcommits))):
381 if newcommits[i] == commits[i]:
382 update_rev = commits[i]
383
384 if not initial_rev:
385 logger.error('Unable to find initial revision - please specify it with --initial-rev')
386 return -1
387
388 if not update_rev:
389 update_rev = initial_rev
390
391 # Find list of existing patches in recipe file
392 recipefile = _get_recipe_file(tinfoil.cooker, args.recipename) 362 recipefile = _get_recipe_file(tinfoil.cooker, args.recipename)
393 if not recipefile: 363 if not recipefile:
394 # Error already logged 364 # Error already logged
395 return -1 365 return -1
396 rd = oe.recipeutils.parse_recipe(recipefile, tinfoil.config_data) 366 rd = oe.recipeutils.parse_recipe(recipefile, tinfoil.config_data)
397 existing_patches = oe.recipeutils.get_recipe_patches(rd)
398 367
399 removepatches = [] 368 orig_src_uri = rd.getVar('SRC_URI', False) or ''
400 if not args.no_remove: 369 if args.mode == 'auto':
401 # Get all patches from source tree and check if any should be removed 370 if 'git://' in orig_src_uri:
371 mode = 'srcrev'
372 else:
373 mode = 'patch'
374 else:
375 mode = args.mode
376
377 def remove_patches(srcuri, patchlist):
378 # Remove any patches that we don't need
379 updated = False
380 for patch in patchlist:
381 patchfile = os.path.basename(patch)
382 for i in xrange(len(srcuri)):
383 if srcuri[i].startswith('file://') and os.path.basename(srcuri[i]).split(';')[0] == patchfile:
384 logger.info('Removing patch %s' % patchfile)
385 srcuri.pop(i)
386 # FIXME "git rm" here would be nice if the file in question is tracked
387 # 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
388 if patch.startswith(os.path.dirname(recipefile)):
389 os.remove(patch)
390 updated = True
391 break
392 return updated
393
394 srctree = workspace[args.recipename]
395 if mode == 'srcrev':
396 (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree)
397 srcrev = stdout.strip()
398 if len(srcrev) != 40:
399 logger.error('Invalid hash returned by git: %s' % stdout)
400 return 1
401
402 logger.info('Updating SRCREV in recipe %s' % os.path.basename(recipefile))
403 patchfields = {}
404 patchfields['SRCREV'] = srcrev
405 if not args.no_remove:
406 # Find list of existing patches in recipe file
407 existing_patches = oe.recipeutils.get_recipe_patches(rd)
408
409 old_srcrev = (rd.getVar('SRCREV', False) or '')
410 tempdir = tempfile.mkdtemp(prefix='devtool')
411 removepatches = []
412 try:
413 GitApplyTree.extractPatches(srctree, old_srcrev, tempdir)
414 newpatches = os.listdir(tempdir)
415 for patch in existing_patches:
416 patchfile = os.path.basename(patch)
417 if patchfile in newpatches:
418 removepatches.append(patch)
419 finally:
420 shutil.rmtree(tempdir)
421 if removepatches:
422 srcuri = (rd.getVar('SRC_URI', False) or '').split()
423 if remove_patches(srcuri, removepatches):
424 patchfields['SRC_URI'] = ' '.join(srcuri)
425
426 oe.recipeutils.patch_recipe(rd, recipefile, patchfields)
427
428 if not 'git://' in orig_src_uri:
429 logger.info('You will need to update SRC_URI within the recipe to point to a git repository where you have pushed your changes')
430
431 elif mode == 'patch':
432 commits = []
433 update_rev = None
434 if args.initial_rev:
435 initial_rev = args.initial_rev
436 else:
437 initial_rev = None
438 with open(appends[0], 'r') as f:
439 for line in f:
440 if line.startswith('# initial_rev:'):
441 initial_rev = line.split(':')[-1].strip()
442 elif line.startswith('# commit:'):
443 commits.append(line.split(':')[-1].strip())
444
445 if initial_rev:
446 # Find first actually changed revision
447 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_rev, cwd=srctree)
448 newcommits = stdout.split()
449 for i in xrange(min(len(commits), len(newcommits))):
450 if newcommits[i] == commits[i]:
451 update_rev = commits[i]
452
453 if not initial_rev:
454 logger.error('Unable to find initial revision - please specify it with --initial-rev')
455 return -1
456
457 if not update_rev:
458 update_rev = initial_rev
459
460 # Find list of existing patches in recipe file
461 existing_patches = oe.recipeutils.get_recipe_patches(rd)
462
463 removepatches = []
464 if not args.no_remove:
465 # Get all patches from source tree and check if any should be removed
466 tempdir = tempfile.mkdtemp(prefix='devtool')
467 try:
468 GitApplyTree.extractPatches(srctree, initial_rev, tempdir)
469 newpatches = os.listdir(tempdir)
470 for patch in existing_patches:
471 patchfile = os.path.basename(patch)
472 if patchfile not in newpatches:
473 removepatches.append(patch)
474 finally:
475 shutil.rmtree(tempdir)
476
477 # Get updated patches from source tree
402 tempdir = tempfile.mkdtemp(prefix='devtool') 478 tempdir = tempfile.mkdtemp(prefix='devtool')
403 try: 479 try:
404 GitApplyTree.extractPatches(srctree, initial_rev, tempdir) 480 GitApplyTree.extractPatches(srctree, update_rev, tempdir)
481
482 # Match up and replace existing patches with corresponding new patches
483 updatepatches = False
484 updaterecipe = False
405 newpatches = os.listdir(tempdir) 485 newpatches = os.listdir(tempdir)
406 for patch in existing_patches: 486 for patch in existing_patches:
407 patchfile = os.path.basename(patch) 487 patchfile = os.path.basename(patch)
408 if patchfile not in newpatches: 488 if patchfile in newpatches:
409 removepatches.append(patch) 489 logger.info('Updating patch %s' % patchfile)
490 shutil.move(os.path.join(tempdir, patchfile), patch)
491 newpatches.remove(patchfile)
492 updatepatches = True
493 srcuri = (rd.getVar('SRC_URI', False) or '').split()
494 if newpatches:
495 # Add any patches left over
496 patchdir = os.path.join(os.path.dirname(recipefile), rd.getVar('BPN', True))
497 bb.utils.mkdirhier(patchdir)
498 for patchfile in newpatches:
499 logger.info('Adding new patch %s' % patchfile)
500 shutil.move(os.path.join(tempdir, patchfile), os.path.join(patchdir, patchfile))
501 srcuri.append('file://%s' % patchfile)
502 updaterecipe = True
503 if removepatches:
504 if remove_patches(srcuri, removepatches):
505 updaterecipe = True
506 if updaterecipe:
507 logger.info('Updating recipe %s' % os.path.basename(recipefile))
508 oe.recipeutils.patch_recipe(rd, recipefile, {'SRC_URI': ' '.join(srcuri)})
509 elif not updatepatches:
510 # Neither patches nor recipe were updated
511 logger.info('No patches need updating')
410 finally: 512 finally:
411 shutil.rmtree(tempdir) 513 shutil.rmtree(tempdir)
412 514
413 # Get updated patches from source tree 515 else:
414 tempdir = tempfile.mkdtemp(prefix='devtool') 516 logger.error('update_recipe: invalid mode %s' % mode)
415 try: 517 return 1
416 GitApplyTree.extractPatches(srctree, update_rev, tempdir)
417
418 # Match up and replace existing patches with corresponding new patches
419 updatepatches = False
420 updaterecipe = False
421 newpatches = os.listdir(tempdir)
422 for patch in existing_patches:
423 patchfile = os.path.basename(patch)
424 if patchfile in newpatches:
425 logger.info('Updating patch %s' % patchfile)
426 shutil.move(os.path.join(tempdir, patchfile), patch)
427 newpatches.remove(patchfile)
428 updatepatches = True
429 srcuri = (rd.getVar('SRC_URI', False) or '').split()
430 if newpatches:
431 # Add any patches left over
432 patchdir = os.path.join(os.path.dirname(recipefile), rd.getVar('BPN', True))
433 bb.utils.mkdirhier(patchdir)
434 for patchfile in newpatches:
435 logger.info('Adding new patch %s' % patchfile)
436 shutil.move(os.path.join(tempdir, patchfile), os.path.join(patchdir, patchfile))
437 srcuri.append('file://%s' % patchfile)
438 updaterecipe = True
439 if removepatches:
440 # Remove any patches that we don't need
441 for patch in removepatches:
442 patchfile = os.path.basename(patch)
443 for i in xrange(len(srcuri)):
444 if srcuri[i].startswith('file://') and os.path.basename(srcuri[i]).split(';')[0] == patchfile:
445 logger.info('Removing patch %s' % patchfile)
446 srcuri.pop(i)
447 # FIXME "git rm" here would be nice if the file in question is tracked
448 # 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
449 os.remove(patch)
450 updaterecipe = True
451 break
452 if updaterecipe:
453 logger.info('Updating recipe %s' % os.path.basename(recipefile))
454 oe.recipeutils.patch_recipe(rd, recipefile, {'SRC_URI': ' '.join(srcuri)})
455 elif not updatepatches:
456 # Neither patches nor recipe were updated
457 logger.info('No patches need updating')
458 finally:
459 shutil.rmtree(tempdir)
460 518
461 return 0 519 return 0
462 520
@@ -539,9 +597,9 @@ def register_commands(subparsers, context):
539 parser_add.set_defaults(func=extract) 597 parser_add.set_defaults(func=extract)
540 598
541 parser_add = subparsers.add_parser('update-recipe', help='Apply changes from external source tree to recipe', 599 parser_add = subparsers.add_parser('update-recipe', help='Apply changes from external source tree to recipe',
542 description='Applies changes from external source tree to a recipe (updating/adding/removing patches as necessary)', 600 description='Applies changes from external source tree to a recipe (updating/adding/removing patches as necessary, or by updating SRCREV)')
543 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
544 parser_add.add_argument('recipename', help='Name of recipe to update') 601 parser_add.add_argument('recipename', help='Name of recipe to update')
602 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')
545 parser_add.add_argument('--initial-rev', help='Starting revision for patches') 603 parser_add.add_argument('--initial-rev', help='Starting revision for patches')
546 parser_add.add_argument('--no-remove', '-n', action="store_true", help='Don\'t remove patches, only add or update') 604 parser_add.add_argument('--no-remove', '-n', action="store_true", help='Don\'t remove patches, only add or update')
547 parser_add.set_defaults(func=update_recipe) 605 parser_add.set_defaults(func=update_recipe)