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 | ||