summaryrefslogtreecommitdiffstats
path: root/scripts/lib/devtool/standard.py
diff options
context:
space:
mode:
authorJulien Stephan <jstephan@baylibre.com>2023-11-22 12:08:16 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-12-01 11:48:25 +0000
commit89f16624842a91e063dc9e6b98787d44c55e4900 (patch)
treec22ebb7b7f5ff89d3ed8431e8dcace59678b9ed3 /scripts/lib/devtool/standard.py
parent17427db136491f13b0c9f187906ce9e3f6c85b29 (diff)
downloadpoky-89f16624842a91e063dc9e6b98787d44c55e4900.tar.gz
devtool: add support for git submodules
Adding the support of submodules required a lot of changes on the internal data structures: * initial_rev/startcommit used as a starting point for looking at new / updated commits was replaced by a dictionary where the keys are the submodule name ("." for main repo) and the values are the initial_rev/startcommit * the extractPatches function now extracts patch for the main repo and for all submodules and stores them in a hierarchical way describing the submodule path * store initial_rev/commit also for all submodules inside the recipe bbappend file * _export_patches now returns dictionaries that contains the 'patchdir' parameter (if any). This parameter is used to add the correct 'patchdir=' parameter on the recipe Also, recipe can extract a secondary git tree inside the workdir. By default, at the end of the do_patch function, there is a hook in devtool that commits everything that was modified to have a clean repository. It uses the command: "git add .; git commit ..." The issue here is that, it adds the secondary git tree as a submodule but in a wrong way. Doing "git add <git dir>" declares a submodule but do not adds a url associated to it, and all following "git submodule foreach" commands will fail. So detect that a git tree was extracted inside S and correctly add it using "git submodule add <url> <path>", so that it will be considered as a regular git submodule (From OE-Core rev: 900129cbdf25297a42ab5dbd02d1adbea405c935) Signed-off-by: Julien Stephan <jstephan@baylibre.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/devtool/standard.py')
-rw-r--r--scripts/lib/devtool/standard.py269
1 files changed, 167 insertions, 102 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 55fa38ccfb..ad6e346279 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -234,10 +234,14 @@ def add(args, config, basepath, workspace):
234 if args.fetchuri and not args.no_git: 234 if args.fetchuri and not args.no_git:
235 setup_git_repo(srctree, args.version, 'devtool', d=tinfoil.config_data) 235 setup_git_repo(srctree, args.version, 'devtool', d=tinfoil.config_data)
236 236
237 initial_rev = None 237 initial_rev = {}
238 if os.path.exists(os.path.join(srctree, '.git')): 238 if os.path.exists(os.path.join(srctree, '.git')):
239 (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree) 239 (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree)
240 initial_rev = stdout.rstrip() 240 initial_rev["."] = stdout.rstrip()
241 (stdout, _) = bb.process.run('git submodule --quiet foreach --recursive \'echo `git rev-parse HEAD` $PWD\'', cwd=srctree)
242 for line in stdout.splitlines():
243 (rev, submodule) = line.split()
244 initial_rev[os.path.relpath(submodule, srctree)] = rev
241 245
242 if args.src_subdir: 246 if args.src_subdir:
243 srctree = os.path.join(srctree, args.src_subdir) 247 srctree = os.path.join(srctree, args.src_subdir)
@@ -251,7 +255,8 @@ def add(args, config, basepath, workspace):
251 if b_is_s: 255 if b_is_s:
252 f.write('EXTERNALSRC_BUILD = "%s"\n' % srctree) 256 f.write('EXTERNALSRC_BUILD = "%s"\n' % srctree)
253 if initial_rev: 257 if initial_rev:
254 f.write('\n# initial_rev: %s\n' % initial_rev) 258 for key, value in initial_rev.items():
259 f.write('\n# initial_rev %s: %s\n' % (key, value))
255 260
256 if args.binary: 261 if args.binary:
257 f.write('do_install:append() {\n') 262 f.write('do_install:append() {\n')
@@ -823,8 +828,8 @@ def modify(args, config, basepath, workspace):
823 828
824 _check_compatible_recipe(pn, rd) 829 _check_compatible_recipe(pn, rd)
825 830
826 initial_rev = None 831 initial_revs = {}
827 commits = [] 832 commits = {}
828 check_commits = False 833 check_commits = False
829 834
830 if bb.data.inherits_class('kernel-yocto', rd): 835 if bb.data.inherits_class('kernel-yocto', rd):
@@ -880,15 +885,23 @@ def modify(args, config, basepath, workspace):
880 args.no_extract = True 885 args.no_extract = True
881 886
882 if not args.no_extract: 887 if not args.no_extract:
883 initial_rev, _ = _extract_source(srctree, args.keep_temp, args.branch, False, config, basepath, workspace, args.fixed_setup, rd, tinfoil, no_overrides=args.no_overrides) 888 initial_revs["."], _ = _extract_source(srctree, args.keep_temp, args.branch, False, config, basepath, workspace, args.fixed_setup, rd, tinfoil, no_overrides=args.no_overrides)
884 if not initial_rev: 889 if not initial_revs["."]:
885 return 1 890 return 1
886 logger.info('Source tree extracted to %s' % srctree) 891 logger.info('Source tree extracted to %s' % srctree)
892
887 if os.path.exists(os.path.join(srctree, '.git')): 893 if os.path.exists(os.path.join(srctree, '.git')):
888 # Get list of commits since this revision 894 # Get list of commits since this revision
889 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_rev, cwd=srctree) 895 (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_revs["."], cwd=srctree)
890 commits = stdout.split() 896 commits["."] = stdout.split()
891 check_commits = True 897 check_commits = True
898 (stdout, _) = bb.process.run('git submodule --quiet foreach --recursive \'echo `git rev-parse devtool-base` $PWD\'', cwd=srctree)
899 for line in stdout.splitlines():
900 (rev, submodule_path) = line.split()
901 submodule = os.path.relpath(submodule_path, srctree)
902 initial_revs[submodule] = rev
903 (stdout, _) = bb.process.run('git rev-list --reverse devtool-base..HEAD', cwd=submodule_path)
904 commits[submodule] = stdout.split()
892 else: 905 else:
893 if os.path.exists(os.path.join(srctree, '.git')): 906 if os.path.exists(os.path.join(srctree, '.git')):
894 # Check if it's a tree previously extracted by us. This is done 907 # Check if it's a tree previously extracted by us. This is done
@@ -905,11 +918,11 @@ def modify(args, config, basepath, workspace):
905 for line in stdout.splitlines(): 918 for line in stdout.splitlines():
906 if line.startswith('*'): 919 if line.startswith('*'):
907 (stdout, _) = bb.process.run('git rev-parse devtool-base', cwd=srctree) 920 (stdout, _) = bb.process.run('git rev-parse devtool-base', cwd=srctree)
908 initial_rev = stdout.rstrip() 921 initial_revs["."] = stdout.rstrip()
909 if not initial_rev: 922 if not initial_revs["."]:
910 # Otherwise, just grab the head revision 923 # Otherwise, just grab the head revision
911 (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree) 924 (stdout, _) = bb.process.run('git rev-parse HEAD', cwd=srctree)
912 initial_rev = stdout.rstrip() 925 initial_revs["."] = stdout.rstrip()
913 926
914 branch_patches = {} 927 branch_patches = {}
915 if check_commits: 928 if check_commits:
@@ -976,10 +989,11 @@ def modify(args, config, basepath, workspace):
976 ' ln -sfT ${KCONFIG_CONFIG_ROOTDIR}/.config ${S}/.config.new\n' 989 ' ln -sfT ${KCONFIG_CONFIG_ROOTDIR}/.config ${S}/.config.new\n'
977 ' fi\n' 990 ' fi\n'
978 '}\n') 991 '}\n')
979 if initial_rev: 992 if initial_revs:
980 f.write('\n# initial_rev: %s\n' % initial_rev) 993 for name, rev in initial_revs.items():
981 for commit in commits: 994 f.write('\n# initial_rev %s: %s\n' % (name, rev))
982 f.write('# commit: %s\n' % commit) 995 for commit in commits[name]:
996 f.write('# commit %s: %s\n' % (name, commit))
983 if branch_patches: 997 if branch_patches:
984 for branch in branch_patches: 998 for branch in branch_patches:
985 if branch == args.branch: 999 if branch == args.branch:
@@ -1202,44 +1216,56 @@ def _get_patchset_revs(srctree, recipe_path, initial_rev=None, force_patch_refre
1202 branchname = stdout.rstrip() 1216 branchname = stdout.rstrip()
1203 1217
1204 # Parse initial rev from recipe if not specified 1218 # Parse initial rev from recipe if not specified
1205 commits = [] 1219 commits = {}
1206 patches = [] 1220 patches = []
1221 initial_revs = {}
1207 with open(recipe_path, 'r') as f: 1222 with open(recipe_path, 'r') as f:
1208 for line in f: 1223 for line in f:
1209 if line.startswith('# initial_rev:'): 1224 pattern = r'^#\s.*\s(.*):\s([0-9a-fA-F]+)$'
1210 if not initial_rev: 1225 match = re.search(pattern, line)
1211 initial_rev = line.split(':')[-1].strip() 1226 if match:
1212 elif line.startswith('# commit:') and not force_patch_refresh: 1227 name = match.group(1)
1213 commits.append(line.split(':')[-1].strip()) 1228 rev = match.group(2)
1214 elif line.startswith('# patches_%s:' % branchname): 1229 if line.startswith('# initial_rev'):
1215 patches = line.split(':')[-1].strip().split(',') 1230 if not (name == "." and initial_rev):
1216 1231 initial_revs[name] = rev
1217 update_rev = initial_rev 1232 elif line.startswith('# commit') and not force_patch_refresh:
1218 changed_revs = None 1233 if name not in commits:
1219 if initial_rev: 1234 commits[name] = [rev]
1235 else:
1236 commits[name].append(rev)
1237 elif line.startswith('# patches_%s:' % branchname):
1238 patches = line.split(':')[-1].strip().split(',')
1239
1240 update_revs = dict(initial_revs)
1241 changed_revs = {}
1242 for name, rev in initial_revs.items():
1220 # Find first actually changed revision 1243 # Find first actually changed revision
1221 stdout, _ = bb.process.run('git rev-list --reverse %s..HEAD' % 1244 stdout, _ = bb.process.run('git rev-list --reverse %s..HEAD' %
1222 initial_rev, cwd=srctree) 1245 rev, cwd=os.path.join(srctree, name))
1223 newcommits = stdout.split() 1246 newcommits = stdout.split()
1224 for i in range(min(len(commits), len(newcommits))): 1247 if name in commits:
1225 if newcommits[i] == commits[i]: 1248 for i in range(min(len(commits[name]), len(newcommits))):
1226 update_rev = commits[i] 1249 if newcommits[i] == commits[name][i]:
1250 update_revs[name] = commits[name][i]
1227 1251
1228 try: 1252 try:
1229 stdout, _ = bb.process.run('git cherry devtool-patched', 1253 stdout, _ = bb.process.run('git cherry devtool-patched',
1230 cwd=srctree) 1254 cwd=os.path.join(srctree, name))
1231 except bb.process.ExecutionError as err: 1255 except bb.process.ExecutionError as err:
1232 stdout = None 1256 stdout = None
1233 1257
1234 if stdout is not None and not force_patch_refresh: 1258 if stdout is not None and not force_patch_refresh:
1235 changed_revs = []
1236 for line in stdout.splitlines(): 1259 for line in stdout.splitlines():
1237 if line.startswith('+ '): 1260 if line.startswith('+ '):
1238 rev = line.split()[1] 1261 rev = line.split()[1]
1239 if rev in newcommits: 1262 if rev in newcommits:
1240 changed_revs.append(rev) 1263 if name not in changed_revs:
1264 changed_revs[name] = [rev]
1265 else:
1266 changed_revs[name].append(rev)
1241 1267
1242 return initial_rev, update_rev, changed_revs, patches 1268 return initial_revs, update_revs, changed_revs, patches
1243 1269
1244def _remove_file_entries(srcuri, filelist): 1270def _remove_file_entries(srcuri, filelist):
1245 """Remove file:// entries from SRC_URI""" 1271 """Remove file:// entries from SRC_URI"""
@@ -1294,14 +1320,17 @@ def _remove_source_files(append, files, destpath, no_report_remove=False, dry_ru
1294 raise 1320 raise
1295 1321
1296 1322
1297def _export_patches(srctree, rd, start_rev, destdir, changed_revs=None): 1323def _export_patches(srctree, rd, start_revs, destdir, changed_revs=None):
1298 """Export patches from srctree to given location. 1324 """Export patches from srctree to given location.
1299 Returns three-tuple of dicts: 1325 Returns three-tuple of dicts:
1300 1. updated - patches that already exist in SRCURI 1326 1. updated - patches that already exist in SRCURI
1301 2. added - new patches that don't exist in SRCURI 1327 2. added - new patches that don't exist in SRCURI
1302 3 removed - patches that exist in SRCURI but not in exported patches 1328 3 removed - patches that exist in SRCURI but not in exported patches
1303 In each dict the key is the 'basepath' of the URI and value is the 1329 In each dict the key is the 'basepath' of the URI and value is:
1304 absolute path to the existing file in recipe space (if any). 1330 - for updated and added dicts, a dict with 2 optionnal keys:
1331 - 'path': the absolute path to the existing file in recipe space (if any)
1332 - 'patchdir': the directory in wich the patch should be applied (if any)
1333 - for removed dict, the absolute path to the existing file in recipe space
1305 """ 1334 """
1306 import oe.recipeutils 1335 import oe.recipeutils
1307 from oe.patch import GitApplyTree 1336 from oe.patch import GitApplyTree
@@ -1315,54 +1344,60 @@ def _export_patches(srctree, rd, start_rev, destdir, changed_revs=None):
1315 1344
1316 # Generate patches from Git, exclude local files directory 1345 # Generate patches from Git, exclude local files directory
1317 patch_pathspec = _git_exclude_path(srctree, 'oe-local-files') 1346 patch_pathspec = _git_exclude_path(srctree, 'oe-local-files')
1318 GitApplyTree.extractPatches(srctree, start_rev, destdir, patch_pathspec) 1347 GitApplyTree.extractPatches(srctree, start_revs, destdir, patch_pathspec)
1319 1348 for dirpath, dirnames, filenames in os.walk(destdir):
1320 new_patches = sorted(os.listdir(destdir)) 1349 new_patches = filenames
1321 for new_patch in new_patches: 1350 reldirpath = os.path.relpath(dirpath, destdir)
1322 # Strip numbering from patch names. If it's a git sequence named patch, 1351 for new_patch in new_patches:
1323 # the numbers might not match up since we are starting from a different 1352 # Strip numbering from patch names. If it's a git sequence named patch,
1324 # revision This does assume that people are using unique shortlog 1353 # the numbers might not match up since we are starting from a different
1325 # values, but they ought to be anyway... 1354 # revision This does assume that people are using unique shortlog
1326 new_basename = seqpatch_re.match(new_patch).group(2) 1355 # values, but they ought to be anyway...
1327 match_name = None 1356 new_basename = seqpatch_re.match(new_patch).group(2)
1328 for old_patch in existing_patches: 1357 match_name = None
1329 old_basename = seqpatch_re.match(old_patch).group(2) 1358 for old_patch in existing_patches:
1330 old_basename_splitext = os.path.splitext(old_basename) 1359 old_basename = seqpatch_re.match(old_patch).group(2)
1331 if old_basename.endswith(('.gz', '.bz2', '.Z')) and old_basename_splitext[0] == new_basename: 1360 old_basename_splitext = os.path.splitext(old_basename)
1332 old_patch_noext = os.path.splitext(old_patch)[0] 1361 if old_basename.endswith(('.gz', '.bz2', '.Z')) and old_basename_splitext[0] == new_basename:
1333 match_name = old_patch_noext 1362 old_patch_noext = os.path.splitext(old_patch)[0]
1334 break 1363 match_name = old_patch_noext
1335 elif new_basename == old_basename: 1364 break
1336 match_name = old_patch 1365 elif new_basename == old_basename:
1337 break 1366 match_name = old_patch
1338 if match_name: 1367 break
1339 # Rename patch files 1368 if match_name:
1340 if new_patch != match_name: 1369 # Rename patch files
1341 bb.utils.rename(os.path.join(destdir, new_patch), 1370 if new_patch != match_name:
1342 os.path.join(destdir, match_name)) 1371 bb.utils.rename(os.path.join(destdir, new_patch),
1343 # Need to pop it off the list now before checking changed_revs 1372 os.path.join(destdir, match_name))
1344 oldpath = existing_patches.pop(old_patch) 1373 # Need to pop it off the list now before checking changed_revs
1345 if changed_revs is not None: 1374 oldpath = existing_patches.pop(old_patch)
1346 # Avoid updating patches that have not actually changed 1375 if changed_revs is not None and dirpath in changed_revs:
1347 with open(os.path.join(destdir, match_name), 'r') as f: 1376 # Avoid updating patches that have not actually changed
1348 firstlineitems = f.readline().split() 1377 with open(os.path.join(dirpath, match_name), 'r') as f:
1349 # Looking for "From <hash>" line 1378 firstlineitems = f.readline().split()
1350 if len(firstlineitems) > 1 and len(firstlineitems[1]) == 40: 1379 # Looking for "From <hash>" line
1351 if not firstlineitems[1] in changed_revs: 1380 if len(firstlineitems) > 1 and len(firstlineitems[1]) == 40:
1352 continue 1381 if not firstlineitems[1] in changed_revs[dirpath]:
1353 # Recompress if necessary 1382 continue
1354 if oldpath.endswith(('.gz', '.Z')): 1383 # Recompress if necessary
1355 bb.process.run(['gzip', match_name], cwd=destdir) 1384 if oldpath.endswith(('.gz', '.Z')):
1356 if oldpath.endswith('.gz'): 1385 bb.process.run(['gzip', match_name], cwd=destdir)
1357 match_name += '.gz' 1386 if oldpath.endswith('.gz'):
1358 else: 1387 match_name += '.gz'
1359 match_name += '.Z' 1388 else:
1360 elif oldpath.endswith('.bz2'): 1389 match_name += '.Z'
1361 bb.process.run(['bzip2', match_name], cwd=destdir) 1390 elif oldpath.endswith('.bz2'):
1362 match_name += '.bz2' 1391 bb.process.run(['bzip2', match_name], cwd=destdir)
1363 updated[match_name] = oldpath 1392 match_name += '.bz2'
1364 else: 1393 updated[match_name] = {'path' : oldpath}
1365 added[new_patch] = None 1394 if reldirpath != ".":
1395 updated[match_name]['patchdir'] = reldirpath
1396 else:
1397 added[new_patch] = {}
1398 if reldirpath != ".":
1399 added[new_patch]['patchdir'] = reldirpath
1400
1366 return (updated, added, existing_patches) 1401 return (updated, added, existing_patches)
1367 1402
1368 1403
@@ -1534,6 +1569,7 @@ def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wi
1534 old_srcrev = rd.getVar('SRCREV') or '' 1569 old_srcrev = rd.getVar('SRCREV') or ''
1535 if old_srcrev == "INVALID": 1570 if old_srcrev == "INVALID":
1536 raise DevtoolError('Update mode srcrev is only valid for recipe fetched from an SCM repository') 1571 raise DevtoolError('Update mode srcrev is only valid for recipe fetched from an SCM repository')
1572 old_srcrev = {'.': old_srcrev}
1537 1573
1538 # Get HEAD revision 1574 # Get HEAD revision
1539 try: 1575 try:
@@ -1566,7 +1602,7 @@ def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wi
1566 logger.debug('Patches: update %s, new %s, delete %s' % (dict(upd_p), dict(new_p), dict(del_p))) 1602 logger.debug('Patches: update %s, new %s, delete %s' % (dict(upd_p), dict(new_p), dict(del_p)))
1567 1603
1568 # Remove deleted local files and "overlapping" patches 1604 # Remove deleted local files and "overlapping" patches
1569 remove_files = list(del_f.values()) + list(upd_p.values()) + list(del_p.values()) 1605 remove_files = list(del_f.values()) + [value["path"] for value in upd_p.values() if "path" in value] + [value["path"] for value in del_p.values() if "path" in value]
1570 if remove_files: 1606 if remove_files:
1571 removedentries = _remove_file_entries(srcuri, remove_files)[0] 1607 removedentries = _remove_file_entries(srcuri, remove_files)[0]
1572 update_srcuri = True 1608 update_srcuri = True
@@ -1635,15 +1671,15 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1635 else: 1671 else:
1636 patchdir_params = {'patchdir': relpatchdir} 1672 patchdir_params = {'patchdir': relpatchdir}
1637 1673
1638 def srcuri_entry(basepath): 1674 def srcuri_entry(basepath, patchdir_params):
1639 if patchdir_params: 1675 if patchdir_params:
1640 paramstr = ';' + ';'.join('%s=%s' % (k,v) for k,v in patchdir_params.items()) 1676 paramstr = ';' + ';'.join('%s=%s' % (k,v) for k,v in patchdir_params.items())
1641 else: 1677 else:
1642 paramstr = '' 1678 paramstr = ''
1643 return 'file://%s%s' % (basepath, paramstr) 1679 return 'file://%s%s' % (basepath, paramstr)
1644 1680
1645 initial_rev, update_rev, changed_revs, filter_patches = _get_patchset_revs(srctree, append, initial_rev, force_patch_refresh) 1681 initial_revs, update_revs, changed_revs, filter_patches = _get_patchset_revs(srctree, append, initial_rev, force_patch_refresh)
1646 if not initial_rev: 1682 if not initial_revs:
1647 raise DevtoolError('Unable to find initial revision - please specify ' 1683 raise DevtoolError('Unable to find initial revision - please specify '
1648 'it with --initial-rev') 1684 'it with --initial-rev')
1649 1685
@@ -1661,11 +1697,11 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1661 1697
1662 # Get updated patches from source tree 1698 # Get updated patches from source tree
1663 patches_dir = tempfile.mkdtemp(dir=tempdir) 1699 patches_dir = tempfile.mkdtemp(dir=tempdir)
1664 upd_p, new_p, _ = _export_patches(srctree, rd, update_rev, 1700 upd_p, new_p, _ = _export_patches(srctree, rd, update_revs,
1665 patches_dir, changed_revs) 1701 patches_dir, changed_revs)
1666 # Get all patches from source tree and check if any should be removed 1702 # Get all patches from source tree and check if any should be removed
1667 all_patches_dir = tempfile.mkdtemp(dir=tempdir) 1703 all_patches_dir = tempfile.mkdtemp(dir=tempdir)
1668 _, _, del_p = _export_patches(srctree, rd, initial_rev, 1704 _, _, del_p = _export_patches(srctree, rd, initial_revs,
1669 all_patches_dir) 1705 all_patches_dir)
1670 logger.debug('Pre-filtering: update: %s, new: %s' % (dict(upd_p), dict(new_p))) 1706 logger.debug('Pre-filtering: update: %s, new: %s' % (dict(upd_p), dict(new_p)))
1671 if filter_patches: 1707 if filter_patches:
@@ -1680,18 +1716,31 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1680 updaterecipe = False 1716 updaterecipe = False
1681 destpath = None 1717 destpath = None
1682 srcuri = (rd.getVar('SRC_URI', False) or '').split() 1718 srcuri = (rd.getVar('SRC_URI', False) or '').split()
1719
1683 if appendlayerdir: 1720 if appendlayerdir:
1684 files = OrderedDict((os.path.join(local_files_dir, key), val) for 1721 files = OrderedDict((os.path.join(local_files_dir, key), val) for
1685 key, val in list(upd_f.items()) + list(new_f.items())) 1722 key, val in list(upd_f.items()) + list(new_f.items()))
1686 files.update(OrderedDict((os.path.join(patches_dir, key), val) for 1723 files.update(OrderedDict((os.path.join(patches_dir, key), val) for
1687 key, val in list(upd_p.items()) + list(new_p.items()))) 1724 key, val in list(upd_p.items()) + list(new_p.items())))
1725
1726 params = []
1727 for file, param in files.items():
1728 patchdir_param = dict(patchdir_params)
1729 patchdir = param.get('patchdir', ".")
1730 if patchdir != "." :
1731 if patchdir_param:
1732 patchdir_param['patchdir'] += patchdir
1733 else:
1734 patchdir_param['patchdir'] = patchdir
1735 params.append(patchdir_param)
1736
1688 if files or remove_files: 1737 if files or remove_files:
1689 removevalues = None 1738 removevalues = None
1690 if remove_files: 1739 if remove_files:
1691 removedentries, remaining = _remove_file_entries( 1740 removedentries, remaining = _remove_file_entries(
1692 srcuri, remove_files) 1741 srcuri, remove_files)
1693 if removedentries or remaining: 1742 if removedentries or remaining:
1694 remaining = [srcuri_entry(os.path.basename(item)) for 1743 remaining = [srcuri_entry(os.path.basename(item), patchdir_params) for
1695 item in remaining] 1744 item in remaining]
1696 removevalues = {'SRC_URI': removedentries + remaining} 1745 removevalues = {'SRC_URI': removedentries + remaining}
1697 appendfile, destpath = oe.recipeutils.bbappend_recipe( 1746 appendfile, destpath = oe.recipeutils.bbappend_recipe(
@@ -1699,7 +1748,7 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1699 wildcardver=wildcard_version, 1748 wildcardver=wildcard_version,
1700 removevalues=removevalues, 1749 removevalues=removevalues,
1701 redirect_output=dry_run_outdir, 1750 redirect_output=dry_run_outdir,
1702 params=[patchdir_params] * len(files)) 1751 params=params)
1703 else: 1752 else:
1704 logger.info('No patches or local source files needed updating') 1753 logger.info('No patches or local source files needed updating')
1705 else: 1754 else:
@@ -1716,14 +1765,22 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1716 _move_file(os.path.join(local_files_dir, basepath), path, 1765 _move_file(os.path.join(local_files_dir, basepath), path,
1717 dry_run_outdir=dry_run_outdir, base_outdir=recipedir) 1766 dry_run_outdir=dry_run_outdir, base_outdir=recipedir)
1718 updatefiles = True 1767 updatefiles = True
1719 for basepath, path in upd_p.items(): 1768 for basepath, param in upd_p.items():
1720 patchfn = os.path.join(patches_dir, basepath) 1769 path = param['path']
1770 patchdir = param.get('patchdir', ".")
1771 if patchdir != "." :
1772 patchdir_param = dict(patchdir_params)
1773 if patchdir_param:
1774 patchdir_param['patchdir'] += patchdir
1775 else:
1776 patchdir_param['patchdir'] = patchdir
1777 patchfn = os.path.join(patches_dir, patchdir, basepath)
1721 if os.path.dirname(path) + '/' == dl_dir: 1778 if os.path.dirname(path) + '/' == dl_dir:
1722 # This is a a downloaded patch file - we now need to 1779 # This is a a downloaded patch file - we now need to
1723 # replace the entry in SRC_URI with our local version 1780 # replace the entry in SRC_URI with our local version
1724 logger.info('Replacing remote patch %s with updated local version' % basepath) 1781 logger.info('Replacing remote patch %s with updated local version' % basepath)
1725 path = os.path.join(files_dir, basepath) 1782 path = os.path.join(files_dir, basepath)
1726 _replace_srcuri_entry(srcuri, basepath, srcuri_entry(basepath)) 1783 _replace_srcuri_entry(srcuri, basepath, srcuri_entry(basepath, patchdir_param))
1727 updaterecipe = True 1784 updaterecipe = True
1728 else: 1785 else:
1729 logger.info('Updating patch %s%s' % (basepath, dry_run_suffix)) 1786 logger.info('Updating patch %s%s' % (basepath, dry_run_suffix))
@@ -1737,15 +1794,23 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1737 os.path.join(files_dir, basepath), 1794 os.path.join(files_dir, basepath),
1738 dry_run_outdir=dry_run_outdir, 1795 dry_run_outdir=dry_run_outdir,
1739 base_outdir=recipedir) 1796 base_outdir=recipedir)
1740 srcuri.append(srcuri_entry(basepath)) 1797 srcuri.append(srcuri_entry(basepath, patchdir_params))
1741 updaterecipe = True 1798 updaterecipe = True
1742 for basepath, path in new_p.items(): 1799 for basepath, param in new_p.items():
1800 patchdir = param.get('patchdir', ".")
1743 logger.info('Adding new patch %s%s' % (basepath, dry_run_suffix)) 1801 logger.info('Adding new patch %s%s' % (basepath, dry_run_suffix))
1744 _move_file(os.path.join(patches_dir, basepath), 1802 _move_file(os.path.join(patches_dir, patchdir, basepath),
1745 os.path.join(files_dir, basepath), 1803 os.path.join(files_dir, basepath),
1746 dry_run_outdir=dry_run_outdir, 1804 dry_run_outdir=dry_run_outdir,
1747 base_outdir=recipedir) 1805 base_outdir=recipedir)
1748 srcuri.append(srcuri_entry(basepath)) 1806 params = dict(patchdir_params)
1807 if patchdir != "." :
1808 if params:
1809 params['patchdir'] += patchdir
1810 else:
1811 params['patchdir'] = patchdir
1812
1813 srcuri.append(srcuri_entry(basepath, params))
1749 updaterecipe = True 1814 updaterecipe = True
1750 # Update recipe, if needed 1815 # Update recipe, if needed
1751 if _remove_file_entries(srcuri, remove_files)[0]: 1816 if _remove_file_entries(srcuri, remove_files)[0]: