configurationengine/source/scripts/conesub_export.py
changeset 0 2e8eeb919028
child 3 e7e0ae78773e
equal deleted inserted replaced
-1:000000000000 0:2e8eeb919028
       
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 
       
    17 import os
       
    18 import fnmatch
       
    19 import logging
       
    20 from optparse import OptionParser, OptionGroup
       
    21 
       
    22 import cone_common
       
    23 from cone.public import api, plugin, utils, exceptions
       
    24 
       
    25 
       
    26 VERSION     = '1.0'
       
    27 DEFAULT_EXT = '.cpf'
       
    28 
       
    29 logger    = logging.getLogger('cone')
       
    30 DATA_NAME = 'confml/data.confml'
       
    31 
       
    32 def main():
       
    33     parser = OptionParser(version="%%prog %s" % VERSION)
       
    34     
       
    35     parser.add_options(cone_common.COMMON_OPTIONS)
       
    36     
       
    37     parser.add_option("-c", "--configuration",
       
    38                         dest="configs",
       
    39                         action="append",
       
    40                         help="Defines the name of the configuration for the action, can be "\
       
    41                              "specified multiple times to include multiple configurations.",
       
    42                         metavar="CONFIG",
       
    43                         default=[])
       
    44     
       
    45     parser.add_option("--config-wildcard",
       
    46                       action="append",
       
    47                       dest="config_wildcards",
       
    48                       help="Wildcard pattern for including configurations, e.g. "\
       
    49                            "product_langpack_*_root.confml",
       
    50                       metavar="WILDCARD",
       
    51                       default=[])
       
    52     
       
    53     parser.add_option("--config-regex",
       
    54                       action="append",
       
    55                       dest="config_regexes",
       
    56                       help="Regular expression for including configurations, e.g. "\
       
    57                            "product_langpack_\\d{2}_root.confml",
       
    58                       metavar="REGEX",
       
    59                       default=[])
       
    60     
       
    61     parser.add_option("-p", "--project",
       
    62                        dest="project",
       
    63                        help="defines the location of current project. Default is the "\
       
    64                             "current working directory.",\
       
    65                        default=".",
       
    66                        metavar="STORAGE")
       
    67     
       
    68     group = OptionGroup(parser, 'Export options',
       
    69                         'The export action is intended for exporting configurations '\
       
    70                         'from one project (storage) to another. A project can be a '\
       
    71                         'folder, a CPF or ZIP file, or a Carbon web storage URL. '\
       
    72                         # An ugly way to make newlines, someone should look into
       
    73                         # sub-classing optparse.HelpFormatter... 
       
    74                         '                                                                          '\
       
    75                         'Two different ways of exporting are supported: '\
       
    76                         '                                                                          '\
       
    77                         '1. Exporting multiple configurations into one new project using --remote '\
       
    78                         '                                                                          '\
       
    79                         '2. Exporting configurations into a number of new projects using --export-dir')
       
    80     
       
    81     group.add_option("-r", "--remote",
       
    82                    dest="remote",
       
    83                    help="Defines the location of remote storage. All configurations included using "\
       
    84                         "--configuration, --config-wildcard and --config-regex are exported into "\
       
    85                         "the storage. If the remote storage location is not given, the default "\
       
    86                         "location is determined based on the first included source configuration name. "\
       
    87                         "E.g. 'example.confml' would be exported into 'example.cpf'",
       
    88                    metavar="STORAGE")
       
    89     
       
    90     group.add_option("--export-dir",
       
    91                      help="Defines the directory where each included configuration is exported "\
       
    92                           "as a new project.",
       
    93                      default=None)
       
    94     
       
    95     group.add_option("--export-format",
       
    96                      help="Defines the format into which projects are exported when using "\
       
    97                           "--export-dir. Possible values are 'cpf' (the default) and 'dir'.",
       
    98                      default=None)
       
    99     
       
   100     group.add_option("-a","--add",
       
   101                    dest="added",
       
   102                    action="append",
       
   103                    type="string",
       
   104                    help="Adds a configuration layer to the given configuration as last element. "\
       
   105                         "The add operation can be used several times in a single command and it "\
       
   106                         "can create even an empty layer. "\
       
   107                         "Example --add foo/root.confml --add bar/root-confml.",
       
   108                    metavar="CONFIG",
       
   109                    default=None)
       
   110 
       
   111     group.add_option("--exclude-folders",
       
   112                         dest="exclude_empty_folders",
       
   113                         action="store_true",
       
   114                         help="Excludes empty folders from export",
       
   115                         default=False)
       
   116     
       
   117     parser.add_option_group(group)
       
   118     (options, args) = parser.parse_args()
       
   119     
       
   120     cone_common.handle_common_options(options)
       
   121     
       
   122     # Check options
       
   123     if options.export_format and options.export_dir is None:
       
   124         parser.error("--export-format can only be used in conjunction with --export-dir")
       
   125     if options.export_dir and options.remote:
       
   126         parser.error("--export-dir and --remote cannot be used at the same time")
       
   127     if options.export_format and options.export_format.lower() not in ('dir', 'cpf'):
       
   128         parser.error("Invalid export format '%s'" % options.export_format)
       
   129     if options.export_dir and not (options.configs or options.config_wildcards or options.config_regexes):
       
   130         parser.error("Use of --export-dir requires at least one configuration to be specified")
       
   131     if options.export_dir and os.path.isfile(options.export_dir):
       
   132         parser.error("Given export directory '%s' is a file")
       
   133     
       
   134     # Open the project and find out the active configuration
       
   135     project = api.Project(api.Storage.open(options.project, "r"))
       
   136     try:
       
   137         active_root = project.get_storage().get_active_configuration()
       
   138     except AttributeError:
       
   139         active_root = None
       
   140     
       
   141     # Collect the list of configurations specified from the command line
       
   142     config_list = []
       
   143     if options.configs or options.config_wildcards or options.config_regexes:
       
   144         try:
       
   145             config_list = cone_common.get_config_list_from_project(
       
   146                 project          = project,
       
   147                 configs          = options.configs,
       
   148                 config_wildcards = options.config_wildcards,
       
   149                 config_regexes   = options.config_regexes)
       
   150         except cone_common.ConfigurationNotFoundError, e:
       
   151             parser.error(str(e))
       
   152     
       
   153     # Use the active configuration if no configurations are specifically given
       
   154     if len(config_list) == 0:
       
   155         if active_root is None:
       
   156             parser.error("No configurations given and the project does not have an active root")
       
   157         else:
       
   158             logger.info('No configurations given! Using active root configuration %s' % active_root)
       
   159             config_list = [active_root]
       
   160     
       
   161     # Perform the export
       
   162     if options.export_dir:
       
   163         _export_to_dir(project       = project,
       
   164                        export_dir    = options.export_dir,
       
   165                        export_format = options.export_format or 'cpf',
       
   166                        configs       = config_list,
       
   167                        added_layers  = options.added,
       
   168                        empty_folders = not options.exclude_empty_folders)
       
   169     else:
       
   170         _export_to_storage(project                 = project,
       
   171                            remote_project_location = options.remote,
       
   172                            configs                 = config_list,
       
   173                            added_layers            = options.added,
       
   174                            empty_folders           = not options.exclude_empty_folders)
       
   175     
       
   176 
       
   177 def _export_to_storage(project, remote_project_location, configs, added_layers, empty_folders):
       
   178     assert len(configs) > 0
       
   179     
       
   180     # If the remote storage is not given, determine it automatically based
       
   181     # on the first specified configuration name
       
   182     if not remote_project_location:
       
   183         remotename, ext = os.path.splitext(os.path.basename(configs[0]))
       
   184         remotename += DEFAULT_EXT
       
   185         logger.info('No remote storage given! Using source configuration name %s' % remotename)
       
   186         remote_project_location = remotename
       
   187     
       
   188     remote_project = api.Project(api.Storage.open(remote_project_location, "w"))
       
   189     for config_path in configs:
       
   190         config = project.get_configuration(config_path)
       
   191         project.export_configuration(config,
       
   192                                      remote_project.storage,
       
   193                                      empty_folders = empty_folders)
       
   194         print "Export %s to %s done!" % (config_path, remote_project_location)
       
   195     
       
   196     # Setting first as active configuration if there are more than one configuration defined.
       
   197     configs = remote_project.list_configurations()
       
   198     if len(configs):
       
   199         try:
       
   200             remote_project.get_storage().set_active_configuration(configs[0])
       
   201         except AttributeError:
       
   202             pass
       
   203     
       
   204     remote_project.save()
       
   205     remote_project.close()
       
   206     
       
   207     _add_layers(project, remote_project_location, added_layers, empty_folders)
       
   208     
       
   209 def _add_layers(source_project, remote_project_location, added_configs, empty_folders):
       
   210     """
       
   211     Add new configuration layers from source_project into 
       
   212     """
       
   213     if not added_configs:
       
   214         return
       
   215     
       
   216     target_project = api.Project(api.Storage.open(remote_project_location, "a"))
       
   217     for target_config_name in target_project.list_configurations():
       
   218         target_config = target_project.get_configuration(target_config_name)
       
   219         
       
   220         for added_config_name in added_configs:
       
   221             # Add layers only once
       
   222             if not target_project.storage.is_resource(added_config_name):
       
   223                 logger.info('Adding configuration %s' % added_config_name)
       
   224                 
       
   225                 if source_project.storage.is_resource(added_config_name):
       
   226                     # The configuration exists in the source project, export it from there
       
   227                     existing_config = source_project.get_configuration(added_config_name)
       
   228                     source_project.export_configuration(existing_config,
       
   229                                                         target_project.storage,
       
   230                                                         empty_folders = empty_folders)
       
   231                 else:
       
   232                     # The given configuration does not exist in the source project,
       
   233                     # create a new empty layer
       
   234                     logger.info("Creating new layer %s." % added_config_name)
       
   235                     new_config = target_project.create_configuration(added_config_name)
       
   236                     new_config.create_configuration(DATA_NAME)
       
   237             
       
   238             # Include the added configuration in the configuration root
       
   239             target_config.include_configuration(utils.resourceref.norm(added_config_name))
       
   240     
       
   241     target_project.save()
       
   242     target_project.close()
       
   243 
       
   244 def _export_to_dir(project, export_dir, export_format, configs, added_layers, empty_folders):
       
   245     if not os.path.exists(export_dir):
       
   246         os.makedirs(export_dir)
       
   247     
       
   248     for config in configs:
       
   249         remote_name, _ = os.path.splitext(os.path.basename(config))
       
   250         if export_format.lower() == 'cpf':
       
   251             remote_name += '.cpf'
       
   252         elif export_format.lower() == 'dir':
       
   253             remote_name += '/'
       
   254         
       
   255         remote_name = os.path.join(export_dir, remote_name)
       
   256         _export_to_storage(project, remote_name, [config], added_layers, empty_folders)
       
   257 
       
   258 if __name__ == "__main__":
       
   259     main()