xref: /OK3568_Linux_fs/yocto/poky/scripts/lib/devtool/export.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1# Development tool - export command plugin
2#
3# Copyright (C) 2014-2017 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6#
7"""Devtool export plugin"""
8
9import os
10import argparse
11import tarfile
12import logging
13import datetime
14import json
15
16logger = logging.getLogger('devtool')
17
18# output files
19default_arcname_prefix = "workspace-export"
20metadata = '.export_metadata'
21
22def export(args, config, basepath, workspace):
23    """Entry point for the devtool 'export' subcommand"""
24
25    def add_metadata(tar):
26        """Archive the workspace object"""
27        # finally store the workspace metadata
28        with open(metadata, 'w') as fd:
29            fd.write(json.dumps((config.workspace_path, workspace)))
30        tar.add(metadata)
31        os.unlink(metadata)
32
33    def add_recipe(tar, recipe, data):
34        """Archive recipe with proper arcname"""
35        # Create a map of name/arcnames
36        arcnames = []
37        for key, name in data.items():
38            if name:
39                if key == 'srctree':
40                    # all sources, no matter where are located, goes into the sources directory
41                    arcname = 'sources/%s' % recipe
42                else:
43                    arcname = name.replace(config.workspace_path, '')
44                arcnames.append((name, arcname))
45
46        for name, arcname in arcnames:
47            tar.add(name, arcname=arcname)
48
49
50    # Make sure workspace is non-empty and possible listed include/excluded recipes are in workspace
51    if not workspace:
52        logger.info('Workspace contains no recipes, nothing to export')
53        return 0
54    else:
55        for param, recipes in {'include':args.include,'exclude':args.exclude}.items():
56            for recipe in recipes:
57                if recipe not in workspace:
58                    logger.error('Recipe (%s) on %s argument not in the current workspace' % (recipe, param))
59                    return 1
60
61    name = args.file
62
63    default_name = "%s-%s.tar.gz" % (default_arcname_prefix, datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
64    if not name:
65        name = default_name
66    else:
67        # if name is a directory, append the default name
68        if os.path.isdir(name):
69            name = os.path.join(name, default_name)
70
71    if os.path.exists(name) and not args.overwrite:
72        logger.error('Tar archive %s exists. Use --overwrite/-o to overwrite it')
73        return 1
74
75    # if all workspace is excluded, quit
76    if not len(set(workspace.keys()).difference(set(args.exclude))):
77        logger.warning('All recipes in workspace excluded, nothing to export')
78        return 0
79
80    exported = []
81    with tarfile.open(name, 'w:gz') as tar:
82        if args.include:
83            for recipe in args.include:
84                add_recipe(tar, recipe, workspace[recipe])
85                exported.append(recipe)
86        else:
87            for recipe, data in workspace.items():
88                if recipe not in args.exclude:
89                    add_recipe(tar, recipe, data)
90                    exported.append(recipe)
91
92        add_metadata(tar)
93
94    logger.info('Tar archive created at %s with the following recipes: %s' % (name, ', '.join(exported)))
95    return 0
96
97def register_commands(subparsers, context):
98    """Register devtool export subcommands"""
99    parser = subparsers.add_parser('export',
100                                   help='Export workspace into a tar archive',
101                                   description='Export one or more recipes from current workspace into a tar archive',
102                                   group='advanced')
103
104    parser.add_argument('--file', '-f', help='Output archive file name')
105    parser.add_argument('--overwrite', '-o', action="store_true", help='Overwrite previous export tar archive')
106    group = parser.add_mutually_exclusive_group()
107    group.add_argument('--include', '-i', nargs='+', default=[], help='Include recipes into the tar archive')
108    group.add_argument('--exclude', '-e', nargs='+', default=[], help='Exclude recipes into the tar archive')
109    parser.set_defaults(func=export)
110