diff options
Diffstat (limited to 'scripts/lib')
| -rw-r--r-- | scripts/lib/devtool/standard.py | 148 |
1 files changed, 107 insertions, 41 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py index 122121aedb..c5b32d81db 100644 --- a/scripts/lib/devtool/standard.py +++ b/scripts/lib/devtool/standard.py | |||
| @@ -24,6 +24,7 @@ import tempfile | |||
| 24 | import logging | 24 | import logging |
| 25 | import argparse | 25 | import argparse |
| 26 | import scriptutils | 26 | import scriptutils |
| 27 | import errno | ||
| 27 | from devtool import exec_build_env_command, setup_tinfoil | 28 | from devtool import exec_build_env_command, setup_tinfoil |
| 28 | 29 | ||
| 29 | logger = logging.getLogger('devtool') | 30 | logger = logging.getLogger('devtool') |
| @@ -510,6 +511,14 @@ def update_recipe(args, config, basepath, workspace): | |||
| 510 | logger.error("no recipe named %s in your workspace" % args.recipename) | 511 | logger.error("no recipe named %s in your workspace" % args.recipename) |
| 511 | return -1 | 512 | return -1 |
| 512 | 513 | ||
| 514 | if args.append: | ||
| 515 | if not os.path.exists(args.append): | ||
| 516 | logger.error('bbappend destination layer directory "%s" does not exist' % args.append) | ||
| 517 | return 2 | ||
| 518 | if not os.path.exists(os.path.join(args.append, 'conf', 'layer.conf')): | ||
| 519 | logger.error('conf/layer.conf not found in bbappend destination layer "%s"' % args.append) | ||
| 520 | return 2 | ||
| 521 | |||
| 513 | tinfoil = setup_tinfoil() | 522 | tinfoil = setup_tinfoil() |
| 514 | import bb | 523 | import bb |
| 515 | from oe.patch import GitApplyTree | 524 | from oe.patch import GitApplyTree |
| @@ -535,22 +544,19 @@ def update_recipe(args, config, basepath, workspace): | |||
| 535 | else: | 544 | else: |
| 536 | mode = args.mode | 545 | mode = args.mode |
| 537 | 546 | ||
| 538 | def remove_patches(srcuri, patchlist): | 547 | def remove_patch_entries(srcuri, patchlist): |
| 539 | """Remove patches""" | 548 | """Remove patch entries from SRC_URI""" |
| 540 | updated = False | 549 | remaining = patchlist[:] |
| 550 | entries = [] | ||
| 541 | for patch in patchlist: | 551 | for patch in patchlist: |
| 542 | patchfile = os.path.basename(patch) | 552 | patchfile = os.path.basename(patch) |
| 543 | for i in xrange(len(srcuri)): | 553 | for i in xrange(len(srcuri)): |
| 544 | if srcuri[i].startswith('file://') and os.path.basename(srcuri[i]).split(';')[0] == patchfile: | 554 | if srcuri[i].startswith('file://') and os.path.basename(srcuri[i].split(';')[0]) == patchfile: |
| 545 | logger.info('Removing patch %s' % patchfile) | 555 | entries.append(srcuri[i]) |
| 556 | remaining.remove(patch) | ||
| 546 | srcuri.pop(i) | 557 | srcuri.pop(i) |
| 547 | # FIXME "git rm" here would be nice if the file in question is tracked | ||
| 548 | # 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 | ||
| 549 | if patch.startswith(os.path.dirname(recipefile)): | ||
| 550 | os.remove(patch) | ||
| 551 | updated = True | ||
| 552 | break | 558 | break |
| 553 | return updated | 559 | return entries, remaining |
| 554 | 560 | ||
| 555 | srctree = workspace[args.recipename] | 561 | srctree = workspace[args.recipename] |
| 556 | 562 | ||
| @@ -565,8 +571,11 @@ def update_recipe(args, config, basepath, workspace): | |||
| 565 | logger.error('Invalid hash returned by git: %s' % stdout) | 571 | logger.error('Invalid hash returned by git: %s' % stdout) |
| 566 | return 1 | 572 | return 1 |
| 567 | 573 | ||
| 574 | removepatches = [] | ||
| 575 | destpath = None | ||
| 568 | if mode == 'srcrev': | 576 | if mode == 'srcrev': |
| 569 | logger.info('Updating SRCREV in recipe %s' % os.path.basename(recipefile)) | 577 | logger.info('Updating SRCREV in recipe %s' % os.path.basename(recipefile)) |
| 578 | removevalues = None | ||
| 570 | patchfields = {} | 579 | patchfields = {} |
| 571 | patchfields['SRCREV'] = srcrev | 580 | patchfields['SRCREV'] = srcrev |
| 572 | if not args.no_remove: | 581 | if not args.no_remove: |
| @@ -575,7 +584,6 @@ def update_recipe(args, config, basepath, workspace): | |||
| 575 | 584 | ||
| 576 | old_srcrev = (rd.getVar('SRCREV', False) or '') | 585 | old_srcrev = (rd.getVar('SRCREV', False) or '') |
| 577 | tempdir = tempfile.mkdtemp(prefix='devtool') | 586 | tempdir = tempfile.mkdtemp(prefix='devtool') |
| 578 | removepatches = [] | ||
| 579 | try: | 587 | try: |
| 580 | GitApplyTree.extractPatches(srctree, old_srcrev, tempdir) | 588 | GitApplyTree.extractPatches(srctree, old_srcrev, tempdir) |
| 581 | newpatches = os.listdir(tempdir) | 589 | newpatches = os.listdir(tempdir) |
| @@ -587,10 +595,14 @@ def update_recipe(args, config, basepath, workspace): | |||
| 587 | shutil.rmtree(tempdir) | 595 | shutil.rmtree(tempdir) |
| 588 | if removepatches: | 596 | if removepatches: |
| 589 | srcuri = (rd.getVar('SRC_URI', False) or '').split() | 597 | srcuri = (rd.getVar('SRC_URI', False) or '').split() |
| 590 | if remove_patches(srcuri, removepatches): | 598 | removedentries, _ = remove_patch_entries(srcuri, removepatches) |
| 599 | if removedentries: | ||
| 591 | patchfields['SRC_URI'] = ' '.join(srcuri) | 600 | patchfields['SRC_URI'] = ' '.join(srcuri) |
| 592 | 601 | ||
| 593 | oe.recipeutils.patch_recipe(tinfoil.config_data, recipefile, patchfields) | 602 | if args.append: |
| 603 | (appendfile, destpath) = oe.recipeutils.bbappend_recipe(rd, args.append, None, wildcardver=args.wildcard_version, extralines=patchfields) | ||
| 604 | else: | ||
| 605 | oe.recipeutils.patch_recipe(tinfoil.config_data, recipefile, patchfields) | ||
| 594 | 606 | ||
| 595 | if not 'git://' in orig_src_uri: | 607 | if not 'git://' in orig_src_uri: |
| 596 | logger.info('You will need to update SRC_URI within the recipe to point to a git repository where you have pushed your changes') | 608 | logger.info('You will need to update SRC_URI within the recipe to point to a git repository where you have pushed your changes') |
| @@ -628,6 +640,7 @@ def update_recipe(args, config, basepath, workspace): | |||
| 628 | existing_patches = oe.recipeutils.get_recipe_patches(rd) | 640 | existing_patches = oe.recipeutils.get_recipe_patches(rd) |
| 629 | 641 | ||
| 630 | removepatches = [] | 642 | removepatches = [] |
| 643 | seqpatch_re = re.compile('^[0-9]{4}-') | ||
| 631 | if not args.no_remove: | 644 | if not args.no_remove: |
| 632 | # Get all patches from source tree and check if any should be removed | 645 | # Get all patches from source tree and check if any should be removed |
| 633 | tempdir = tempfile.mkdtemp(prefix='devtool') | 646 | tempdir = tempfile.mkdtemp(prefix='devtool') |
| @@ -635,8 +648,18 @@ def update_recipe(args, config, basepath, workspace): | |||
| 635 | GitApplyTree.extractPatches(srctree, initial_rev, tempdir) | 648 | GitApplyTree.extractPatches(srctree, initial_rev, tempdir) |
| 636 | newpatches = os.listdir(tempdir) | 649 | newpatches = os.listdir(tempdir) |
| 637 | for patch in existing_patches: | 650 | for patch in existing_patches: |
| 651 | # If it's a git sequence named patch, the numbers might not match up | ||
| 652 | # since we are starting from a different revision | ||
| 653 | # This does assume that people are using unique shortlog values, but | ||
| 654 | # they ought to be anyway... | ||
| 638 | patchfile = os.path.basename(patch) | 655 | patchfile = os.path.basename(patch) |
| 639 | if patchfile not in newpatches: | 656 | if seqpatch_re.search(patchfile): |
| 657 | for newpatch in newpatches: | ||
| 658 | if seqpatch_re.search(newpatch) and patchfile[5:] == newpatch[5:]: | ||
| 659 | break | ||
| 660 | else: | ||
| 661 | removepatches.append(patch) | ||
| 662 | elif patchfile not in newpatches: | ||
| 640 | removepatches.append(patch) | 663 | removepatches.append(patch) |
| 641 | finally: | 664 | finally: |
| 642 | shutil.rmtree(tempdir) | 665 | shutil.rmtree(tempdir) |
| @@ -650,33 +673,56 @@ def update_recipe(args, config, basepath, workspace): | |||
| 650 | updatepatches = False | 673 | updatepatches = False |
| 651 | updaterecipe = False | 674 | updaterecipe = False |
| 652 | newpatches = os.listdir(tempdir) | 675 | newpatches = os.listdir(tempdir) |
| 653 | for patch in existing_patches: | 676 | if args.append: |
| 654 | patchfile = os.path.basename(patch) | 677 | patchfiles = {} |
| 655 | if patchfile in newpatches: | 678 | for patch in existing_patches: |
| 656 | logger.info('Updating patch %s' % patchfile) | 679 | patchfile = os.path.basename(patch) |
| 657 | shutil.move(os.path.join(tempdir, patchfile), patch) | 680 | if patchfile in newpatches: |
| 658 | newpatches.remove(patchfile) | 681 | patchfiles[os.path.join(tempdir, patchfile)] = patchfile |
| 659 | updatepatches = True | 682 | newpatches.remove(patchfile) |
| 660 | srcuri = (rd.getVar('SRC_URI', False) or '').split() | ||
| 661 | if newpatches: | ||
| 662 | # Add any patches left over | ||
| 663 | patchdir = os.path.join(os.path.dirname(recipefile), rd.getVar('BPN', True)) | ||
| 664 | bb.utils.mkdirhier(patchdir) | ||
| 665 | for patchfile in newpatches: | 683 | for patchfile in newpatches: |
| 666 | logger.info('Adding new patch %s' % patchfile) | 684 | patchfiles[os.path.join(tempdir, patchfile)] = None |
| 667 | shutil.move(os.path.join(tempdir, patchfile), os.path.join(patchdir, patchfile)) | 685 | |
| 668 | srcuri.append('file://%s' % patchfile) | 686 | if patchfiles or removepatches: |
| 669 | updaterecipe = True | 687 | removevalues = None |
| 670 | if removepatches: | 688 | if removepatches: |
| 671 | if remove_patches(srcuri, removepatches): | 689 | srcuri = (rd.getVar('SRC_URI', False) or '').split() |
| 672 | updaterecipe = True | 690 | removedentries, remaining = remove_patch_entries(srcuri, removepatches) |
| 673 | if updaterecipe: | 691 | if removedentries or remaining: |
| 674 | logger.info('Updating recipe %s' % os.path.basename(recipefile)) | 692 | removevalues = {'SRC_URI': removedentries + ['file://' + os.path.basename(item) for item in remaining]} |
| 675 | oe.recipeutils.patch_recipe(tinfoil.config_data, | 693 | (appendfile, destpath) = oe.recipeutils.bbappend_recipe(rd, args.append, patchfiles, removevalues=removevalues) |
| 676 | recipefile, {'SRC_URI': ' '.join(srcuri)}) | 694 | else: |
| 677 | elif not updatepatches: | 695 | logger.info('No patches needed updating') |
| 678 | # Neither patches nor recipe were updated | 696 | else: |
| 679 | logger.info('No patches need updating') | 697 | for patch in existing_patches: |
| 698 | patchfile = os.path.basename(patch) | ||
| 699 | if patchfile in newpatches: | ||
| 700 | logger.info('Updating patch %s' % patchfile) | ||
| 701 | shutil.move(os.path.join(tempdir, patchfile), patch) | ||
| 702 | newpatches.remove(patchfile) | ||
| 703 | updatepatches = True | ||
| 704 | srcuri = (rd.getVar('SRC_URI', False) or '').split() | ||
| 705 | if newpatches: | ||
| 706 | # Add any patches left over | ||
| 707 | patchdir = os.path.join(os.path.dirname(recipefile), rd.getVar('BPN', True)) | ||
| 708 | bb.utils.mkdirhier(patchdir) | ||
| 709 | for patchfile in newpatches: | ||
| 710 | logger.info('Adding new patch %s' % patchfile) | ||
| 711 | shutil.move(os.path.join(tempdir, patchfile), os.path.join(patchdir, patchfile)) | ||
| 712 | srcuri.append('file://%s' % patchfile) | ||
| 713 | updaterecipe = True | ||
| 714 | if removepatches: | ||
| 715 | removedentries, _ = remove_patch_entries(srcuri, removepatches) | ||
| 716 | if removedentries: | ||
| 717 | updaterecipe = True | ||
| 718 | if updaterecipe: | ||
| 719 | logger.info('Updating recipe %s' % os.path.basename(recipefile)) | ||
| 720 | oe.recipeutils.patch_recipe(tinfoil.config_data, | ||
| 721 | recipefile, {'SRC_URI': ' '.join(srcuri)}) | ||
| 722 | elif not updatepatches: | ||
| 723 | # Neither patches nor recipe were updated | ||
| 724 | logger.info('No patches need updating') | ||
| 725 | |||
| 680 | finally: | 726 | finally: |
| 681 | shutil.rmtree(tempdir) | 727 | shutil.rmtree(tempdir) |
| 682 | 728 | ||
| @@ -684,6 +730,24 @@ def update_recipe(args, config, basepath, workspace): | |||
| 684 | logger.error('update_recipe: invalid mode %s' % mode) | 730 | logger.error('update_recipe: invalid mode %s' % mode) |
| 685 | return 1 | 731 | return 1 |
| 686 | 732 | ||
| 733 | if removepatches: | ||
| 734 | for patchfile in removepatches: | ||
| 735 | if args.append: | ||
| 736 | if not destpath: | ||
| 737 | raise Exception('destpath should be set here') | ||
| 738 | patchfile = os.path.join(destpath, os.path.basename(patchfile)) | ||
| 739 | |||
| 740 | if os.path.exists(patchfile): | ||
| 741 | logger.info('Removing patch %s' % patchfile) | ||
| 742 | # FIXME "git rm" here would be nice if the file in question is tracked | ||
| 743 | # 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 | ||
| 744 | os.remove(patchfile) | ||
| 745 | # Remove directory if empty | ||
| 746 | try: | ||
| 747 | os.rmdir(os.path.dirname(patchfile)) | ||
| 748 | except OSError as ose: | ||
| 749 | if ose.errno != errno.ENOTEMPTY: | ||
| 750 | raise | ||
| 687 | return 0 | 751 | return 0 |
| 688 | 752 | ||
| 689 | 753 | ||
| @@ -797,6 +861,8 @@ def register_commands(subparsers, context): | |||
| 797 | parser_update_recipe.add_argument('recipename', help='Name of recipe to update') | 861 | parser_update_recipe.add_argument('recipename', help='Name of recipe to update') |
| 798 | parser_update_recipe.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') | 862 | parser_update_recipe.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') |
| 799 | parser_update_recipe.add_argument('--initial-rev', help='Starting revision for patches') | 863 | parser_update_recipe.add_argument('--initial-rev', help='Starting revision for patches') |
| 864 | parser_update_recipe.add_argument('--append', '-a', help='Write changes to a bbappend in the specified layer instead of the recipe', metavar='LAYERDIR') | ||
| 865 | parser_update_recipe.add_argument('--wildcard-version', '-w', help='In conjunction with -a/--append, use a wildcard to make the bbappend apply to any recipe version', action='store_true') | ||
| 800 | parser_update_recipe.add_argument('--no-remove', '-n', action="store_true", help='Don\'t remove patches, only add or update') | 866 | parser_update_recipe.add_argument('--no-remove', '-n', action="store_true", help='Don\'t remove patches, only add or update') |
| 801 | parser_update_recipe.set_defaults(func=update_recipe) | 867 | parser_update_recipe.set_defaults(func=update_recipe) |
| 802 | 868 | ||
