[OE-core] [PATCH v4 4/4] import: new plugin to import the devtool workspace

leonardo.sandoval.gonzalez at linux.intel.com leonardo.sandoval.gonzalez at linux.intel.com
Thu Jun 29 16:40:52 UTC 2017


From: Leonardo Sandoval <leonardo.sandoval.gonzalez at linux.intel.com>

Takes a tar archive created by 'devtool export' and export it (untar) to
workspace. By default, the whole tar archive is imported, thus there is no
way to limit what is imported.

https://bugzilla.yoctoproject.org/show_bug.cgi?id=10510

[YOCTO #10510]

Signed-off-by: Leonardo Sandoval <leonardo.sandoval.gonzalez at linux.intel.com>
---
 scripts/lib/devtool/import.py | 150 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 150 insertions(+)
 create mode 100644 scripts/lib/devtool/import.py

diff --git a/scripts/lib/devtool/import.py b/scripts/lib/devtool/import.py
new file mode 100644
index 0000000000..21eb90820b
--- /dev/null
+++ b/scripts/lib/devtool/import.py
@@ -0,0 +1,150 @@
+# Development tool - import command plugin
+#
+# Copyright (C) 2014-2017 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+"""Devtool import plugin"""
+
+import os
+import tarfile
+import logging
+import collections
+import json
+import fnmatch
+
+from devtool import standard, setup_tinfoil, replace_from_file
+from devtool import export
+
+logger = logging.getLogger('devtool')
+
+def devimport(args, config, basepath, workspace):
+    """Entry point for the devtool 'import' subcommand"""
+
+    def get_pn(name):
+        """ Returns the filename of a workspace recipe/append"""
+        metadata = name.split('/')[-1]
+        fn, _ = os.path.splitext(metadata)
+        return fn
+
+    if not os.path.exists(args.file):
+        logger.error('Tar archive %s does not exist. Export your workspace using "devtool export"' % args.file)
+        return 1
+
+    tar = tarfile.open(args.file)
+
+    # Get exported metadata
+    export_workspace_path = export_workspace = None
+    try:
+        metadata = tar.getmember(export.metadata)
+    except KeyError as ke:
+        logger.error('The export metadata file created by "devtool export" was not found')
+        logger.error('The devtool import plugin can only be used to import tar archives created by devtool export')
+        return 1
+
+    tar.extract(metadata)
+    with open(metadata.name) as fdm:
+        export_workspace_path, export_workspace = json.load(fdm)
+    os.unlink(metadata.name)
+
+    members = tar.getmembers()
+
+    # Get appends and recipes from the exported archive, these
+    # will be needed to find out those appends without corresponding
+    # recipe pair
+    append_fns, recipe_fns = set(), set()
+    for member in members:
+        if member.name.startswith('appends'):
+            append_fns.add(get_pn(member.name))
+        elif member.name.startswith('recipes'):
+            recipe_fns.add(get_pn(member.name))
+
+    # Setup tinfoil, get required data and shutdown
+    tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
+    try:
+        current_fns = [os.path.basename(recipe[0]) for recipe in tinfoil.cooker.recipecaches[''].pkg_fn.items()]
+    finally:
+        tinfoil.shutdown()
+
+    # Find those appends that do not have recipes in current metadata
+    non_importables = []
+    for fn in append_fns - recipe_fns:
+        # Check on current metadata (covering those layers indicated in bblayers.conf)
+        for current_fn in current_fns:
+            if fnmatch.fnmatch(current_fn, '*' + fn.replace('%', '') + '*'):
+                break
+        else:
+            non_importables.append(fn)
+            logger.warn('No recipe to append %s.bbapppend, skipping' % fn)
+
+    # Extract
+    imported = []
+    for member in members:
+        if member.name == export.metadata:
+            continue
+
+        for nonimp in non_importables:
+            pn = nonimp.split('_')[0]
+            # do not extract data from non-importable recipes or metadata
+            if member.name.startswith('appends/%s' % nonimp) or \
+               member.name.startswith('recipes/%s' % nonimp) or \
+               member.name.startswith('sources/%s' % pn):
+               break
+        else:
+            path = os.path.join(config.workspace_path, member.name)
+            if os.path.exists(path):
+                # by default, no file overwrite is done unless -o is given by the user
+                if args.overwrite:
+                    try:
+                        tar.extract(member, path=config.workspace_path)
+                    except PermissionError as pe:
+                        logger.warn(pe)
+                else:
+                    logger.warn('File already present. Use --overwrite/-o to overwrite it: %s' % member.name)
+                    continue
+            else:
+                tar.extract(member, path=config.workspace_path)
+
+            # Update EXTERNALSRC and the devtool md5 file
+            if member.name.startswith('appends'):
+                if export_workspace_path:
+                    # appends created by 'devtool modify' just need to update the workspace
+                    replace_from_file(path, export_workspace_path, config.workspace_path)
+
+                    # appends created by 'devtool add' need replacement of exported source tree
+                    pn = get_pn(member.name).split('_')[0]
+                    exported_srctree = export_workspace[pn]['srctree']
+                    if exported_srctree:
+                        replace_from_file(path, exported_srctree, os.path.join(config.workspace_path, 'sources', pn))
+
+                standard._add_md5(config, pn, path)
+                imported.append(pn)
+
+    tar.close()
+
+    if  imported:
+        logger.info('Imported recipes into workspace %s: %s' % (config.workspace_path, ', '.join(imported)))
+    else:
+        logger.warn('No recipes imported into the workspace')
+
+    return 0
+
+def register_commands(subparsers, context):
+    """Register devtool import subcommands"""
+    parser = subparsers.add_parser('import',
+                                   help='Import exported tar archive into workspace',
+                                   description='Import tar archive previously created by "devtool export" into workspace',
+                                   group='advanced')
+    parser.add_argument('file', metavar='FILE', help='Name of the tar archive to import')
+    parser.add_argument('--overwrite', '-o', action="store_true", help='Overwrite files when extracting')
+    parser.set_defaults(func=devimport)
-- 
2.12.0




More information about the Openembedded-core mailing list