diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-05-01 22:36:50 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-05-21 12:08:04 +0100 |
commit | 6d77296d83f87ea7f6ca0363a947d3eac721459b (patch) | |
tree | bdd4f17e69cffdcc39e20e43a917938736482e45 /scripts/lib/devtool/standard.py | |
parent | d6ae8d2004f8ac3aab4571e0077d406b2d19b542 (diff) | |
download | poky-6d77296d83f87ea7f6ca0363a947d3eac721459b.tar.gz |
devtool: Drop oe-local-files and simplify
The only real reason for oe-local-files was to support S = WORKDIR. With changes to
drop support for that, it makes sense to simplify devtool and to try and make both
the code and the processes/workflows simpler.
This patch drops support for S = WORKDIR, removes oe-local-files and then updates
the test cases to match this new situation.
At the code level, we assume we can always now track code changes using git and
that things committed into git are handled as patches (as before) but delta against
HEAD is saved as specific file level changes to the recipe.
One test is disabled as it is no longer approproate. It is being keped until we can
make WORKDIR != UNPACKDIR at which point it should be revisited.
(From OE-Core rev: ce8190c519052fed10b5233697b69a75868db45a)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/devtool/standard.py')
-rw-r--r-- | scripts/lib/devtool/standard.py | 194 |
1 files changed, 59 insertions, 135 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py index 05161942b7..1d0fe13788 100644 --- a/scripts/lib/devtool/standard.py +++ b/scripts/lib/devtool/standard.py | |||
@@ -387,6 +387,19 @@ def _git_ls_tree(repodir, treeish='HEAD', recursive=False): | |||
387 | ret[split[3]] = split[0:3] | 387 | ret[split[3]] = split[0:3] |
388 | return ret | 388 | return ret |
389 | 389 | ||
390 | def _git_modified(repodir): | ||
391 | """List the difference between HEAD and the index""" | ||
392 | import bb | ||
393 | cmd = ['git', 'status', '--porcelain'] | ||
394 | out, _ = bb.process.run(cmd, cwd=repodir) | ||
395 | ret = [] | ||
396 | if out: | ||
397 | for line in out.split("\n"): | ||
398 | if line and not line.startswith('??'): | ||
399 | ret.append(line[3:]) | ||
400 | return ret | ||
401 | |||
402 | |||
390 | def _git_exclude_path(srctree, path): | 403 | def _git_exclude_path(srctree, path): |
391 | """Return pathspec (list of paths) that excludes certain path""" | 404 | """Return pathspec (list of paths) that excludes certain path""" |
392 | # NOTE: "Filtering out" files/paths in this way is not entirely reliable - | 405 | # NOTE: "Filtering out" files/paths in this way is not entirely reliable - |
@@ -460,32 +473,6 @@ def sync(args, config, basepath, workspace): | |||
460 | finally: | 473 | finally: |
461 | tinfoil.shutdown() | 474 | tinfoil.shutdown() |
462 | 475 | ||
463 | def symlink_oelocal_files_srctree(rd, srctree): | ||
464 | import oe.patch | ||
465 | if os.path.abspath(rd.getVar('S')) == os.path.abspath(rd.getVar('WORKDIR')): | ||
466 | # If recipe extracts to ${WORKDIR}, symlink the files into the srctree | ||
467 | # (otherwise the recipe won't build as expected) | ||
468 | local_files_dir = os.path.join(srctree, 'oe-local-files') | ||
469 | addfiles = [] | ||
470 | for root, _, files in os.walk(local_files_dir): | ||
471 | relpth = os.path.relpath(root, local_files_dir) | ||
472 | if relpth != '.': | ||
473 | bb.utils.mkdirhier(os.path.join(srctree, relpth)) | ||
474 | for fn in files: | ||
475 | if fn == '.gitignore': | ||
476 | continue | ||
477 | destpth = os.path.join(srctree, relpth, fn) | ||
478 | if os.path.exists(destpth): | ||
479 | os.unlink(destpth) | ||
480 | if relpth != '.': | ||
481 | back_relpth = os.path.relpath(local_files_dir, root) | ||
482 | os.symlink('%s/oe-local-files/%s/%s' % (back_relpth, relpth, fn), destpth) | ||
483 | else: | ||
484 | os.symlink('oe-local-files/%s' % fn, destpth) | ||
485 | addfiles.append(os.path.join(relpth, fn)) | ||
486 | if addfiles: | ||
487 | oe.patch.GitApplyTree.commitIgnored("Add local file symlinks", dir=srctree, files=addfiles, d=rd) | ||
488 | |||
489 | def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, workspace, fixed_setup, d, tinfoil, no_overrides=False): | 476 | def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, workspace, fixed_setup, d, tinfoil, no_overrides=False): |
490 | """Extract sources of a recipe""" | 477 | """Extract sources of a recipe""" |
491 | import oe.recipeutils | 478 | import oe.recipeutils |
@@ -657,9 +644,6 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works | |||
657 | elif not os.path.exists(workshareddir): | 644 | elif not os.path.exists(workshareddir): |
658 | oe.path.copyhardlinktree(srcsubdir, workshareddir) | 645 | oe.path.copyhardlinktree(srcsubdir, workshareddir) |
659 | 646 | ||
660 | tempdir_localdir = os.path.join(tempdir, 'oe-local-files') | ||
661 | srctree_localdir = os.path.join(srctree, 'oe-local-files') | ||
662 | |||
663 | if sync: | 647 | if sync: |
664 | try: | 648 | try: |
665 | logger.info('Backing up current %s branch as branch: %s.bak' % (devbranch, devbranch)) | 649 | logger.info('Backing up current %s branch as branch: %s.bak' % (devbranch, devbranch)) |
@@ -674,29 +658,8 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works | |||
674 | except bb.process.ExecutionError as e: | 658 | except bb.process.ExecutionError as e: |
675 | raise DevtoolError("Error when syncing source files to local checkout: %s" % str(e)) | 659 | raise DevtoolError("Error when syncing source files to local checkout: %s" % str(e)) |
676 | 660 | ||
677 | # Move the oe-local-files directory to srctree. | ||
678 | # As oe-local-files is not part of the constructed git tree, | ||
679 | # removing it directly during the synchronization might surprise | ||
680 | # the user. Instead, we move it to oe-local-files.bak and remind | ||
681 | # the user in the log message. | ||
682 | if os.path.exists(srctree_localdir + '.bak'): | ||
683 | shutil.rmtree(srctree_localdir + '.bak') | ||
684 | |||
685 | if os.path.exists(srctree_localdir): | ||
686 | logger.info('Backing up current local file directory %s' % srctree_localdir) | ||
687 | shutil.move(srctree_localdir, srctree_localdir + '.bak') | ||
688 | |||
689 | if os.path.exists(tempdir_localdir): | ||
690 | logger.info('Syncing local source files to srctree...') | ||
691 | shutil.copytree(tempdir_localdir, srctree_localdir) | ||
692 | else: | 661 | else: |
693 | # Move oe-local-files directory to srctree | ||
694 | if os.path.exists(tempdir_localdir): | ||
695 | logger.info('Adding local source files to srctree...') | ||
696 | shutil.move(tempdir_localdir, srcsubdir) | ||
697 | |||
698 | shutil.move(srcsubdir, srctree) | 662 | shutil.move(srcsubdir, srctree) |
699 | symlink_oelocal_files_srctree(d, srctree) | ||
700 | 663 | ||
701 | if is_kernel_yocto: | 664 | if is_kernel_yocto: |
702 | logger.info('Copying kernel config to srctree') | 665 | logger.info('Copying kernel config to srctree') |
@@ -852,34 +815,22 @@ def modify(args, config, basepath, workspace): | |||
852 | if (os.path.exists(srcdir) and os.listdir(srcdir)) and (kernelVersion in staging_kerVer and staging_kbranch == kbranch): | 815 | if (os.path.exists(srcdir) and os.listdir(srcdir)) and (kernelVersion in staging_kerVer and staging_kbranch == kbranch): |
853 | oe.path.copyhardlinktree(srcdir, srctree) | 816 | oe.path.copyhardlinktree(srcdir, srctree) |
854 | workdir = rd.getVar('WORKDIR') | 817 | workdir = rd.getVar('WORKDIR') |
818 | unpackdir = rd.getVar('UNPACKDIR') | ||
855 | srcsubdir = rd.getVar('S') | 819 | srcsubdir = rd.getVar('S') |
856 | localfilesdir = os.path.join(srctree, 'oe-local-files') | 820 | localfilesdir = os.path.join(srctree, 'oe-local-files') |
857 | # Move local source files into separate subdir | ||
858 | recipe_patches = [os.path.basename(patch) for patch in oe.recipeutils.get_recipe_patches(rd)] | ||
859 | local_files = oe.recipeutils.get_recipe_local_files(rd) | ||
860 | 821 | ||
861 | for key in local_files.copy(): | 822 | # Add locally copied files to gitignore as we add back to the metadata directly |
862 | if key.endswith('scc'): | 823 | local_files = oe.recipeutils.get_recipe_local_files(rd) |
863 | sccfile = open(local_files[key], 'r') | ||
864 | for l in sccfile: | ||
865 | line = l.split() | ||
866 | if line and line[0] in ('kconf', 'patch'): | ||
867 | cfg = os.path.join(os.path.dirname(local_files[key]), line[-1]) | ||
868 | if not cfg in local_files.values(): | ||
869 | local_files[line[-1]] = cfg | ||
870 | shutil.copy2(cfg, workdir) | ||
871 | sccfile.close() | ||
872 | |||
873 | # Ignore local files with subdir={BP} | ||
874 | srcabspath = os.path.abspath(srcsubdir) | 824 | srcabspath = os.path.abspath(srcsubdir) |
875 | local_files = [fname for fname in local_files if os.path.exists(os.path.join(workdir, fname)) and (srcabspath == workdir or not os.path.join(workdir, fname).startswith(srcabspath + os.sep))] | 825 | local_files = [fname for fname in local_files if |
826 | os.path.exists(os.path.join(unpackdir, fname)) and | ||
827 | srcabspath == unpackdir] | ||
876 | if local_files: | 828 | if local_files: |
877 | for fname in local_files: | 829 | with open(os.path.join(srctree, '.gitignore'), 'a+') as f: |
878 | _move_file(os.path.join(workdir, fname), os.path.join(srctree, 'oe-local-files', fname)) | 830 | f.write('# Ignore local files, by default. Remove following lines' |
879 | with open(os.path.join(srctree, 'oe-local-files', '.gitignore'), 'w') as f: | 831 | 'if you want to commit the directory to Git\n') |
880 | f.write('# Ignore local files, by default. Remove this file if you want to commit the directory to Git\n*\n') | 832 | for fname in local_files: |
881 | 833 | f.write('%s\n' % fname) | |
882 | symlink_oelocal_files_srctree(rd, srctree) | ||
883 | 834 | ||
884 | task = 'do_configure' | 835 | task = 'do_configure' |
885 | res = tinfoil.build_targets(pn, task, handle_events=True) | 836 | res = tinfoil.build_targets(pn, task, handle_events=True) |
@@ -1478,6 +1429,7 @@ def _export_local_files(srctree, rd, destdir, srctreebase): | |||
1478 | # Instead they are directly copied over the original source files (in | 1429 | # Instead they are directly copied over the original source files (in |
1479 | # recipe space). | 1430 | # recipe space). |
1480 | existing_files = oe.recipeutils.get_recipe_local_files(rd) | 1431 | existing_files = oe.recipeutils.get_recipe_local_files(rd) |
1432 | |||
1481 | new_set = None | 1433 | new_set = None |
1482 | updated = OrderedDict() | 1434 | updated = OrderedDict() |
1483 | added = OrderedDict() | 1435 | added = OrderedDict() |
@@ -1494,24 +1446,28 @@ def _export_local_files(srctree, rd, destdir, srctreebase): | |||
1494 | if branchname.startswith(override_branch_prefix): | 1446 | if branchname.startswith(override_branch_prefix): |
1495 | return (updated, added, removed) | 1447 | return (updated, added, removed) |
1496 | 1448 | ||
1497 | local_files_dir = os.path.join(srctreebase, 'oe-local-files') | 1449 | files = _git_modified(srctree) |
1498 | git_files = _git_ls_tree(srctree) | 1450 | #if not files: |
1499 | if 'oe-local-files' in git_files: | 1451 | # files = _ls_tree(srctree) |
1500 | # If tracked by Git, take the files from srctree HEAD. First get | 1452 | for f in files: |
1501 | # the tree object of the directory | 1453 | fullfile = os.path.join(srctree, f) |
1502 | tmp_index = os.path.join(srctree, '.git', 'index.tmp.devtool') | 1454 | if os.path.exists(os.path.join(fullfile, ".git")): |
1503 | tree = git_files['oe-local-files'][2] | 1455 | # submodules handled elsewhere |
1504 | bb.process.run(['git', 'checkout', tree, '--', '.'], cwd=srctree, | 1456 | continue |
1505 | env=dict(os.environ, GIT_WORK_TREE=destdir, | 1457 | if f not in existing_files: |
1506 | GIT_INDEX_FILE=tmp_index)) | 1458 | added[f] = {} |
1507 | new_set = list(_git_ls_tree(srctree, tree, True).keys()) | 1459 | if os.path.isdir(os.path.join(srctree, f)): |
1508 | elif os.path.isdir(local_files_dir): | 1460 | shutil.copytree(fullfile, os.path.join(destdir, f)) |
1509 | # If not tracked by Git, just copy from working copy | 1461 | else: |
1510 | new_set = _ls_tree(local_files_dir) | 1462 | shutil.copy2(fullfile, os.path.join(destdir, f)) |
1511 | bb.process.run(['cp', '-ax', | 1463 | elif not os.path.exists(fullfile): |
1512 | os.path.join(local_files_dir, '.'), destdir]) | 1464 | removed[f] = existing_files[f] |
1513 | else: | 1465 | elif f in existing_files: |
1514 | new_set = [] | 1466 | updated[f] = {'path' : existing_files[f]} |
1467 | if os.path.isdir(os.path.join(srctree, f)): | ||
1468 | shutil.copytree(fullfile, os.path.join(destdir, f)) | ||
1469 | else: | ||
1470 | shutil.copy2(fullfile, os.path.join(destdir, f)) | ||
1515 | 1471 | ||
1516 | # Special handling for kernel config | 1472 | # Special handling for kernel config |
1517 | if bb.data.inherits_class('kernel-yocto', rd): | 1473 | if bb.data.inherits_class('kernel-yocto', rd): |
@@ -1519,17 +1475,14 @@ def _export_local_files(srctree, rd, destdir, srctreebase): | |||
1519 | fragment_path = os.path.join(destdir, fragment_fn) | 1475 | fragment_path = os.path.join(destdir, fragment_fn) |
1520 | if _create_kconfig_diff(srctree, rd, fragment_path): | 1476 | if _create_kconfig_diff(srctree, rd, fragment_path): |
1521 | if os.path.exists(fragment_path): | 1477 | if os.path.exists(fragment_path): |
1522 | if fragment_fn not in new_set: | 1478 | if fragment_fn in removed: |
1523 | new_set.append(fragment_fn) | 1479 | del removed[fragment_fn] |
1524 | # Copy fragment to local-files | 1480 | if fragment_fn not in updated and fragment_fn not in added: |
1525 | if os.path.isdir(local_files_dir): | 1481 | added[fragment_fn] = {} |
1526 | shutil.copy2(fragment_path, local_files_dir) | ||
1527 | else: | 1482 | else: |
1528 | if fragment_fn in new_set: | 1483 | if fragment_fn in updated: |
1529 | new_set.remove(fragment_fn) | 1484 | revoved[fragment_fn] = updated[fragment_fn] |
1530 | # Remove fragment from local-files | 1485 | del updated[fragment_fn] |
1531 | if os.path.exists(os.path.join(local_files_dir, fragment_fn)): | ||
1532 | os.unlink(os.path.join(local_files_dir, fragment_fn)) | ||
1533 | 1486 | ||
1534 | # Special handling for cml1, ccmake, etc bbclasses that generated | 1487 | # Special handling for cml1, ccmake, etc bbclasses that generated |
1535 | # configuration fragment files that are consumed as source files | 1488 | # configuration fragment files that are consumed as source files |
@@ -1537,42 +1490,13 @@ def _export_local_files(srctree, rd, destdir, srctreebase): | |||
1537 | if bb.data.inherits_class(frag_class, rd): | 1490 | if bb.data.inherits_class(frag_class, rd): |
1538 | srcpath = os.path.join(rd.getVar('WORKDIR'), frag_name) | 1491 | srcpath = os.path.join(rd.getVar('WORKDIR'), frag_name) |
1539 | if os.path.exists(srcpath): | 1492 | if os.path.exists(srcpath): |
1540 | if frag_name not in new_set: | 1493 | if frag_name in removed: |
1541 | new_set.append(frag_name) | 1494 | del removed[frag_name] |
1495 | if frag_name not in updated: | ||
1496 | added[frag_name] = {} | ||
1542 | # copy fragment into destdir | 1497 | # copy fragment into destdir |
1543 | shutil.copy2(srcpath, destdir) | 1498 | shutil.copy2(srcpath, destdir) |
1544 | # copy fragment into local files if exists | 1499 | |
1545 | if os.path.isdir(local_files_dir): | ||
1546 | shutil.copy2(srcpath, local_files_dir) | ||
1547 | |||
1548 | if new_set is not None: | ||
1549 | for fname in new_set: | ||
1550 | if fname in existing_files: | ||
1551 | origpath = existing_files.pop(fname) | ||
1552 | workpath = os.path.join(local_files_dir, fname) | ||
1553 | if not filecmp.cmp(origpath, workpath): | ||
1554 | updated[fname] = {'path' : origpath} | ||
1555 | elif fname != '.gitignore': | ||
1556 | added[fname] = {} | ||
1557 | |||
1558 | workdir = rd.getVar('WORKDIR') | ||
1559 | s = rd.getVar('S') | ||
1560 | if not s.endswith(os.sep): | ||
1561 | s += os.sep | ||
1562 | |||
1563 | if workdir != s: | ||
1564 | # Handle files where subdir= was specified | ||
1565 | for fname in list(existing_files.keys()): | ||
1566 | # FIXME handle both subdir starting with BP and not? | ||
1567 | fworkpath = os.path.join(workdir, fname) | ||
1568 | if fworkpath.startswith(s): | ||
1569 | fpath = os.path.join(srctree, os.path.relpath(fworkpath, s)) | ||
1570 | if os.path.exists(fpath): | ||
1571 | origpath = existing_files.pop(fname) | ||
1572 | if not filecmp.cmp(origpath, fpath): | ||
1573 | updated[fpath] = {'path' : origpath} | ||
1574 | |||
1575 | removed = existing_files | ||
1576 | return (updated, added, removed) | 1500 | return (updated, added, removed) |
1577 | 1501 | ||
1578 | 1502 | ||