summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/lib/oeqa/selftest/devtool.py60
-rw-r--r--scripts/lib/devtool/build.py2
-rw-r--r--scripts/lib/devtool/standard.py202
3 files changed, 263 insertions, 1 deletions
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/devtool.py
index 71d205c73f..46f5a0b998 100644
--- a/meta/lib/oeqa/selftest/devtool.py
+++ b/meta/lib/oeqa/selftest/devtool.py
@@ -1349,3 +1349,63 @@ class DevtoolTests(DevtoolBase):
1349 files.remove(foundpatch) 1349 files.remove(foundpatch)
1350 if files: 1350 if files:
1351 self.fail('Unexpected file(s) copied next to bbappend: %s' % ', '.join(files)) 1351 self.fail('Unexpected file(s) copied next to bbappend: %s' % ', '.join(files))
1352
1353 def test_devtool_rename(self):
1354 # Check preconditions
1355 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1356 self.track_for_cleanup(self.workspacedir)
1357 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1358
1359 # First run devtool add
1360 # We already have this recipe in OE-Core, but that doesn't matter
1361 recipename = 'i2c-tools'
1362 recipever = '3.1.2'
1363 recipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, recipever))
1364 url = 'http://downloads.yoctoproject.org/mirror/sources/i2c-tools-%s.tar.bz2' % recipever
1365 def add_recipe():
1366 result = runCmd('devtool add %s' % url)
1367 self.assertTrue(os.path.exists(recipefile), 'Expected recipe file not created')
1368 self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'sources', recipename)), 'Source directory not created')
1369 checkvars = {}
1370 checkvars['S'] = None
1371 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
1372 self._test_recipe_contents(recipefile, checkvars, [])
1373 add_recipe()
1374 # Now rename it - change both name and version
1375 newrecipename = 'mynewrecipe'
1376 newrecipever = '456'
1377 newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, newrecipever))
1378 result = runCmd('devtool rename %s %s -V %s' % (recipename, newrecipename, newrecipever))
1379 self.assertTrue(os.path.exists(newrecipefile), 'Recipe file not renamed')
1380 self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipename)), 'Old recipe directory still exists')
1381 newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename)
1382 self.assertTrue(os.path.exists(newsrctree), 'Source directory not renamed')
1383 checkvars = {}
1384 checkvars['S'] = '${WORKDIR}/%s-%s' % (recipename, recipever)
1385 checkvars['SRC_URI'] = url
1386 self._test_recipe_contents(newrecipefile, checkvars, [])
1387 # Try again - change just name this time
1388 result = runCmd('devtool reset -n %s' % newrecipename)
1389 shutil.rmtree(newsrctree)
1390 add_recipe()
1391 newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, recipever))
1392 result = runCmd('devtool rename %s %s' % (recipename, newrecipename))
1393 self.assertTrue(os.path.exists(newrecipefile), 'Recipe file not renamed')
1394 self.assertFalse(os.path.exists(os.path.join(self.workspacedir, 'recipes', recipename)), 'Old recipe directory still exists')
1395 self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'sources', newrecipename)), 'Source directory not renamed')
1396 checkvars = {}
1397 checkvars['S'] = '${WORKDIR}/%s-${PV}' % recipename
1398 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
1399 self._test_recipe_contents(newrecipefile, checkvars, [])
1400 # Try again - change just version this time
1401 result = runCmd('devtool reset -n %s' % newrecipename)
1402 shutil.rmtree(newsrctree)
1403 add_recipe()
1404 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, newrecipever))
1405 result = runCmd('devtool rename %s -V %s' % (recipename, newrecipever))
1406 self.assertTrue(os.path.exists(newrecipefile), 'Recipe file not renamed')
1407 self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'sources', recipename)), 'Source directory no longer exists')
1408 checkvars = {}
1409 checkvars['S'] = '${WORKDIR}/${BPN}-%s' % recipever
1410 checkvars['SRC_URI'] = url
1411 self._test_recipe_contents(newrecipefile, checkvars, [])
diff --git a/scripts/lib/devtool/build.py b/scripts/lib/devtool/build.py
index 6be549dd59..252379e9b2 100644
--- a/scripts/lib/devtool/build.py
+++ b/scripts/lib/devtool/build.py
@@ -80,7 +80,7 @@ def register_commands(subparsers, context):
80 """Register devtool subcommands from this plugin""" 80 """Register devtool subcommands from this plugin"""
81 parser_build = subparsers.add_parser('build', help='Build a recipe', 81 parser_build = subparsers.add_parser('build', help='Build a recipe',
82 description='Builds the specified recipe using bitbake (up to and including %s)' % ', '.join(_get_build_tasks(context.config)), 82 description='Builds the specified recipe using bitbake (up to and including %s)' % ', '.join(_get_build_tasks(context.config)),
83 group='working') 83 group='working', order=50)
84 parser_build.add_argument('recipename', help='Recipe to build') 84 parser_build.add_argument('recipename', help='Recipe to build')
85 parser_build.add_argument('-s', '--disable-parallel-make', action="store_true", help='Disable make parallelism') 85 parser_build.add_argument('-s', '--disable-parallel-make', action="store_true", help='Disable make parallelism')
86 parser_build.set_defaults(func=build) 86 parser_build.set_defaults(func=build)
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index c15bfef9d8..4523048b38 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -852,6 +852,199 @@ def modify(args, config, basepath, workspace):
852 852
853 return 0 853 return 0
854 854
855
856def rename(args, config, basepath, workspace):
857 """Entry point for the devtool 'rename' subcommand"""
858 import bb
859 import oe.recipeutils
860
861 check_workspace_recipe(workspace, args.recipename)
862
863 if not (args.newname or args.version):
864 raise DevtoolError('You must specify a new name, a version with -V/--version, or both')
865
866 recipefile = workspace[args.recipename]['recipefile']
867 if not recipefile:
868 raise DevtoolError('devtool rename can only be used where the recipe file itself is in the workspace (e.g. after devtool add)')
869
870 if args.newname and args.newname != args.recipename:
871 reason = oe.recipeutils.validate_pn(args.newname)
872 if reason:
873 raise DevtoolError(reason)
874 newname = args.newname
875 else:
876 newname = args.recipename
877
878 append = workspace[args.recipename]['bbappend']
879 appendfn = os.path.splitext(os.path.basename(append))[0]
880 splitfn = appendfn.split('_')
881 if len(splitfn) > 1:
882 origfnver = appendfn.split('_')[1]
883 else:
884 origfnver = ''
885
886 recipefilemd5 = None
887 tinfoil = setup_tinfoil(basepath=basepath, tracking=True)
888 try:
889 rd = parse_recipe(config, tinfoil, args.recipename, True)
890 if not rd:
891 return 1
892
893 bp = rd.getVar('BP', True)
894 bpn = rd.getVar('BPN', True)
895 if newname != args.recipename:
896 localdata = rd.createCopy()
897 localdata.setVar('PN', newname)
898 newbpn = localdata.getVar('BPN', True)
899 else:
900 newbpn = bpn
901 s = rd.getVar('S', False)
902 src_uri = rd.getVar('SRC_URI', False)
903 pv = rd.getVar('PV', True)
904
905 # Correct variable values that refer to the upstream source - these
906 # values must stay the same, so if the name/version are changing then
907 # we need to fix them up
908 new_s = s
909 new_src_uri = src_uri
910 if newbpn != bpn:
911 # ${PN} here is technically almost always incorrect, but people do use it
912 new_s = new_s.replace('${BPN}', bpn)
913 new_s = new_s.replace('${PN}', bpn)
914 new_s = new_s.replace('${BP}', '%s-${PV}' % bpn)
915 new_src_uri = new_src_uri.replace('${BPN}', bpn)
916 new_src_uri = new_src_uri.replace('${PN}', bpn)
917 new_src_uri = new_src_uri.replace('${BP}', '%s-${PV}' % bpn)
918 if args.version and origfnver == pv:
919 new_s = new_s.replace('${PV}', pv)
920 new_s = new_s.replace('${BP}', '${BPN}-%s' % pv)
921 new_src_uri = new_src_uri.replace('${PV}', pv)
922 new_src_uri = new_src_uri.replace('${BP}', '${BPN}-%s' % pv)
923 patchfields = {}
924 if new_s != s:
925 patchfields['S'] = new_s
926 if new_src_uri != src_uri:
927 patchfields['SRC_URI'] = new_src_uri
928 if patchfields:
929 recipefilemd5 = bb.utils.md5_file(recipefile)
930 oe.recipeutils.patch_recipe(rd, recipefile, patchfields)
931 newrecipefilemd5 = bb.utils.md5_file(recipefile)
932 finally:
933 tinfoil.shutdown()
934
935 if args.version:
936 newver = args.version
937 else:
938 newver = origfnver
939
940 if newver:
941 newappend = '%s_%s.bbappend' % (newname, newver)
942 newfile = '%s_%s.bb' % (newname, newver)
943 else:
944 newappend = '%s.bbappend' % newname
945 newfile = '%s.bb' % newname
946
947 oldrecipedir = os.path.dirname(recipefile)
948 newrecipedir = os.path.join(config.workspace_path, 'recipes', newname)
949 if oldrecipedir != newrecipedir:
950 bb.utils.mkdirhier(newrecipedir)
951
952 newappend = os.path.join(os.path.dirname(append), newappend)
953 newfile = os.path.join(newrecipedir, newfile)
954
955 # Rename bbappend
956 logger.info('Renaming %s to %s' % (append, newappend))
957 os.rename(append, newappend)
958 # Rename recipe file
959 logger.info('Renaming %s to %s' % (recipefile, newfile))
960 os.rename(recipefile, newfile)
961
962 # Rename source tree if it's the default path
963 appendmd5 = None
964 if not args.no_srctree:
965 srctree = workspace[args.recipename]['srctree']
966 if os.path.abspath(srctree) == os.path.join(config.workspace_path, 'sources', args.recipename):
967 newsrctree = os.path.join(config.workspace_path, 'sources', newname)
968 logger.info('Renaming %s to %s' % (srctree, newsrctree))
969 shutil.move(srctree, newsrctree)
970 # Correct any references (basically EXTERNALSRC*) in the .bbappend
971 appendmd5 = bb.utils.md5_file(newappend)
972 appendlines = []
973 with open(newappend, 'r') as f:
974 for line in f:
975 appendlines.append(line)
976 with open(newappend, 'w') as f:
977 for line in appendlines:
978 if srctree in line:
979 line = line.replace(srctree, newsrctree)
980 f.write(line)
981 newappendmd5 = bb.utils.md5_file(newappend)
982
983 bpndir = None
984 newbpndir = None
985 if newbpn != bpn:
986 bpndir = os.path.join(oldrecipedir, bpn)
987 if os.path.exists(bpndir):
988 newbpndir = os.path.join(newrecipedir, newbpn)
989 logger.info('Renaming %s to %s' % (bpndir, newbpndir))
990 shutil.move(bpndir, newbpndir)
991
992 bpdir = None
993 newbpdir = None
994 if newver != origfnver or newbpn != bpn:
995 bpdir = os.path.join(oldrecipedir, bp)
996 if os.path.exists(bpdir):
997 newbpdir = os.path.join(newrecipedir, '%s-%s' % (newbpn, newver))
998 logger.info('Renaming %s to %s' % (bpdir, newbpdir))
999 shutil.move(bpdir, newbpdir)
1000
1001 if oldrecipedir != newrecipedir:
1002 # Move any stray files and delete the old recipe directory
1003 for entry in os.listdir(oldrecipedir):
1004 oldpath = os.path.join(oldrecipedir, entry)
1005 newpath = os.path.join(newrecipedir, entry)
1006 logger.info('Renaming %s to %s' % (oldpath, newpath))
1007 shutil.move(oldpath, newpath)
1008 os.rmdir(oldrecipedir)
1009
1010 # Now take care of entries in .devtool_md5
1011 md5entries = []
1012 with open(os.path.join(config.workspace_path, '.devtool_md5'), 'r') as f:
1013 for line in f:
1014 md5entries.append(line)
1015
1016 if bpndir and newbpndir:
1017 relbpndir = os.path.relpath(bpndir, config.workspace_path) + '/'
1018 else:
1019 relbpndir = None
1020 if bpdir and newbpdir:
1021 relbpdir = os.path.relpath(bpdir, config.workspace_path) + '/'
1022 else:
1023 relbpdir = None
1024
1025 with open(os.path.join(config.workspace_path, '.devtool_md5'), 'w') as f:
1026 for entry in md5entries:
1027 splitentry = entry.rstrip().split('|')
1028 if len(splitentry) > 2:
1029 if splitentry[0] == args.recipename:
1030 splitentry[0] = newname
1031 if splitentry[1] == os.path.relpath(append, config.workspace_path):
1032 splitentry[1] = os.path.relpath(newappend, config.workspace_path)
1033 if appendmd5 and splitentry[2] == appendmd5:
1034 splitentry[2] = newappendmd5
1035 elif splitentry[1] == os.path.relpath(recipefile, config.workspace_path):
1036 splitentry[1] = os.path.relpath(newfile, config.workspace_path)
1037 if recipefilemd5 and splitentry[2] == recipefilemd5:
1038 splitentry[2] = newrecipefilemd5
1039 elif relbpndir and splitentry[1].startswith(relbpndir):
1040 splitentry[1] = os.path.relpath(os.path.join(newbpndir, splitentry[1][len(relbpndir):]), config.workspace_path)
1041 elif relbpdir and splitentry[1].startswith(relbpdir):
1042 splitentry[1] = os.path.relpath(os.path.join(newbpdir, splitentry[1][len(relbpdir):]), config.workspace_path)
1043 entry = '|'.join(splitentry) + '\n'
1044 f.write(entry)
1045 return 0
1046
1047
855def _get_patchset_revs(srctree, recipe_path, initial_rev=None): 1048def _get_patchset_revs(srctree, recipe_path, initial_rev=None):
856 """Get initial and update rev of a recipe. These are the start point of the 1049 """Get initial and update rev of a recipe. These are the start point of the
857 whole patchset and start point for the patches to be re-generated/updated. 1050 whole patchset and start point for the patches to be re-generated/updated.
@@ -1630,6 +1823,15 @@ def register_commands(subparsers, context):
1630 parser_sync.add_argument('--keep-temp', action="store_true", help='Keep temporary directory (for debugging)') 1823 parser_sync.add_argument('--keep-temp', action="store_true", help='Keep temporary directory (for debugging)')
1631 parser_sync.set_defaults(func=sync) 1824 parser_sync.set_defaults(func=sync)
1632 1825
1826 parser_rename = subparsers.add_parser('rename', help='Rename a recipe file in the workspace',
1827 description='Renames the recipe file for a recipe in the workspace, changing the name or version part or both, ensuring that all references within the workspace are updated at the same time. Only works when the recipe file itself is in the workspace, e.g. after devtool add. Particularly useful when devtool add did not automatically determine the correct name.',
1828 group='working', order=10)
1829 parser_rename.add_argument('recipename', help='Current name of recipe to rename')
1830 parser_rename.add_argument('newname', nargs='?', help='New name for recipe (optional, not needed if you only want to change the version)')
1831 parser_rename.add_argument('--version', '-V', help='Change the version (NOTE: this does not change the version fetched by the recipe, just the version in the recipe file name)')
1832 parser_rename.add_argument('--no-srctree', '-s', action='store_true', help='Do not rename the source tree directory (if the default source tree path has been used) - keeping the old name may be desirable if there are internal/other external references to this path')
1833 parser_rename.set_defaults(func=rename)
1834
1633 parser_update_recipe = subparsers.add_parser('update-recipe', help='Apply changes from external source tree to recipe', 1835 parser_update_recipe = subparsers.add_parser('update-recipe', help='Apply changes from external source tree to recipe',
1634 description='Applies changes from external source tree to a recipe (updating/adding/removing patches as necessary, or by updating SRCREV). Note that these changes need to have been committed to the git repository in order to be recognised.', 1836 description='Applies changes from external source tree to a recipe (updating/adding/removing patches as necessary, or by updating SRCREV). Note that these changes need to have been committed to the git repository in order to be recognised.',
1635 group='working', order=-90) 1837 group='working', order=-90)