citadel/scripts/lib/devtool/export.py

120 lines
4.5 KiB
Python
Raw Normal View History

# 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)