diff options
-rw-r--r-- | meta/lib/oeqa/selftest/devtool.py | 71 | ||||
-rw-r--r-- | scripts/lib/devtool/__init__.py | 10 | ||||
-rw-r--r-- | scripts/lib/devtool/standard.py | 314 |
3 files changed, 297 insertions, 98 deletions
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/devtool.py index 92cd0e230d..baa56d6dc1 100644 --- a/meta/lib/oeqa/selftest/devtool.py +++ b/meta/lib/oeqa/selftest/devtool.py | |||
@@ -723,6 +723,77 @@ class DevtoolTests(DevtoolBase): | |||
723 | self.assertEqual(expectedlines, f.readlines()) | 723 | self.assertEqual(expectedlines, f.readlines()) |
724 | # Deleting isn't expected to work under these circumstances | 724 | # Deleting isn't expected to work under these circumstances |
725 | 725 | ||
726 | @testcase(1173) | ||
727 | def test_devtool_update_recipe_local_files(self): | ||
728 | """Check that local source files are copied over instead of patched""" | ||
729 | testrecipe = 'makedevs' | ||
730 | recipefile = get_bb_var('FILE', testrecipe) | ||
731 | # Setup srctree for modifying the recipe | ||
732 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
733 | self.track_for_cleanup(tempdir) | ||
734 | self.track_for_cleanup(self.workspacedir) | ||
735 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
736 | # (don't bother with cleaning the recipe on teardown, we won't be | ||
737 | # building it) | ||
738 | result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) | ||
739 | # Check git repo | ||
740 | self._check_src_repo(tempdir) | ||
741 | # Edit / commit local source | ||
742 | runCmd('echo "/* Foobar */" >> oe-local-files/makedevs.c', cwd=tempdir) | ||
743 | runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir) | ||
744 | runCmd('echo "Bar" > new-file', cwd=tempdir) | ||
745 | runCmd('git add new-file', cwd=tempdir) | ||
746 | runCmd('git commit -m "Add new file"', cwd=tempdir) | ||
747 | self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' % | ||
748 | os.path.dirname(recipefile)) | ||
749 | runCmd('devtool update-recipe %s' % testrecipe) | ||
750 | expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)), | ||
751 | (' M', '.*/makedevs/makedevs.c$'), | ||
752 | ('??', '.*/makedevs/new-local$'), | ||
753 | ('??', '.*/makedevs/0001-Add-new-file.patch$')] | ||
754 | self._check_repo_status(os.path.dirname(recipefile), expected_status) | ||
755 | |||
756 | @testcase(1174) | ||
757 | def test_devtool_update_recipe_local_files_2(self): | ||
758 | """Check local source files support when oe-local-files is in Git""" | ||
759 | testrecipe = 'lzo' | ||
760 | recipefile = get_bb_var('FILE', testrecipe) | ||
761 | # Setup srctree for modifying the recipe | ||
762 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
763 | self.track_for_cleanup(tempdir) | ||
764 | self.track_for_cleanup(self.workspacedir) | ||
765 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
766 | result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) | ||
767 | # Check git repo | ||
768 | self._check_src_repo(tempdir) | ||
769 | # Add oe-local-files to Git | ||
770 | runCmd('rm oe-local-files/.gitignore', cwd=tempdir) | ||
771 | runCmd('git add oe-local-files', cwd=tempdir) | ||
772 | runCmd('git commit -m "Add local sources"', cwd=tempdir) | ||
773 | # Edit / commit local sources | ||
774 | runCmd('echo "# Foobar" >> oe-local-files/acinclude.m4', cwd=tempdir) | ||
775 | runCmd('git commit -am "Edit existing file"', cwd=tempdir) | ||
776 | runCmd('git rm oe-local-files/run-ptest', cwd=tempdir) | ||
777 | runCmd('git commit -m"Remove file"', cwd=tempdir) | ||
778 | runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir) | ||
779 | runCmd('git add oe-local-files/new-local', cwd=tempdir) | ||
780 | runCmd('git commit -m "Add new local file"', cwd=tempdir) | ||
781 | runCmd('echo "Gar" > new-file', cwd=tempdir) | ||
782 | runCmd('git add new-file', cwd=tempdir) | ||
783 | runCmd('git commit -m "Add new file"', cwd=tempdir) | ||
784 | self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' % | ||
785 | os.path.dirname(recipefile)) | ||
786 | # Checkout unmodified file to working copy -> devtool should still pick | ||
787 | # the modified version from HEAD | ||
788 | runCmd('git checkout HEAD^ -- oe-local-files/acinclude.m4', cwd=tempdir) | ||
789 | runCmd('devtool update-recipe %s' % testrecipe) | ||
790 | expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)), | ||
791 | (' M', '.*/acinclude.m4$'), | ||
792 | (' D', '.*/run-ptest$'), | ||
793 | ('??', '.*/new-local$'), | ||
794 | ('??', '.*/0001-Add-new-file.patch$')] | ||
795 | self._check_repo_status(os.path.dirname(recipefile), expected_status) | ||
796 | |||
726 | @testcase(1163) | 797 | @testcase(1163) |
727 | def test_devtool_extract(self): | 798 | def test_devtool_extract(self): |
728 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | 799 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') |
diff --git a/scripts/lib/devtool/__init__.py b/scripts/lib/devtool/__init__.py index 7b1ab1110d..c8c30202b1 100644 --- a/scripts/lib/devtool/__init__.py +++ b/scripts/lib/devtool/__init__.py | |||
@@ -183,11 +183,17 @@ def setup_git_repo(repodir, version, devbranch, basetag='devtool-base'): | |||
183 | if not os.path.exists(os.path.join(repodir, '.git')): | 183 | if not os.path.exists(os.path.join(repodir, '.git')): |
184 | bb.process.run('git init', cwd=repodir) | 184 | bb.process.run('git init', cwd=repodir) |
185 | bb.process.run('git add .', cwd=repodir) | 185 | bb.process.run('git add .', cwd=repodir) |
186 | if version: | 186 | commit_cmd = ['git', 'commit', '-q'] |
187 | stdout, _ = bb.process.run('git status --porcelain', cwd=repodir) | ||
188 | if not stdout: | ||
189 | commit_cmd.append('--allow-empty') | ||
190 | commitmsg = "Initial empty commit with no upstream sources" | ||
191 | elif version: | ||
187 | commitmsg = "Initial commit from upstream at version %s" % version | 192 | commitmsg = "Initial commit from upstream at version %s" % version |
188 | else: | 193 | else: |
189 | commitmsg = "Initial commit from upstream" | 194 | commitmsg = "Initial commit from upstream" |
190 | bb.process.run('git commit -q -m "%s"' % commitmsg, cwd=repodir) | 195 | commit_cmd += ['-m', commitmsg] |
196 | bb.process.run(commit_cmd, cwd=repodir) | ||
191 | 197 | ||
192 | bb.process.run('git checkout -b %s' % devbranch, cwd=repodir) | 198 | bb.process.run('git checkout -b %s' % devbranch, cwd=repodir) |
193 | bb.process.run('git tag -f %s' % basetag, cwd=repodir) | 199 | bb.process.run('git tag -f %s' % basetag, cwd=repodir) |
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py index e4e90a7160..0c67c131a8 100644 --- a/scripts/lib/devtool/standard.py +++ b/scripts/lib/devtool/standard.py | |||
@@ -181,6 +181,36 @@ def _move_file(src, dst): | |||
181 | bb.utils.mkdirhier(dst_d) | 181 | bb.utils.mkdirhier(dst_d) |
182 | shutil.move(src, dst) | 182 | shutil.move(src, dst) |
183 | 183 | ||
184 | def _git_ls_tree(repodir, treeish='HEAD', recursive=False): | ||
185 | """List contents of a git treeish""" | ||
186 | import bb | ||
187 | cmd = ['git', 'ls-tree', '-z', treeish] | ||
188 | if recursive: | ||
189 | cmd.append('-r') | ||
190 | out, _ = bb.process.run(cmd, cwd=repodir) | ||
191 | ret = {} | ||
192 | for line in out.split('\0'): | ||
193 | if line: | ||
194 | split = line.split(None, 4) | ||
195 | ret[split[3]] = split[0:3] | ||
196 | return ret | ||
197 | |||
198 | def _git_exclude_path(srctree, path): | ||
199 | """Return pathspec (list of paths) that excludes certain path""" | ||
200 | # NOTE: "Filtering out" files/paths in this way is not entirely reliable - | ||
201 | # we don't catch files that are deleted, for example. A more reliable way | ||
202 | # to implement this would be to use "negative pathspecs" which were | ||
203 | # introduced in Git v1.9.0. Revisit this when/if the required Git version | ||
204 | # becomes greater than that. | ||
205 | path = os.path.normpath(path) | ||
206 | recurse = True if len(path.split(os.path.sep)) > 1 else False | ||
207 | git_files = _git_ls_tree(srctree, 'HEAD', recurse).keys() | ||
208 | if path in git_files: | ||
209 | git_files.remove(path) | ||
210 | return git_files | ||
211 | else: | ||
212 | return ['.'] | ||
213 | |||
184 | def _ls_tree(directory): | 214 | def _ls_tree(directory): |
185 | """Recursive listing of files in a directory""" | 215 | """Recursive listing of files in a directory""" |
186 | ret = [] | 216 | ret = [] |
@@ -326,10 +356,25 @@ def _extract_source(srctree, keep_temp, devbranch, d): | |||
326 | logger.info('Doing kernel checkout...') | 356 | logger.info('Doing kernel checkout...') |
327 | task_executor.exec_func('do_kernel_checkout', False) | 357 | task_executor.exec_func('do_kernel_checkout', False) |
328 | srcsubdir = crd.getVar('S', True) | 358 | srcsubdir = crd.getVar('S', True) |
359 | |||
360 | # Move local source files into separate subdir | ||
361 | recipe_patches = [os.path.basename(patch) for patch in | ||
362 | oe.recipeutils.get_recipe_patches(crd)] | ||
363 | local_files = oe.recipeutils.get_recipe_local_files(crd) | ||
364 | local_files = [fname for fname in local_files if | ||
365 | os.path.exists(os.path.join(workdir, fname))] | ||
366 | if local_files: | ||
367 | for fname in local_files: | ||
368 | _move_file(os.path.join(workdir, fname), | ||
369 | os.path.join(tempdir, 'oe-local-files', fname)) | ||
370 | with open(os.path.join(tempdir, 'oe-local-files', '.gitignore'), | ||
371 | 'w') as f: | ||
372 | f.write('# Ignore local files, by default. Remove this file ' | ||
373 | 'if you want to commit the directory to Git\n*\n') | ||
374 | |||
329 | if srcsubdir == workdir: | 375 | if srcsubdir == workdir: |
330 | # Find non-patch sources that were "unpacked" to srctree directory | 376 | # Find non-patch non-local sources that were "unpacked" to srctree |
331 | recipe_patches = [os.path.basename(patch) for patch in | 377 | # directory |
332 | oe.recipeutils.get_recipe_patches(crd)] | ||
333 | src_files = [fname for fname in _ls_tree(workdir) if | 378 | src_files = [fname for fname in _ls_tree(workdir) if |
334 | os.path.basename(fname) not in recipe_patches] | 379 | os.path.basename(fname) not in recipe_patches] |
335 | # Force separate S so that patch files can be left out from srctree | 380 | # Force separate S so that patch files can be left out from srctree |
@@ -352,12 +397,12 @@ def _extract_source(srctree, keep_temp, devbranch, d): | |||
352 | haspatches = True | 397 | haspatches = True |
353 | else: | 398 | else: |
354 | os.rmdir(patchdir) | 399 | os.rmdir(patchdir) |
355 | 400 | # Make sure that srcsubdir exists | |
401 | bb.utils.mkdirhier(srcsubdir) | ||
356 | if not os.path.exists(srcsubdir) or not os.listdir(srcsubdir): | 402 | if not os.path.exists(srcsubdir) or not os.listdir(srcsubdir): |
357 | raise DevtoolError("no source unpacked to S, either the %s " | 403 | logger.warning("no source unpacked to S, either the %s recipe " |
358 | "recipe doesn't use any source or the " | 404 | "doesn't use any source or the correct source " |
359 | "correct source directory could not be " | 405 | "directory could not be determined" % pn) |
360 | "determined" % pn) | ||
361 | 406 | ||
362 | setup_git_repo(srcsubdir, crd.getVar('PV', True), devbranch) | 407 | setup_git_repo(srcsubdir, crd.getVar('PV', True), devbranch) |
363 | 408 | ||
@@ -376,6 +421,12 @@ def _extract_source(srctree, keep_temp, devbranch, d): | |||
376 | if haspatches: | 421 | if haspatches: |
377 | bb.process.run('git checkout patches', cwd=srcsubdir) | 422 | bb.process.run('git checkout patches', cwd=srcsubdir) |
378 | 423 | ||
424 | # Move oe-local-files directory to srctree | ||
425 | if os.path.exists(os.path.join(tempdir, 'oe-local-files')): | ||
426 | logger.info('Adding local source files to srctree...') | ||
427 | shutil.move(os.path.join(tempdir, 'oe-local-files'), srcsubdir) | ||
428 | |||
429 | |||
379 | shutil.move(srcsubdir, srctree) | 430 | shutil.move(srcsubdir, srctree) |
380 | finally: | 431 | finally: |
381 | bb.logger.setLevel(origlevel) | 432 | bb.logger.setLevel(origlevel) |
@@ -560,39 +611,40 @@ def _get_patchset_revs(args, srctree, recipe_path): | |||
560 | 611 | ||
561 | return initial_rev, update_rev | 612 | return initial_rev, update_rev |
562 | 613 | ||
563 | def _remove_patch_entries(srcuri, patchlist): | 614 | def _remove_file_entries(srcuri, filelist): |
564 | """Remove patch entries from SRC_URI""" | 615 | """Remove file:// entries from SRC_URI""" |
565 | remaining = patchlist[:] | 616 | remaining = filelist[:] |
566 | entries = [] | 617 | entries = [] |
567 | for patch in patchlist: | 618 | for fname in filelist: |
568 | patchfile = os.path.basename(patch) | 619 | basename = os.path.basename(fname) |
569 | for i in xrange(len(srcuri)): | 620 | for i in xrange(len(srcuri)): |
570 | if srcuri[i].startswith('file://') and os.path.basename(srcuri[i].split(';')[0]) == patchfile: | 621 | if (srcuri[i].startswith('file://') and |
622 | os.path.basename(srcuri[i].split(';')[0]) == basename): | ||
571 | entries.append(srcuri[i]) | 623 | entries.append(srcuri[i]) |
572 | remaining.remove(patch) | 624 | remaining.remove(fname) |
573 | srcuri.pop(i) | 625 | srcuri.pop(i) |
574 | break | 626 | break |
575 | return entries, remaining | 627 | return entries, remaining |
576 | 628 | ||
577 | def _remove_patch_files(args, patches, destpath): | 629 | def _remove_source_files(args, files, destpath): |
578 | """Unlink existing patch files""" | 630 | """Unlink existing patch files""" |
579 | for patchfile in patches: | 631 | for path in files: |
580 | if args.append: | 632 | if args.append: |
581 | if not destpath: | 633 | if not destpath: |
582 | raise Exception('destpath should be set here') | 634 | raise Exception('destpath should be set here') |
583 | patchfile = os.path.join(destpath, os.path.basename(patchfile)) | 635 | path = os.path.join(destpath, os.path.basename(path)) |
584 | 636 | ||
585 | if os.path.exists(patchfile): | 637 | if os.path.exists(path): |
586 | logger.info('Removing patch %s' % patchfile) | 638 | logger.info('Removing file %s' % path) |
587 | # FIXME "git rm" here would be nice if the file in question is | 639 | # FIXME "git rm" here would be nice if the file in question is |
588 | # tracked | 640 | # tracked |
589 | # FIXME there's a chance that this file is referred to by | 641 | # FIXME there's a chance that this file is referred to by |
590 | # another recipe, in which case deleting wouldn't be the | 642 | # another recipe, in which case deleting wouldn't be the |
591 | # right thing to do | 643 | # right thing to do |
592 | os.remove(patchfile) | 644 | os.remove(path) |
593 | # Remove directory if empty | 645 | # Remove directory if empty |
594 | try: | 646 | try: |
595 | os.rmdir(os.path.dirname(patchfile)) | 647 | os.rmdir(os.path.dirname(path)) |
596 | except OSError as ose: | 648 | except OSError as ose: |
597 | if ose.errno != errno.ENOTEMPTY: | 649 | if ose.errno != errno.ENOTEMPTY: |
598 | raise | 650 | raise |
@@ -616,8 +668,9 @@ def _export_patches(srctree, rd, start_rev, destdir): | |||
616 | existing_patches = dict((os.path.basename(path), path) for path in | 668 | existing_patches = dict((os.path.basename(path), path) for path in |
617 | oe.recipeutils.get_recipe_patches(rd)) | 669 | oe.recipeutils.get_recipe_patches(rd)) |
618 | 670 | ||
619 | # Generate patches from Git | 671 | # Generate patches from Git, exclude local files directory |
620 | GitApplyTree.extractPatches(srctree, start_rev, destdir) | 672 | patch_pathspec = _git_exclude_path(srctree, 'oe-local-files') |
673 | GitApplyTree.extractPatches(srctree, start_rev, destdir, patch_pathspec) | ||
621 | 674 | ||
622 | new_patches = sorted(os.listdir(destdir)) | 675 | new_patches = sorted(os.listdir(destdir)) |
623 | for new_patch in new_patches: | 676 | for new_patch in new_patches: |
@@ -642,6 +695,52 @@ def _export_patches(srctree, rd, start_rev, destdir): | |||
642 | return (updated, added, existing_patches) | 695 | return (updated, added, existing_patches) |
643 | 696 | ||
644 | 697 | ||
698 | def _export_local_files(srctree, rd, destdir): | ||
699 | """Copy local files from srctree to given location. | ||
700 | Returns three-tuple of dicts: | ||
701 | 1. updated - files that already exist in SRCURI | ||
702 | 2. added - new files files that don't exist in SRCURI | ||
703 | 3 removed - files that exist in SRCURI but not in exported files | ||
704 | In each dict the key is the 'basepath' of the URI and value is the | ||
705 | absolute path to the existing file in recipe space (if any). | ||
706 | """ | ||
707 | import oe.recipeutils | ||
708 | |||
709 | # Find out local files (SRC_URI files that exist in the "recipe space"). | ||
710 | # Local files that reside in srctree are not included in patch generation. | ||
711 | # Instead they are directly copied over the original source files (in | ||
712 | # recipe space). | ||
713 | existing_files = oe.recipeutils.get_recipe_local_files(rd) | ||
714 | new_set = None | ||
715 | updated = OrderedDict() | ||
716 | added = OrderedDict() | ||
717 | removed = OrderedDict() | ||
718 | git_files = _git_ls_tree(srctree) | ||
719 | if 'oe-local-files' in git_files: | ||
720 | # If tracked by Git, take the files from srctree HEAD. First get | ||
721 | # the tree object of the directory | ||
722 | tmp_index = os.path.join(srctree, '.git', 'index.tmp.devtool') | ||
723 | tree = git_files['oe-local-files'][2] | ||
724 | bb.process.run(['git', 'checkout', tree, '--', '.'], cwd=srctree, | ||
725 | env=dict(os.environ, GIT_WORK_TREE=destdir, | ||
726 | GIT_INDEX_FILE=tmp_index)) | ||
727 | new_set = _git_ls_tree(srctree, tree, True).keys() | ||
728 | elif os.path.isdir(os.path.join(srctree, 'oe-local-files')): | ||
729 | # If not tracked by Git, just copy from working copy | ||
730 | new_set = _ls_tree(os.path.join(srctree, 'oe-local-files')) | ||
731 | bb.process.run(['cp', '-ax', | ||
732 | os.path.join(srctree, 'oe-local-files', '.'), destdir]) | ||
733 | if new_set is not None: | ||
734 | for fname in new_set: | ||
735 | if fname in existing_files: | ||
736 | updated[fname] = existing_files.pop(fname) | ||
737 | elif fname != '.gitignore': | ||
738 | added[fname] = None | ||
739 | |||
740 | removed = existing_files | ||
741 | return (updated, added, removed) | ||
742 | |||
743 | |||
645 | def _update_recipe_srcrev(args, srctree, rd, config_data): | 744 | def _update_recipe_srcrev(args, srctree, rd, config_data): |
646 | """Implement the 'srcrev' mode of update-recipe""" | 745 | """Implement the 'srcrev' mode of update-recipe""" |
647 | import bb | 746 | import bb |
@@ -661,43 +760,63 @@ def _update_recipe_srcrev(args, srctree, rd, config_data): | |||
661 | raise DevtoolError('Invalid hash returned by git: %s' % stdout) | 760 | raise DevtoolError('Invalid hash returned by git: %s' % stdout) |
662 | 761 | ||
663 | destpath = None | 762 | destpath = None |
664 | removepatches = [] | 763 | remove_files = [] |
665 | patchfields = {} | 764 | patchfields = {} |
666 | patchfields['SRCREV'] = srcrev | 765 | patchfields['SRCREV'] = srcrev |
667 | orig_src_uri = rd.getVar('SRC_URI', False) or '' | 766 | orig_src_uri = rd.getVar('SRC_URI', False) or '' |
668 | if not args.no_remove: | 767 | srcuri = orig_src_uri.split() |
669 | # Find list of existing patches in recipe file | 768 | tempdir = tempfile.mkdtemp(prefix='devtool') |
670 | existing_patches = oe.recipeutils.get_recipe_patches(rd) | 769 | update_srcuri = False |
671 | 770 | try: | |
672 | old_srcrev = (rd.getVar('SRCREV', False) or '') | 771 | local_files_dir = tempfile.mkdtemp(dir=tempdir) |
673 | tempdir = tempfile.mkdtemp(prefix='devtool') | 772 | upd_f, new_f, del_f = _export_local_files(srctree, rd, local_files_dir) |
674 | try: | 773 | if not args.no_remove: |
774 | # Find list of existing patches in recipe file | ||
775 | patches_dir = tempfile.mkdtemp(dir=tempdir) | ||
776 | old_srcrev = (rd.getVar('SRCREV', False) or '') | ||
675 | upd_p, new_p, del_p = _export_patches(srctree, rd, old_srcrev, | 777 | upd_p, new_p, del_p = _export_patches(srctree, rd, old_srcrev, |
676 | tempdir) | 778 | patches_dir) |
677 | # Remove "overlapping" patches | ||
678 | removepatches = upd_p.values() | ||
679 | finally: | ||
680 | shutil.rmtree(tempdir) | ||
681 | |||
682 | if removepatches: | ||
683 | srcuri = orig_src_uri.split() | ||
684 | removedentries, _ = _remove_patch_entries(srcuri, removepatches) | ||
685 | if removedentries: | ||
686 | patchfields['SRC_URI'] = ' '.join(srcuri) | ||
687 | 779 | ||
688 | if args.append: | 780 | # Remove deleted local files and "overlapping" patches |
689 | _, destpath = oe.recipeutils.bbappend_recipe( | 781 | remove_files = del_f.values() + upd_p.values() |
690 | rd, args.append, None, wildcardver=args.wildcard_version, | 782 | if remove_files: |
691 | extralines=patchfields) | 783 | removedentries = _remove_file_entries(srcuri, remove_files)[0] |
692 | else: | 784 | update_srcuri = True |
693 | oe.recipeutils.patch_recipe(rd, recipefile, patchfields) | ||
694 | 785 | ||
786 | if args.append: | ||
787 | files = dict((os.path.join(local_files_dir, key), val) for | ||
788 | key, val in upd_f.items() + new_f.items()) | ||
789 | removevalues = {} | ||
790 | if update_srcuri: | ||
791 | removevalues = {'SRC_URI': removedentries} | ||
792 | patchfields['SRC_URI'] = '\\\n '.join(srcuri) | ||
793 | _, destpath = oe.recipeutils.bbappend_recipe( | ||
794 | rd, args.append, files, wildcardver=args.wildcard_version, | ||
795 | extralines=patchfields, removevalues=removevalues) | ||
796 | else: | ||
797 | files_dir = os.path.join(os.path.dirname(recipefile), | ||
798 | rd.getVar('BPN', True)) | ||
799 | for basepath, path in upd_f.iteritems(): | ||
800 | logger.info('Updating file %s' % basepath) | ||
801 | _move_file(os.path.join(local_files_dir, basepath), path) | ||
802 | update_srcuri= True | ||
803 | for basepath, path in new_f.iteritems(): | ||
804 | logger.info('Adding new file %s' % basepath) | ||
805 | _move_file(os.path.join(local_files_dir, basepath), | ||
806 | os.path.join(files_dir, basepath)) | ||
807 | srcuri.append('file://%s' % basepath) | ||
808 | update_srcuri = True | ||
809 | if update_srcuri: | ||
810 | patchfields['SRC_URI'] = ' '.join(srcuri) | ||
811 | oe.recipeutils.patch_recipe(rd, recipefile, patchfields) | ||
812 | finally: | ||
813 | shutil.rmtree(tempdir) | ||
695 | if not 'git://' in orig_src_uri: | 814 | if not 'git://' in orig_src_uri: |
696 | logger.info('You will need to update SRC_URI within the recipe to ' | 815 | logger.info('You will need to update SRC_URI within the recipe to ' |
697 | 'point to a git repository where you have pushed your ' | 816 | 'point to a git repository where you have pushed your ' |
698 | 'changes') | 817 | 'changes') |
699 | 818 | ||
700 | _remove_patch_files(args, removepatches, destpath) | 819 | _remove_source_files(args, remove_files, destpath) |
701 | 820 | ||
702 | def _update_recipe_patch(args, config, srctree, rd, config_data): | 821 | def _update_recipe_patch(args, config, srctree, rd, config_data): |
703 | """Implement the 'patch' mode of update-recipe""" | 822 | """Implement the 'patch' mode of update-recipe""" |
@@ -716,83 +835,86 @@ def _update_recipe_patch(args, config, srctree, rd, config_data): | |||
716 | raise DevtoolError('Unable to find initial revision - please specify ' | 835 | raise DevtoolError('Unable to find initial revision - please specify ' |
717 | 'it with --initial-rev') | 836 | 'it with --initial-rev') |
718 | 837 | ||
719 | # Find list of existing patches in recipe file | 838 | tempdir = tempfile.mkdtemp(prefix='devtool') |
720 | existing_patches = oe.recipeutils.get_recipe_patches(rd) | 839 | try: |
840 | local_files_dir = tempfile.mkdtemp(dir=tempdir) | ||
841 | upd_f, new_f, del_f = _export_local_files(srctree, rd, local_files_dir) | ||
721 | 842 | ||
722 | removepatches = [] | 843 | remove_files = [] |
723 | seqpatch_re = re.compile('^([0-9]{4}-)?(.+)') | 844 | if not args.no_remove: |
724 | if not args.no_remove: | ||
725 | # Get all patches from source tree and check if any should be removed | ||
726 | tempdir = tempfile.mkdtemp(prefix='devtool') | ||
727 | try: | ||
728 | # Get all patches from source tree and check if any should be removed | 845 | # Get all patches from source tree and check if any should be removed |
846 | all_patches_dir = tempfile.mkdtemp(dir=tempdir) | ||
729 | upd_p, new_p, del_p = _export_patches(srctree, rd, initial_rev, | 847 | upd_p, new_p, del_p = _export_patches(srctree, rd, initial_rev, |
730 | tempdir) | 848 | all_patches_dir) |
731 | # Remove deleted patches | 849 | # Remove deleted local files and patches |
732 | removepatches = del_p.values() | 850 | remove_files = del_f.values() + del_p.values() |
733 | finally: | ||
734 | shutil.rmtree(tempdir) | ||
735 | 851 | ||
736 | # Get updated patches from source tree | 852 | # Get updated patches from source tree |
737 | tempdir = tempfile.mkdtemp(prefix='devtool') | 853 | patches_dir = tempfile.mkdtemp(dir=tempdir) |
738 | try: | ||
739 | upd_p, new_p, del_p = _export_patches(srctree, rd, update_rev, | 854 | upd_p, new_p, del_p = _export_patches(srctree, rd, update_rev, |
740 | tempdir) | 855 | patches_dir) |
741 | 856 | updatefiles = False | |
742 | # Match up and replace existing patches with corresponding new patches | ||
743 | updatepatches = False | ||
744 | updaterecipe = False | 857 | updaterecipe = False |
745 | destpath = None | 858 | destpath = None |
859 | srcuri = (rd.getVar('SRC_URI', False) or '').split() | ||
746 | if args.append: | 860 | if args.append: |
747 | patchfiles = dict((os.path.join(tempdir, key), val) for | 861 | files = dict((os.path.join(local_files_dir, key), val) for |
748 | key, val in upd_p.items() + new_p.items()) | 862 | key, val in upd_f.items() + new_f.items()) |
749 | 863 | files.update(dict((os.path.join(patches_dir, key), val) for | |
750 | if patchfiles or removepatches: | 864 | key, val in upd_p.items() + new_p.items())) |
865 | if files or remove_files: | ||
751 | removevalues = None | 866 | removevalues = None |
752 | if removepatches: | 867 | if remove_files: |
753 | srcuri = (rd.getVar('SRC_URI', False) or '').split() | 868 | removedentries, remaining = _remove_file_entries( |
754 | removedentries, remaining = _remove_patch_entries( | 869 | srcuri, remove_files) |
755 | srcuri, removepatches) | ||
756 | if removedentries or remaining: | 870 | if removedentries or remaining: |
757 | remaining = ['file://' + os.path.basename(item) for | 871 | remaining = ['file://' + os.path.basename(item) for |
758 | item in remaining] | 872 | item in remaining] |
759 | removevalues = {'SRC_URI': removedentries + remaining} | 873 | removevalues = {'SRC_URI': removedentries + remaining} |
760 | _, destpath = oe.recipeutils.bbappend_recipe( | 874 | _, destpath = oe.recipeutils.bbappend_recipe( |
761 | rd, args.append, patchfiles, | 875 | rd, args.append, files, |
762 | removevalues=removevalues) | 876 | removevalues=removevalues) |
763 | else: | 877 | else: |
764 | logger.info('No patches needed updating') | 878 | logger.info('No patches or local source files needed updating') |
765 | else: | 879 | else: |
880 | # Update existing files | ||
881 | for basepath, path in upd_f.iteritems(): | ||
882 | logger.info('Updating file %s' % basepath) | ||
883 | _move_file(os.path.join(local_files_dir, basepath), path) | ||
884 | updatefiles = True | ||
766 | for basepath, path in upd_p.iteritems(): | 885 | for basepath, path in upd_p.iteritems(): |
767 | logger.info('Updating patch %s' % basepath) | 886 | logger.info('Updating patch %s' % basepath) |
768 | shutil.move(os.path.join(tempdir, basepath), path) | 887 | _move_file(os.path.join(patches_dir, basepath), path) |
769 | updatepatches = True | 888 | updatefiles = True |
770 | srcuri = (rd.getVar('SRC_URI', False) or '').split() | 889 | # Add any new files |
771 | patchdir = os.path.join(os.path.dirname(recipefile), | 890 | files_dir = os.path.join(os.path.dirname(recipefile), |
772 | rd.getVar('BPN', True)) | 891 | rd.getVar('BPN', True)) |
773 | bb.utils.mkdirhier(patchdir) | 892 | for basepath, path in new_f.iteritems(): |
893 | logger.info('Adding new file %s' % basepath) | ||
894 | _move_file(os.path.join(local_files_dir, basepath), | ||
895 | os.path.join(files_dir, basepath)) | ||
896 | srcuri.append('file://%s' % basepath) | ||
897 | updaterecipe = True | ||
774 | for basepath, path in new_p.iteritems(): | 898 | for basepath, path in new_p.iteritems(): |
775 | logger.info('Adding new patch %s' % basepath) | 899 | logger.info('Adding new patch %s' % basepath) |
776 | bb.utils.mkdirhier(patchdir) | 900 | _move_file(os.path.join(patches_dir, basepath), |
777 | shutil.move(os.path.join(tempdir, basepath), | 901 | os.path.join(files_dir, basepath)) |
778 | os.path.join(patchdir, basepath)) | ||
779 | srcuri.append('file://%s' % basepath) | 902 | srcuri.append('file://%s' % basepath) |
780 | updaterecipe = True | 903 | updaterecipe = True |
781 | if removepatches: | 904 | # Update recipe, if needed |
782 | removedentries, _ = _remove_patch_entries(srcuri, removepatches) | 905 | if _remove_file_entries(srcuri, remove_files)[0]: |
783 | if removedentries: | 906 | updaterecipe = True |
784 | updaterecipe = True | ||
785 | if updaterecipe: | 907 | if updaterecipe: |
786 | logger.info('Updating recipe %s' % os.path.basename(recipefile)) | 908 | logger.info('Updating recipe %s' % os.path.basename(recipefile)) |
787 | oe.recipeutils.patch_recipe(rd, recipefile, | 909 | oe.recipeutils.patch_recipe(rd, recipefile, |
788 | {'SRC_URI': ' '.join(srcuri)}) | 910 | {'SRC_URI': ' '.join(srcuri)}) |
789 | elif not updatepatches: | 911 | elif not updatefiles: |
790 | # Neither patches nor recipe were updated | 912 | # Neither patches nor recipe were updated |
791 | logger.info('No patches need updating') | 913 | logger.info('No patches or files need updating') |
792 | finally: | 914 | finally: |
793 | shutil.rmtree(tempdir) | 915 | shutil.rmtree(tempdir) |
794 | 916 | ||
795 | _remove_patch_files(args, removepatches, destpath) | 917 | _remove_source_files(args, remove_files, destpath) |
796 | 918 | ||
797 | def _guess_recipe_update_mode(srctree, rdata): | 919 | def _guess_recipe_update_mode(srctree, rdata): |
798 | """Guess the recipe update mode to use""" | 920 | """Guess the recipe update mode to use""" |