aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonardo Sandoval <leonardo.sandoval.gonzalez@linux.intel.com>2017-05-23 12:10:28 -0700
committerPaul Eggleton <paul.eggleton@linux.intel.com>2017-08-21 17:28:31 +1200
commit024784eb244f5886a7f8105bfeff3a8649d263fc (patch)
tree5a8b8028d310db0e50e85a25b6e4e38cd44b7fd3
parent0df957515454888de7a4fb4a9be66fb9401b4a24 (diff)
downloadopenembedded-core-contrib-024784eb244f5886a7f8105bfeff3a8649d263fc.tar.gz
devtool: export: new plugin to export the devtool workspace
By default, exports the whole workspace (all recipes) including the source code. User can also limit what is exported with --included/--excluded flags. As a result of this operation, a tar archive containing only workspace metadata and its corresponding source code is created, which can be properly imported with 'devtool import'. https://bugzilla.yoctoproject.org/show_bug.cgi?id=10510 [YOCTO #10510] Signed-off-by: Leonardo Sandoval <leonardo.sandoval.gonzalez@linux.intel.com> Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
-rw-r--r--scripts/lib/devtool/export.py119
1 files changed, 119 insertions, 0 deletions
diff --git a/scripts/lib/devtool/export.py b/scripts/lib/devtool/export.py
new file mode 100644
index 0000000000..13ee258e7a
--- /dev/null
+++ b/scripts/lib/devtool/export.py
@@ -0,0 +1,119 @@
+# Development tool - export 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 export plugin"""
+
+import os
+import argparse
+import tarfile
+import logging
+import datetime
+import json
+
+logger = logging.getLogger('devtool')
+
+# output files
+default_arcname_prefix = "workspace-export"
+metadata = '.export_metadata'
+
+def export(args, config, basepath, workspace):
+ """Entry point for the devtool 'export' subcommand"""
+
+ def add_metadata(tar):
+ """Archive the workspace object"""
+ # finally store the workspace metadata
+ with open(metadata, 'w') as fd:
+ fd.write(json.dumps((config.workspace_path, workspace)))
+ tar.add(metadata)
+ os.unlink(metadata)
+
+ def add_recipe(tar, recipe, data):
+ """Archive recipe with proper arcname"""
+ # Create a map of name/arcnames
+ arcnames = []
+ for key, name in data.items():
+ if name:
+ if key == 'srctree':
+ # all sources, no matter where are located, goes into the sources directory
+ arcname = 'sources/%s' % recipe
+ else:
+ arcname = name.replace(config.workspace_path, '')
+ arcnames.append((name, arcname))
+
+ for name, arcname in arcnames:
+ tar.add(name, arcname=arcname)
+
+
+ # Make sure workspace is non-empty and possible listed include/excluded recipes are in workspace
+ if not workspace:
+ logger.info('Workspace contains no recipes, nothing to export')
+ return 0
+ else:
+ for param, recipes in {'include':args.include,'exclude':args.exclude}.items():
+ for recipe in recipes:
+ if recipe not in workspace:
+ logger.error('Recipe (%s) on %s argument not in the current workspace' % (recipe, param))
+ return 1
+
+ name = args.file
+
+ default_name = "%s-%s.tar.gz" % (default_arcname_prefix, datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
+ if not name:
+ name = default_name
+ else:
+ # if name is a directory, append the default name
+ if os.path.isdir(name):
+ name = os.path.join(name, default_name)
+
+ if os.path.exists(name) and not args.overwrite:
+ logger.error('Tar archive %s exists. Use --overwrite/-o to overwrite it')
+ return 1
+
+ # if all workspace is excluded, quit
+ if not len(set(workspace.keys()).difference(set(args.exclude))):
+ logger.warn('All recipes in workspace excluded, nothing to export')
+ return 0
+
+ exported = []
+ with tarfile.open(name, 'w:gz') as tar:
+ if args.include:
+ for recipe in args.include:
+ add_recipe(tar, recipe, workspace[recipe])
+ exported.append(recipe)
+ else:
+ for recipe, data in workspace.items():
+ if recipe not in args.exclude:
+ add_recipe(tar, recipe, data)
+ exported.append(recipe)
+
+ add_metadata(tar)
+
+ logger.info('Tar archive created at %s with the following recipes: %s' % (name, ', '.join(exported)))
+ return 0
+
+def register_commands(subparsers, context):
+ """Register devtool export subcommands"""
+ parser = subparsers.add_parser('export',
+ help='Export workspace into a tar archive',
+ description='Export one or more recipes from current workspace into a tar archive',
+ group='advanced')
+
+ parser.add_argument('--file', '-f', help='Output archive file name')
+ parser.add_argument('--overwrite', '-o', action="store_true", help='Overwrite previous export tar archive')
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument('--include', '-i', nargs='+', default=[], help='Include recipes into the tar archive')
+ group.add_argument('--exclude', '-e', nargs='+', default=[], help='Exclude recipes into the tar archive')
+ parser.set_defaults(func=export)