summaryrefslogtreecommitdiffstats
path: root/scripts/lib
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib')
-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)