diff options
-rw-r--r-- | meta/lib/oeqa/selftest/devtool.py | 171 | ||||
-rw-r--r-- | scripts/lib/devtool/standard.py | 148 |
2 files changed, 278 insertions, 41 deletions
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/devtool.py index ad10af5826..4e22e1dfe4 100644 --- a/meta/lib/oeqa/selftest/devtool.py +++ b/meta/lib/oeqa/selftest/devtool.py | |||
@@ -524,6 +524,177 @@ class DevtoolTests(DevtoolBase): | |||
524 | break | 524 | break |
525 | self.assertTrue(matched, 'Unexpected diff remove line: %s' % line) | 525 | self.assertTrue(matched, 'Unexpected diff remove line: %s' % line) |
526 | 526 | ||
527 | def test_devtool_update_recipe_append(self): | ||
528 | # Check preconditions | ||
529 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
530 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
531 | testrecipe = 'mdadm' | ||
532 | recipefile = get_bb_var('FILE', testrecipe) | ||
533 | src_uri = get_bb_var('SRC_URI', testrecipe) | ||
534 | self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe) | ||
535 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
536 | self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe) | ||
537 | # First, modify a recipe | ||
538 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
539 | tempsrcdir = os.path.join(tempdir, 'source') | ||
540 | templayerdir = os.path.join(tempdir, 'layer') | ||
541 | self.track_for_cleanup(tempdir) | ||
542 | self.track_for_cleanup(workspacedir) | ||
543 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
544 | # (don't bother with cleaning the recipe on teardown, we won't be building it) | ||
545 | result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir)) | ||
546 | # Check git repo | ||
547 | self.assertTrue(os.path.isdir(os.path.join(tempsrcdir, '.git')), 'git repository for external source tree not found') | ||
548 | result = runCmd('git status --porcelain', cwd=tempsrcdir) | ||
549 | self.assertEqual(result.output.strip(), "", 'Created git repo is not clean') | ||
550 | result = runCmd('git symbolic-ref HEAD', cwd=tempsrcdir) | ||
551 | self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo') | ||
552 | # Add a commit | ||
553 | result = runCmd("sed 's!\\(#define VERSION\\W*\"[^\"]*\\)\"!\\1-custom\"!' -i ReadMe.c", cwd=tempsrcdir) | ||
554 | result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir) | ||
555 | self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (os.path.dirname(recipefile), testrecipe)) | ||
556 | # Create a temporary layer and add it to bblayers.conf | ||
557 | self._create_temp_layer(templayerdir, True, 'selftestupdaterecipe') | ||
558 | # Create the bbappend | ||
559 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
560 | self.assertNotIn('WARNING:', result.output) | ||
561 | # Check recipe is still clean | ||
562 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
563 | self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe) | ||
564 | # Check bbappend was created | ||
565 | splitpath = os.path.dirname(recipefile).split(os.sep) | ||
566 | appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1]) | ||
567 | bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir) | ||
568 | patchfile = os.path.join(appenddir, testrecipe, '0001-Add-our-custom-version.patch') | ||
569 | self.assertTrue(os.path.exists(patchfile), 'Patch file not created') | ||
570 | |||
571 | # Check bbappend contents | ||
572 | expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', | ||
573 | '\n', | ||
574 | 'SRC_URI += "file://0001-Add-our-custom-version.patch"\n', | ||
575 | '\n'] | ||
576 | with open(bbappendfile, 'r') as f: | ||
577 | self.assertEqual(expectedlines, f.readlines()) | ||
578 | |||
579 | # Check we can run it again and bbappend isn't modified | ||
580 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
581 | with open(bbappendfile, 'r') as f: | ||
582 | self.assertEqual(expectedlines, f.readlines()) | ||
583 | # Drop new commit and check patch gets deleted | ||
584 | result = runCmd('git reset HEAD^', cwd=tempsrcdir) | ||
585 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
586 | self.assertFalse(os.path.exists(patchfile), 'Patch file not deleted') | ||
587 | expectedlines2 = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', | ||
588 | '\n'] | ||
589 | with open(bbappendfile, 'r') as f: | ||
590 | self.assertEqual(expectedlines2, f.readlines()) | ||
591 | # Put commit back and check we can run it if layer isn't in bblayers.conf | ||
592 | os.remove(bbappendfile) | ||
593 | result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir) | ||
594 | result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir) | ||
595 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
596 | self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output) | ||
597 | self.assertTrue(os.path.exists(patchfile), 'Patch file not created (with disabled layer)') | ||
598 | with open(bbappendfile, 'r') as f: | ||
599 | self.assertEqual(expectedlines, f.readlines()) | ||
600 | # Deleting isn't expected to work under these circumstances | ||
601 | |||
602 | def test_devtool_update_recipe_append_git(self): | ||
603 | # Check preconditions | ||
604 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
605 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
606 | testrecipe = 'mtd-utils' | ||
607 | recipefile = get_bb_var('FILE', testrecipe) | ||
608 | src_uri = get_bb_var('SRC_URI', testrecipe) | ||
609 | self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe) | ||
610 | for entry in src_uri.split(): | ||
611 | if entry.startswith('git://'): | ||
612 | git_uri = entry | ||
613 | break | ||
614 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
615 | self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe) | ||
616 | # First, modify a recipe | ||
617 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
618 | tempsrcdir = os.path.join(tempdir, 'source') | ||
619 | templayerdir = os.path.join(tempdir, 'layer') | ||
620 | self.track_for_cleanup(tempdir) | ||
621 | self.track_for_cleanup(workspacedir) | ||
622 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
623 | # (don't bother with cleaning the recipe on teardown, we won't be building it) | ||
624 | result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir)) | ||
625 | # Check git repo | ||
626 | self.assertTrue(os.path.isdir(os.path.join(tempsrcdir, '.git')), 'git repository for external source tree not found') | ||
627 | result = runCmd('git status --porcelain', cwd=tempsrcdir) | ||
628 | self.assertEqual(result.output.strip(), "", 'Created git repo is not clean') | ||
629 | result = runCmd('git symbolic-ref HEAD', cwd=tempsrcdir) | ||
630 | self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo') | ||
631 | # Add a commit | ||
632 | result = runCmd('echo "# Additional line" >> Makefile', cwd=tempsrcdir) | ||
633 | result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir) | ||
634 | self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (os.path.dirname(recipefile), testrecipe)) | ||
635 | # Create a temporary layer | ||
636 | os.makedirs(os.path.join(templayerdir, 'conf')) | ||
637 | with open(os.path.join(templayerdir, 'conf', 'layer.conf'), 'w') as f: | ||
638 | f.write('BBPATH .= ":${LAYERDIR}"\n') | ||
639 | f.write('BBFILES += "${LAYERDIR}/recipes-*/*/*.bbappend"\n') | ||
640 | f.write('BBFILE_COLLECTIONS += "oeselftesttemplayer"\n') | ||
641 | f.write('BBFILE_PATTERN_oeselftesttemplayer = "^${LAYERDIR}/"\n') | ||
642 | f.write('BBFILE_PRIORITY_oeselftesttemplayer = "999"\n') | ||
643 | f.write('BBFILE_PATTERN_IGNORE_EMPTY_oeselftesttemplayer = "1"\n') | ||
644 | self.add_command_to_tearDown('bitbake-layers remove-layer %s || true' % templayerdir) | ||
645 | result = runCmd('bitbake-layers add-layer %s' % templayerdir, cwd=self.builddir) | ||
646 | # Create the bbappend | ||
647 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
648 | self.assertNotIn('WARNING:', result.output) | ||
649 | # Check recipe is still clean | ||
650 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
651 | self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe) | ||
652 | # Check bbappend was created | ||
653 | splitpath = os.path.dirname(recipefile).split(os.sep) | ||
654 | appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1]) | ||
655 | bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir) | ||
656 | self.assertFalse(os.path.exists(os.path.join(appenddir, testrecipe)), 'Patch directory should not be created') | ||
657 | |||
658 | # Check bbappend contents | ||
659 | result = runCmd('git rev-parse HEAD', cwd=tempsrcdir) | ||
660 | expectedlines = ['SRCREV = "%s"\n' % result.output, | ||
661 | '\n', | ||
662 | 'SRC_URI = "%s"\n' % git_uri, | ||
663 | '\n'] | ||
664 | with open(bbappendfile, 'r') as f: | ||
665 | self.assertEqual(expectedlines, f.readlines()) | ||
666 | |||
667 | # Check we can run it again and bbappend isn't modified | ||
668 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
669 | with open(bbappendfile, 'r') as f: | ||
670 | self.assertEqual(expectedlines, f.readlines()) | ||
671 | # Drop new commit and check SRCREV changes | ||
672 | result = runCmd('git reset HEAD^', cwd=tempsrcdir) | ||
673 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
674 | self.assertFalse(os.path.exists(os.path.join(appenddir, testrecipe)), 'Patch directory should not be created') | ||
675 | result = runCmd('git rev-parse HEAD', cwd=tempsrcdir) | ||
676 | expectedlines = ['SRCREV = "%s"\n' % result.output, | ||
677 | '\n', | ||
678 | 'SRC_URI = "%s"\n' % git_uri, | ||
679 | '\n'] | ||
680 | with open(bbappendfile, 'r') as f: | ||
681 | self.assertEqual(expectedlines, f.readlines()) | ||
682 | # Put commit back and check we can run it if layer isn't in bblayers.conf | ||
683 | os.remove(bbappendfile) | ||
684 | result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir) | ||
685 | result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir) | ||
686 | result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) | ||
687 | self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output) | ||
688 | self.assertFalse(os.path.exists(os.path.join(appenddir, testrecipe)), 'Patch directory should not be created') | ||
689 | result = runCmd('git rev-parse HEAD', cwd=tempsrcdir) | ||
690 | expectedlines = ['SRCREV = "%s"\n' % result.output, | ||
691 | '\n', | ||
692 | 'SRC_URI = "%s"\n' % git_uri, | ||
693 | '\n'] | ||
694 | with open(bbappendfile, 'r') as f: | ||
695 | self.assertEqual(expectedlines, f.readlines()) | ||
696 | # Deleting isn't expected to work under these circumstances | ||
697 | |||
527 | def test_devtool_extract(self): | 698 | def test_devtool_extract(self): |
528 | # Check preconditions | 699 | # Check preconditions |
529 | workspacedir = os.path.join(self.builddir, 'workspace') | 700 | workspacedir = os.path.join(self.builddir, 'workspace') |
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 | ||