diff options
Diffstat (limited to 'scripts/lib/devtool')
-rw-r--r-- | scripts/lib/devtool/standard.py | 270 |
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 | ||
344 | def _move_file(src, dst): | 344 | def _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 | |||
359 | def _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 | ||
351 | def _copy_file(src, dst): | 372 | def _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 | ||
358 | def _git_ls_tree(repodir, treeish='HEAD', recursive=False): | 384 | def _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 | ||
1057 | def _remove_source_files(append, files, destpath, no_report_remove=False): | 1083 | def _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 | ||
1082 | def _export_patches(srctree, rd, start_rev, destdir, changed_revs=None): | 1112 | def _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 | ||
1280 | def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove): | 1310 | def _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 | ||
1364 | def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wildcard_version, no_remove, no_report_remove, initial_rev): | 1405 | def _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 | ||
1483 | def _guess_recipe_update_mode(srctree, rdata): | 1537 | def _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 | ||
1505 | def _update_recipe(recipename, workspace, rd, mode, appendlayerdir, wildcard_version, no_remove, initial_rev, no_report_remove=False): | 1559 | def _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 | ||
1518 | def update_recipe(args, config, basepath, workspace): | 1572 | def 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) |