summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/lib/devtool/standard.py270
1 files changed, 199 insertions, 71 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 9d9031c2b3..d55d504a14 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -341,19 +341,45 @@ def _check_compatible_recipe(pn, d):
341 "from working. You will need to disable this " 341 "from working. You will need to disable this "
342 "first." % pn) 342 "first." % pn)
343 343
344def _move_file(src, dst): 344def _dry_run_copy(src, dst, dry_run_outdir, base_outdir):
345 """Move a file. Creates all the directory components of destination path.""" 345 """Common function for copying a file to the dry run output directory"""
346 relpath = os.path.relpath(dst, base_outdir)
347 if relpath.startswith('..'):
348 raise Exception('Incorrect base path %s for path %s' % (base_outdir, dst))
349 dst = os.path.join(dry_run_outdir, relpath)
346 dst_d = os.path.dirname(dst) 350 dst_d = os.path.dirname(dst)
347 if dst_d: 351 if dst_d:
348 bb.utils.mkdirhier(dst_d) 352 bb.utils.mkdirhier(dst_d)
349 shutil.move(src, dst) 353 # Don't overwrite existing files, otherwise in the case of an upgrade
354 # the dry-run written out recipe will be overwritten with an unmodified
355 # version
356 if not os.path.exists(dst):
357 shutil.copy(src, dst)
358
359def _move_file(src, dst, dry_run_outdir=None, base_outdir=None):
360 """Move a file. Creates all the directory components of destination path."""
361 dry_run_suffix = ' (dry-run)' if dry_run_outdir else ''
362 logger.debug('Moving %s to %s%s' % (src, dst, dry_run_suffix))
363 if dry_run_outdir:
364 # We want to copy here, not move
365 _dry_run_copy(src, dst, dry_run_outdir, base_outdir)
366 else:
367 dst_d = os.path.dirname(dst)
368 if dst_d:
369 bb.utils.mkdirhier(dst_d)
370 shutil.move(src, dst)
350 371
351def _copy_file(src, dst): 372def _copy_file(src, dst, dry_run_outdir=None):
352 """Copy a file. Creates all the directory components of destination path.""" 373 """Copy a file. Creates all the directory components of destination path."""
353 dst_d = os.path.dirname(dst) 374 dry_run_suffix = ' (dry-run)' if dry_run_outdir else ''
354 if dst_d: 375 logger.debug('Copying %s to %s%s' % (src, dst, dry_run_suffix))
355 bb.utils.mkdirhier(dst_d) 376 if dry_run_outdir:
356 shutil.copy(src, dst) 377 _dry_run_copy(src, dst, dry_run_outdir, base_outdir)
378 else:
379 dst_d = os.path.dirname(dst)
380 if dst_d:
381 bb.utils.mkdirhier(dst_d)
382 shutil.copy(src, dst)
357 383
358def _git_ls_tree(repodir, treeish='HEAD', recursive=False): 384def _git_ls_tree(repodir, treeish='HEAD', recursive=False):
359 """List contents of a git treeish""" 385 """List contents of a git treeish"""
@@ -1054,8 +1080,11 @@ def _replace_srcuri_entry(srcuri, filename, newentry):
1054 srcuri.insert(i, newentry) 1080 srcuri.insert(i, newentry)
1055 break 1081 break
1056 1082
1057def _remove_source_files(append, files, destpath, no_report_remove=False): 1083def _remove_source_files(append, files, destpath, no_report_remove=False, dry_run=False):
1058 """Unlink existing patch files""" 1084 """Unlink existing patch files"""
1085
1086 dry_run_suffix = ' (dry-run)' if dry_run else ''
1087
1059 for path in files: 1088 for path in files:
1060 if append: 1089 if append:
1061 if not destpath: 1090 if not destpath:
@@ -1064,19 +1093,20 @@ def _remove_source_files(append, files, destpath, no_report_remove=False):
1064 1093
1065 if os.path.exists(path): 1094 if os.path.exists(path):
1066 if not no_report_remove: 1095 if not no_report_remove:
1067 logger.info('Removing file %s' % path) 1096 logger.info('Removing file %s%s' % (path, dry_run_suffix))
1068 # FIXME "git rm" here would be nice if the file in question is 1097 if not dry_run:
1069 # tracked 1098 # FIXME "git rm" here would be nice if the file in question is
1070 # FIXME there's a chance that this file is referred to by 1099 # tracked
1071 # another recipe, in which case deleting wouldn't be the 1100 # FIXME there's a chance that this file is referred to by
1072 # right thing to do 1101 # another recipe, in which case deleting wouldn't be the
1073 os.remove(path) 1102 # right thing to do
1074 # Remove directory if empty 1103 os.remove(path)
1075 try: 1104 # Remove directory if empty
1076 os.rmdir(os.path.dirname(path)) 1105 try:
1077 except OSError as ose: 1106 os.rmdir(os.path.dirname(path))
1078 if ose.errno != errno.ENOTEMPTY: 1107 except OSError as ose:
1079 raise 1108 if ose.errno != errno.ENOTEMPTY:
1109 raise
1080 1110
1081 1111
1082def _export_patches(srctree, rd, start_rev, destdir, changed_revs=None): 1112def _export_patches(srctree, rd, start_rev, destdir, changed_revs=None):
@@ -1277,13 +1307,16 @@ def _determine_files_dir(rd):
1277 return os.path.join(recipedir, rd.getVar('BPN')) 1307 return os.path.join(recipedir, rd.getVar('BPN'))
1278 1308
1279 1309
1280def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove): 1310def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove, dry_run_outdir=None):
1281 """Implement the 'srcrev' mode of update-recipe""" 1311 """Implement the 'srcrev' mode of update-recipe"""
1282 import bb 1312 import bb
1283 import oe.recipeutils 1313 import oe.recipeutils
1284 1314
1315 dry_run_suffix = ' (dry-run)' if dry_run_outdir else ''
1316
1285 recipefile = rd.getVar('FILE') 1317 recipefile = rd.getVar('FILE')
1286 logger.info('Updating SRCREV in recipe %s' % os.path.basename(recipefile)) 1318 recipedir = os.path.basename(recipefile)
1319 logger.info('Updating SRCREV in recipe %s%s' % (recipedir, dry_run_suffix))
1287 1320
1288 # Get HEAD revision 1321 # Get HEAD revision
1289 try: 1322 try:
@@ -1303,6 +1336,7 @@ def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wi
1303 srcuri = orig_src_uri.split() 1336 srcuri = orig_src_uri.split()
1304 tempdir = tempfile.mkdtemp(prefix='devtool') 1337 tempdir = tempfile.mkdtemp(prefix='devtool')
1305 update_srcuri = False 1338 update_srcuri = False
1339 appendfile = None
1306 try: 1340 try:
1307 local_files_dir = tempfile.mkdtemp(dir=tempdir) 1341 local_files_dir = tempfile.mkdtemp(dir=tempdir)
1308 srctreebase = workspace[recipename]['srctreebase'] 1342 srctreebase = workspace[recipename]['srctreebase']
@@ -1328,29 +1362,36 @@ def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wi
1328 if update_srcuri: 1362 if update_srcuri:
1329 removevalues = {'SRC_URI': removedentries} 1363 removevalues = {'SRC_URI': removedentries}
1330 patchfields['SRC_URI'] = '\\\n '.join(srcuri) 1364 patchfields['SRC_URI'] = '\\\n '.join(srcuri)
1331 _, destpath = oe.recipeutils.bbappend_recipe( 1365 if dry_run_outdir:
1332 rd, appendlayerdir, files, wildcardver=wildcard_version, 1366 logger.info('Creating bbappend (dry-run)')
1333 extralines=patchfields, removevalues=removevalues) 1367 else:
1368 appendfile, destpath = oe.recipeutils.bbappend_recipe(
1369 rd, appendlayerdir, files, wildcardver=wildcard_version,
1370 extralines=patchfields, removevalues=removevalues,
1371 redirect_output=dry_run_outdir)
1334 else: 1372 else:
1335 files_dir = _determine_files_dir(rd) 1373 files_dir = _determine_files_dir(rd)
1336 for basepath, path in upd_f.items(): 1374 for basepath, path in upd_f.items():
1337 logger.info('Updating file %s' % basepath) 1375 logger.info('Updating file %s%s' % (basepath, dry_run_suffix))
1338 if os.path.isabs(basepath): 1376 if os.path.isabs(basepath):
1339 # Original file (probably with subdir pointing inside source tree) 1377 # Original file (probably with subdir pointing inside source tree)
1340 # so we do not want to move it, just copy 1378 # so we do not want to move it, just copy
1341 _copy_file(basepath, path) 1379 _copy_file(basepath, path, dry_run_outdir=dry_run_outdir, base_outdir=recipedir)
1342 else: 1380 else:
1343 _move_file(os.path.join(local_files_dir, basepath), path) 1381 _move_file(os.path.join(local_files_dir, basepath), path,
1382 dry_run_outdir=dry_run_outdir, base_outdir=recipedir)
1344 update_srcuri= True 1383 update_srcuri= True
1345 for basepath, path in new_f.items(): 1384 for basepath, path in new_f.items():
1346 logger.info('Adding new file %s' % basepath) 1385 logger.info('Adding new file %s%s' % (basepath, dry_run_suffix))
1347 _move_file(os.path.join(local_files_dir, basepath), 1386 _move_file(os.path.join(local_files_dir, basepath),
1348 os.path.join(files_dir, basepath)) 1387 os.path.join(files_dir, basepath),
1388 dry_run_outdir=dry_run_outdir,
1389 base_outdir=recipedir)
1349 srcuri.append('file://%s' % basepath) 1390 srcuri.append('file://%s' % basepath)
1350 update_srcuri = True 1391 update_srcuri = True
1351 if update_srcuri: 1392 if update_srcuri:
1352 patchfields['SRC_URI'] = ' '.join(srcuri) 1393 patchfields['SRC_URI'] = ' '.join(srcuri)
1353 oe.recipeutils.patch_recipe(rd, recipefile, patchfields) 1394 ret = oe.recipeutils.patch_recipe(rd, recipefile, patchfields, redirect_output=dry_run_outdir)
1354 finally: 1395 finally:
1355 shutil.rmtree(tempdir) 1396 shutil.rmtree(tempdir)
1356 if not 'git://' in orig_src_uri: 1397 if not 'git://' in orig_src_uri:
@@ -1358,15 +1399,16 @@ def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wi
1358 'point to a git repository where you have pushed your ' 1399 'point to a git repository where you have pushed your '
1359 'changes') 1400 'changes')
1360 1401
1361 _remove_source_files(appendlayerdir, remove_files, destpath, no_report_remove) 1402 _remove_source_files(appendlayerdir, remove_files, destpath, no_report_remove, dry_run=dry_run_outdir)
1362 return True 1403 return True, appendfile, remove_files
1363 1404
1364def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove, initial_rev): 1405def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove, initial_rev, dry_run_outdir=None):
1365 """Implement the 'patch' mode of update-recipe""" 1406 """Implement the 'patch' mode of update-recipe"""
1366 import bb 1407 import bb
1367 import oe.recipeutils 1408 import oe.recipeutils
1368 1409
1369 recipefile = rd.getVar('FILE') 1410 recipefile = rd.getVar('FILE')
1411 recipedir = os.path.dirname(recipefile)
1370 append = workspace[recipename]['bbappend'] 1412 append = workspace[recipename]['bbappend']
1371 if not os.path.exists(append): 1413 if not os.path.exists(append):
1372 raise DevtoolError('unable to find workspace bbappend for recipe %s' % 1414 raise DevtoolError('unable to find workspace bbappend for recipe %s' %
@@ -1377,10 +1419,13 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1377 raise DevtoolError('Unable to find initial revision - please specify ' 1419 raise DevtoolError('Unable to find initial revision - please specify '
1378 'it with --initial-rev') 1420 'it with --initial-rev')
1379 1421
1422 appendfile = None
1380 dl_dir = rd.getVar('DL_DIR') 1423 dl_dir = rd.getVar('DL_DIR')
1381 if not dl_dir.endswith('/'): 1424 if not dl_dir.endswith('/'):
1382 dl_dir += '/' 1425 dl_dir += '/'
1383 1426
1427 dry_run_suffix = ' (dry-run)' if dry_run_outdir else ''
1428
1384 tempdir = tempfile.mkdtemp(prefix='devtool') 1429 tempdir = tempfile.mkdtemp(prefix='devtool')
1385 try: 1430 try:
1386 local_files_dir = tempfile.mkdtemp(dir=tempdir) 1431 local_files_dir = tempfile.mkdtemp(dir=tempdir)
@@ -1418,10 +1463,11 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1418 remaining = ['file://' + os.path.basename(item) for 1463 remaining = ['file://' + os.path.basename(item) for
1419 item in remaining] 1464 item in remaining]
1420 removevalues = {'SRC_URI': removedentries + remaining} 1465 removevalues = {'SRC_URI': removedentries + remaining}
1421 _, destpath = oe.recipeutils.bbappend_recipe( 1466 appendfile, destpath = oe.recipeutils.bbappend_recipe(
1422 rd, appendlayerdir, files, 1467 rd, appendlayerdir, files,
1423 wildcardver=wildcard_version, 1468 wildcardver=wildcard_version,
1424 removevalues=removevalues) 1469 removevalues=removevalues,
1470 redirect_output=dry_run_outdir)
1425 else: 1471 else:
1426 logger.info('No patches or local source files needed updating') 1472 logger.info('No patches or local source files needed updating')
1427 else: 1473 else:
@@ -1432,9 +1478,11 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1432 if os.path.isabs(basepath): 1478 if os.path.isabs(basepath):
1433 # Original file (probably with subdir pointing inside source tree) 1479 # Original file (probably with subdir pointing inside source tree)
1434 # so we do not want to move it, just copy 1480 # so we do not want to move it, just copy
1435 _copy_file(basepath, path) 1481 _copy_file(basepath, path,
1482 dry_run_outdir=dry_run_outdir, base_outdir=recipedir)
1436 else: 1483 else:
1437 _move_file(os.path.join(local_files_dir, basepath), path) 1484 _move_file(os.path.join(local_files_dir, basepath), path,
1485 dry_run_outdir=dry_run_outdir, base_outdir=recipedir)
1438 updatefiles = True 1486 updatefiles = True
1439 for basepath, path in upd_p.items(): 1487 for basepath, path in upd_p.items():
1440 patchfn = os.path.join(patches_dir, basepath) 1488 patchfn = os.path.join(patches_dir, basepath)
@@ -1446,39 +1494,45 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil
1446 _replace_srcuri_entry(srcuri, basepath, 'file://%s' % basepath) 1494 _replace_srcuri_entry(srcuri, basepath, 'file://%s' % basepath)
1447 updaterecipe = True 1495 updaterecipe = True
1448 else: 1496 else:
1449 logger.info('Updating patch %s' % basepath) 1497 logger.info('Updating patch %s%s' % (basepath, dry_run_suffix))
1450 logger.debug('Moving new patch %s to %s' % (patchfn, path)) 1498 _move_file(patchfn, path,
1451 _move_file(patchfn, path) 1499 dry_run_outdir=dry_run_outdir, base_outdir=recipedir)
1452 updatefiles = True 1500 updatefiles = True
1453 # Add any new files 1501 # Add any new files
1454 for basepath, path in new_f.items(): 1502 for basepath, path in new_f.items():
1455 logger.info('Adding new file %s' % basepath) 1503 logger.info('Adding new file %s%s' % (basepath, dry_run_suffix))
1456 _move_file(os.path.join(local_files_dir, basepath), 1504 _move_file(os.path.join(local_files_dir, basepath),
1457 os.path.join(files_dir, basepath)) 1505 os.path.join(files_dir, basepath),
1506 dry_run_outdir=dry_run_outdir,
1507 base_outdir=recipedir)
1458 srcuri.append('file://%s' % basepath) 1508 srcuri.append('file://%s' % basepath)
1459 updaterecipe = True 1509 updaterecipe = True
1460 for basepath, path in new_p.items(): 1510 for basepath, path in new_p.items():
1461 logger.info('Adding new patch %s' % basepath) 1511 logger.info('Adding new patch %s%s' % (basepath, dry_run_suffix))
1462 _move_file(os.path.join(patches_dir, basepath), 1512 _move_file(os.path.join(patches_dir, basepath),
1463 os.path.join(files_dir, basepath)) 1513 os.path.join(files_dir, basepath),
1514 dry_run_outdir=dry_run_outdir,
1515 base_outdir=recipedir)
1464 srcuri.append('file://%s' % basepath) 1516 srcuri.append('file://%s' % basepath)
1465 updaterecipe = True 1517 updaterecipe = True
1466 # Update recipe, if needed 1518 # Update recipe, if needed
1467 if _remove_file_entries(srcuri, remove_files)[0]: 1519 if _remove_file_entries(srcuri, remove_files)[0]:
1468 updaterecipe = True 1520 updaterecipe = True
1469 if updaterecipe: 1521 if updaterecipe:
1470 logger.info('Updating recipe %s' % os.path.basename(recipefile)) 1522 if not dry_run_outdir:
1471 oe.recipeutils.patch_recipe(rd, recipefile, 1523 logger.info('Updating recipe %s' % os.path.basename(recipefile))
1472 {'SRC_URI': ' '.join(srcuri)}) 1524 ret = oe.recipeutils.patch_recipe(rd, recipefile,
1525 {'SRC_URI': ' '.join(srcuri)},
1526 redirect_output=dry_run_outdir)
1473 elif not updatefiles: 1527 elif not updatefiles:
1474 # Neither patches nor recipe were updated 1528 # Neither patches nor recipe were updated
1475 logger.info('No patches or files need updating') 1529 logger.info('No patches or files need updating')
1476 return False 1530 return False, None, []
1477 finally: 1531 finally:
1478 shutil.rmtree(tempdir) 1532 shutil.rmtree(tempdir)
1479 1533
1480 _remove_source_files(appendlayerdir, remove_files, destpath, no_report_remove) 1534 _remove_source_files(appendlayerdir, remove_files, destpath, no_report_remove, dry_run=dry_run_outdir)
1481 return True 1535 return True, appendfile, remove_files
1482 1536
1483def _guess_recipe_update_mode(srctree, rdata): 1537def _guess_recipe_update_mode(srctree, rdata):
1484 """Guess the recipe update mode to use""" 1538 """Guess the recipe update mode to use"""
@@ -1502,18 +1556,18 @@ def _guess_recipe_update_mode(srctree, rdata):
1502 1556
1503 return 'patch' 1557 return 'patch'
1504 1558
1505def _update_recipe(recipename, workspace, rd, mode, appendlayerdir, wildcard_version, no_remove, initial_rev, no_report_remove=False): 1559def _update_recipe(recipename, workspace, rd, mode, appendlayerdir, wildcard_version, no_remove, initial_rev, no_report_remove=False, dry_run_outdir=None):
1506 srctree = workspace[recipename]['srctree'] 1560 srctree = workspace[recipename]['srctree']
1507 if mode == 'auto': 1561 if mode == 'auto':
1508 mode = _guess_recipe_update_mode(srctree, rd) 1562 mode = _guess_recipe_update_mode(srctree, rd)
1509 1563
1510 if mode == 'srcrev': 1564 if mode == 'srcrev':
1511 updated = _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove) 1565 updated, appendfile, removed = _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove, dry_run_outdir)
1512 elif mode == 'patch': 1566 elif mode == 'patch':
1513 updated = _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove, initial_rev) 1567 updated, appendfile, removed = _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove, initial_rev, dry_run_outdir)
1514 else: 1568 else:
1515 raise DevtoolError('update_recipe: invalid mode %s' % mode) 1569 raise DevtoolError('update_recipe: invalid mode %s' % mode)
1516 return updated 1570 return updated, appendfile, removed
1517 1571
1518def update_recipe(args, config, basepath, workspace): 1572def update_recipe(args, config, basepath, workspace):
1519 """Entry point for the devtool 'update-recipe' subcommand""" 1573 """Entry point for the devtool 'update-recipe' subcommand"""
@@ -1534,7 +1588,12 @@ def update_recipe(args, config, basepath, workspace):
1534 if not rd: 1588 if not rd:
1535 return 1 1589 return 1
1536 1590
1537 updated = _update_recipe(args.recipename, workspace, rd, args.mode, args.append, args.wildcard_version, args.no_remove, args.initial_rev) 1591 dry_run_output = None
1592 dry_run_outdir = None
1593 if args.dry_run:
1594 dry_run_output = tempfile.TemporaryDirectory(prefix='devtool')
1595 dry_run_outdir = dry_run_output.name
1596 updated, _, _ = _update_recipe(args.recipename, workspace, rd, args.mode, args.append, args.wildcard_version, args.no_remove, args.initial_rev, dry_run_outdir=dry_run_outdir)
1538 1597
1539 if updated: 1598 if updated:
1540 rf = rd.getVar('FILE') 1599 rf = rd.getVar('FILE')
@@ -1680,6 +1739,8 @@ def finish(args, config, basepath, workspace):
1680 1739
1681 check_workspace_recipe(workspace, args.recipename) 1740 check_workspace_recipe(workspace, args.recipename)
1682 1741
1742 dry_run_suffix = ' (dry-run)' if args.dry_run else ''
1743
1683 # Grab the equivalent of COREBASE without having to initialise tinfoil 1744 # Grab the equivalent of COREBASE without having to initialise tinfoil
1684 corebasedir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) 1745 corebasedir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
1685 1746
@@ -1700,7 +1761,9 @@ def finish(args, config, basepath, workspace):
1700 return 1 1761 return 1
1701 1762
1702 destlayerdir = _get_layer(args.destination, tinfoil.config_data) 1763 destlayerdir = _get_layer(args.destination, tinfoil.config_data)
1703 origlayerdir = oe.recipeutils.find_layerdir(rd.getVar('FILE')) 1764 recipefile = rd.getVar('FILE')
1765 recipedir = os.path.dirname(recipefile)
1766 origlayerdir = oe.recipeutils.find_layerdir(recipefile)
1704 1767
1705 if not os.path.isdir(destlayerdir): 1768 if not os.path.isdir(destlayerdir):
1706 raise DevtoolError('Unable to find layer or directory matching "%s"' % args.destination) 1769 raise DevtoolError('Unable to find layer or directory matching "%s"' % args.destination)
@@ -1748,38 +1811,101 @@ def finish(args, config, basepath, workspace):
1748 1811
1749 # Actually update the recipe / bbappend 1812 # Actually update the recipe / bbappend
1750 removing_original = (origpath and origfilelist and oe.recipeutils.find_layerdir(origpath) == destlayerbasedir) 1813 removing_original = (origpath and origfilelist and oe.recipeutils.find_layerdir(origpath) == destlayerbasedir)
1751 _update_recipe(args.recipename, workspace, rd, args.mode, appendlayerdir, wildcard_version=True, no_remove=False, initial_rev=args.initial_rev, no_report_remove=removing_original) 1814 dry_run_output = None
1815 dry_run_outdir = None
1816 if args.dry_run:
1817 dry_run_output = tempfile.TemporaryDirectory(prefix='devtool')
1818 dry_run_outdir = dry_run_output.name
1819 updated, appendfile, removed = _update_recipe(args.recipename, workspace, rd, args.mode, appendlayerdir, wildcard_version=True, no_remove=False, no_report_remove=removing_original, initial_rev=args.initial_rev, dry_run_outdir=dry_run_outdir)
1820 removed = [os.path.relpath(pth, recipedir) for pth in removed]
1752 1821
1753 # Remove any old files in the case of an upgrade 1822 # Remove any old files in the case of an upgrade
1754 recipedir = os.path.dirname(rd.getVar('FILE'))
1755 if removing_original: 1823 if removing_original:
1756 for fn in origfilelist: 1824 for fn in origfilelist:
1757 fnp = os.path.join(origpath, fn) 1825 fnp = os.path.join(origpath, fn)
1758 if not os.path.exists(os.path.join(recipedir, fn)): 1826 if fn in removed or not os.path.exists(os.path.join(recipedir, fn)):
1759 logger.info('Removing file %s' % fnp) 1827 logger.info('Removing file %s%s' % (fnp, dry_run_suffix))
1760 try: 1828 if not args.dry_run:
1761 os.remove(fnp) 1829 try:
1762 except FileNotFoundError: 1830 os.remove(fnp)
1763 pass 1831 except FileNotFoundError:
1832 pass
1764 1833
1765 if origlayerdir == config.workspace_path and destpath: 1834 if origlayerdir == config.workspace_path and destpath:
1766 # Recipe file itself is in the workspace - need to move it and any 1835 # Recipe file itself is in the workspace - need to move it and any
1767 # associated files to the specified layer 1836 # associated files to the specified layer
1768 no_clean = True 1837 no_clean = True
1769 logger.info('Moving recipe file to %s' % destpath) 1838 logger.info('Moving recipe file to %s%s' % (destpath, dry_run_suffix))
1770 for root, _, files in os.walk(recipedir): 1839 for root, _, files in os.walk(recipedir):
1771 for fn in files: 1840 for fn in files:
1772 srcpath = os.path.join(root, fn) 1841 srcpath = os.path.join(root, fn)
1773 relpth = os.path.relpath(os.path.dirname(srcpath), recipedir) 1842 relpth = os.path.relpath(os.path.dirname(srcpath), recipedir)
1774 destdir = os.path.abspath(os.path.join(destpath, relpth)) 1843 destdir = os.path.abspath(os.path.join(destpath, relpth))
1775 bb.utils.mkdirhier(destdir) 1844 destfp = os.path.join(destdir, fn)
1776 shutil.move(srcpath, os.path.join(destdir, fn)) 1845 _move_file(srcpath, destfp, dry_run_outdir=dry_run_outdir, base_outdir=destpath)
1777 1846
1847 if dry_run_outdir:
1848 import difflib
1849 comparelist = []
1850 for root, _, files in os.walk(dry_run_outdir):
1851 for fn in files:
1852 outf = os.path.join(root, fn)
1853 relf = os.path.relpath(outf, dry_run_outdir)
1854 logger.debug('dry-run: output file %s' % relf)
1855 if fn.endswith('.bb'):
1856 if origfilelist and origpath and destpath:
1857 # Need to match this up with the pre-upgrade recipe file
1858 for origf in origfilelist:
1859 if origf.endswith('.bb'):
1860 comparelist.append((os.path.abspath(os.path.join(origpath, origf)),
1861 outf,
1862 os.path.abspath(os.path.join(destpath, relf))))
1863 break
1864 else:
1865 # Compare to the existing recipe
1866 comparelist.append((recipefile, outf, recipefile))
1867 elif fn.endswith('.bbappend'):
1868 if appendfile:
1869 if os.path.exists(appendfile):
1870 comparelist.append((appendfile, outf, appendfile))
1871 else:
1872 comparelist.append((None, outf, appendfile))
1873 else:
1874 if destpath:
1875 recipedest = destpath
1876 elif appendfile:
1877 recipedest = os.path.dirname(appendfile)
1878 else:
1879 recipedest = os.path.dirname(recipefile)
1880 destfp = os.path.join(recipedest, relf)
1881 if os.path.exists(destfp):
1882 comparelist.append((destfp, outf, destfp))
1883 output = ''
1884 for oldfile, newfile, newfileshow in comparelist:
1885 if oldfile:
1886 with open(oldfile, 'r') as f:
1887 oldlines = f.readlines()
1888 else:
1889 oldfile = '/dev/null'
1890 oldlines = []
1891 with open(newfile, 'r') as f:
1892 newlines = f.readlines()
1893 if not newfileshow:
1894 newfileshow = newfile
1895 diff = difflib.unified_diff(oldlines, newlines, oldfile, newfileshow)
1896 difflines = list(diff)
1897 if difflines:
1898 output += ''.join(difflines)
1899 if output:
1900 logger.info('Diff of changed files:\n%s' % output)
1778 finally: 1901 finally:
1779 tinfoil.shutdown() 1902 tinfoil.shutdown()
1780 1903
1781 # Everything else has succeeded, we can now reset 1904 # Everything else has succeeded, we can now reset
1782 _reset([args.recipename], no_clean=no_clean, config=config, basepath=basepath, workspace=workspace) 1905 if args.dry_run:
1906 logger.info('Resetting recipe (dry-run)')
1907 else:
1908 _reset([args.recipename], no_clean=no_clean, config=config, basepath=basepath, workspace=workspace)
1783 1909
1784 return 0 1910 return 0
1785 1911
@@ -1873,6 +1999,7 @@ def register_commands(subparsers, context):
1873 parser_update_recipe.add_argument('--append', '-a', help='Write changes to a bbappend in the specified layer instead of the recipe', metavar='LAYERDIR') 1999 parser_update_recipe.add_argument('--append', '-a', help='Write changes to a bbappend in the specified layer instead of the recipe', metavar='LAYERDIR')
1874 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') 2000 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')
1875 parser_update_recipe.add_argument('--no-remove', '-n', action="store_true", help='Don\'t remove patches, only add or update') 2001 parser_update_recipe.add_argument('--no-remove', '-n', action="store_true", help='Don\'t remove patches, only add or update')
2002 parser_update_recipe.add_argument('--dry-run', '-N', action="store_true", help='Dry-run (just report changes instead of writing them)')
1876 parser_update_recipe.set_defaults(func=update_recipe) 2003 parser_update_recipe.set_defaults(func=update_recipe)
1877 2004
1878 parser_status = subparsers.add_parser('status', help='Show workspace status', 2005 parser_status = subparsers.add_parser('status', help='Show workspace status',
@@ -1896,4 +2023,5 @@ def register_commands(subparsers, context):
1896 parser_finish.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') 2023 parser_finish.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')
1897 parser_finish.add_argument('--initial-rev', help='Override starting revision for patches') 2024 parser_finish.add_argument('--initial-rev', help='Override starting revision for patches')
1898 parser_finish.add_argument('--force', '-f', action="store_true", help='Force continuing even if there are uncommitted changes in the source tree repository') 2025 parser_finish.add_argument('--force', '-f', action="store_true", help='Force continuing even if there are uncommitted changes in the source tree repository')
2026 parser_finish.add_argument('--dry-run', '-N', action="store_true", help='Dry-run (just report changes instead of writing them)')
1899 parser_finish.set_defaults(func=finish) 2027 parser_finish.set_defaults(func=finish)