--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/scripts/conesub_initvariant.py Tue Aug 10 14:29:28 2010 +0300
@@ -0,0 +1,265 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+#
+
+import sys
+import logging
+import tempfile
+import os, re
+import shutil
+
+from optparse import OptionParser, OptionGroup
+import cone_common
+
+from cone.public import api, utils
+
+from conesub_merge import merge_config_root_to_config_root,\
+ get_active_root_if_necessary,\
+ MergePolicy, MergeFailedException
+
+from conesub_export import run_export
+
+VERSION = '1.0'
+
+logger = logging.getLogger('cone')
+
+class MetaNotFoundException(Exception):
+ pass
+
+def find_variant_layers_to_merge(source_config, target_config, find_pattern):
+ """
+ Find all layers in the configuration that contain custvariant* in
+ their path name and return a list containing source->target mappings.
+ @param source_config: The source configuration object.
+ @param target_config: The target configuration object.
+ @param new_name: The new name to replace custvariant* in the
+ target path name with.
+ @return: A list of (source_layer, target_layer) tuples.
+ """
+ pattern = re.compile(find_pattern)
+
+ result = []
+ for src in source_config.list_configurations():
+ m = pattern.match(src)
+ if m:
+ result.append(src)
+
+ print "Found layers %r" % result
+ return result
+
+def main(argv=sys.argv):
+ """ Initialize a variant from a cpf. """
+ parser = OptionParser(version="%%prog %s" % VERSION)
+
+ parser.add_options(cone_common.COMMON_OPTIONS)
+
+ parser.add_option("-p", "--project",
+ dest="project",
+ help="Defines the location of current project. Default is the current working directory.",
+ default=".",
+ metavar="STORAGE")
+
+ group = OptionGroup(parser, 'Initvariant options',
+ 'The initvariant action is intended for merging a variant CPF back into the '
+ 'configuration project, or creating a new empty variant based on an existing '
+ 'configuration. It merges all customer variant layers (layers with '
+ 'custvariant* in their path name) and renames them based on the variant ID '
+ 'and variant name ("custvariant_<id>_<name>").')
+
+ group.add_option("-c", "--configuration",
+ dest="configuration",
+ help="Defines the name of the target configuration. By default the "
+ "configuration file name is composed of product name, variant ID "
+ "and variant name like this: <product>_custvariant_<id>_<name>_root.confml",
+ metavar="CONFIG")
+
+ group.add_option("-r", "--remote",
+ dest="remote",
+ help="Defines the location of remote storage (CPF)",
+ metavar="STORAGE")
+
+ group.add_option("-s", "--sourceconfiguration",
+ dest="sourceconfiguration",
+ help="Defines the name of the remote configuration inside the remote storage. "
+ "Default is the active root of the remote project.",
+ metavar="CONFIG")
+
+ group.add_option("--variant-id", help="Variant ID, mandatory.")
+ group.add_option("--variant-name", help="Variant name, optional.")
+ group.add_option("--product-name",
+ help="Product name, taken from the configuration data by default "
+ "(i.e. defaults to '${imakerapi.productname}')",
+ default="${imakerapi.productname}")
+
+ group.add_option("--set-active-root",
+ action="store_true",
+ help="Set the newly created (or update) configuration root as the "
+ "project's active root after the merge is done.")
+
+ group.add_option("-b","--based-on-configuration",
+ dest="boconfig",
+ help="Defines the configuration root which is used as a base "
+ "configuration for the new empty variant.")
+
+ group.add_option("--find-layer-regexp",
+ dest="find_pattern",
+ default='.*/manual/.*|.*/configurator/.*',
+ help="Defines the pattern which is used to find the layers "
+ "from source configuration that will be merged"
+ "Default: '.*/manual/.*|.*/configurator/.*' " )
+
+ parser.add_option_group(group)
+ (options, _) = parser.parse_args(argv)
+
+ cone_common.handle_common_options(options)
+
+ # Check the passed options
+ if not options.remote and not options.boconfig:
+ parser.error("Remote project or based-on-configuration must be given")
+ if options.remote and options.boconfig:
+ parser.error("Only either remote project or based-on-configuration can be given, but not both")
+ if not options.variant_id: parser.error("Variant ID must be given")
+
+ temp_cpf_folder = None
+
+ if options.boconfig:
+ class ExportOptions(object):
+ pass
+
+ path = ''
+ coreplat_name = ''
+ product = ''
+
+ project = api.Project(api.Storage.open(options.project,"a", username=options.username, password=options.password))
+ config = project.get_configuration(options.boconfig)
+ meta = config.meta
+
+ if meta:
+ for prop in meta.array:
+ if 'name' in prop.attrs and 'value' in prop.attrs:
+ name = prop.attrs['name']
+ if name == 'coreplat_name':
+ coreplat_name = prop.attrs['value']
+ if name == 'product_name':
+ product = prop.attrs['value']
+
+ if not coreplat_name or not product:
+ print >>sys.stderr, "Could not find coreplat_name or product_name from meta data."
+ print >>sys.stderr, "Are you sure the given based-on-configuration is valid?"
+ sys.exit(2)
+
+ path = coreplat_name + '/' + product
+
+ temp_cpf_folder = tempfile.mkdtemp()
+
+ export_options = ExportOptions()
+ export_options.project = options.project
+ export_options.remote = os.path.join(temp_cpf_folder, 'temp.cpf')
+ export_options.configs = [options.boconfig]
+ export_options.username = options.username
+ export_options.password = options.password
+ export_options.config_wildcards = None
+ export_options.config_regexes = None
+ export_options.export_dir = None
+ export_options.exclude_content_filter = None
+ export_options.added = [path + '/customer/custvariant/manual/root.confml',
+ path + '/customer/custvariant/configurator/root.confml']
+ export_options.exclude_empty_folders = False
+ export_options.action = None
+
+ options.remote = export_options.remote
+
+ print "Exporting variant CPF to a temporary directory"
+ run_export(export_options)
+
+ target_project = api.Project(api.Storage.open(options.project,"a", username=options.username, password=options.password))
+ source_project = api.Project(api.Storage.open(options.remote,"r", username=options.username, password=options.password))
+
+ print "Target project: %s" % options.project
+ print "Source project: %s" % options.remote
+ replace_dict = {"VAR_ID": options.variant_id, "VAR_NAME": options.variant_name}
+
+ try:
+ # Open the source configuration
+ source_config = get_active_root_if_necessary(source_project, options.sourceconfiguration, 'source')
+ source_config = source_project.get_configuration(source_config)
+
+ # Determine the new name of the layer part (replaces 'custvariant[^/]*')
+ if options.variant_name:
+ new_name = "custvariant_%s_%s" % (options.variant_id, options.variant_name)
+ else:
+ new_name = "custvariant_%s" % options.variant_id
+
+ # Determine the target configuration
+ if options.configuration:
+ target_config = options.configuration
+ else:
+ # Target configuration not given explicitly, automatically
+ # determine the name based on the product name and the new
+ # layer name
+ try:
+ product_name = utils.expand_refs_by_default_view(
+ options.product_name,
+ source_config.get_default_view(),
+ catch_not_found = False)
+ except Exception, e:
+ print "Could not determine product name: %s" % e
+ sys.exit(2)
+ print "Product name: %s" % product_name
+ target_config = "%s_%s_root.confml" % (product_name, new_name)
+
+
+ def find_layers(source_config, target_config):
+ ret_list = []
+
+ layers = find_variant_layers_to_merge(source_config,
+ target_config,
+ options.find_pattern)
+ p = re.compile(r'custvariant[^/]*')
+ for layer in layers:
+ tgt_layer = p.sub(new_name, layer)
+ ret_list.append((layer, tgt_layer))
+
+ return ret_list
+
+ # Perform the merge
+ merge_config_root_to_config_root(
+ source_project = source_project,
+ target_project = target_project,
+ source_config = options.sourceconfiguration,
+ target_config = target_config,
+ layer_finder_func = find_layers,
+ merge_policy = MergePolicy.OVERWRITE_LAYER)
+
+ if options.set_active_root:
+ target_project.get_storage().set_active_configuration(target_config)
+ except MergeFailedException, e:
+ print "Could not initialize variant: %s" % e
+ sys.exit(2)
+ else:
+ # Merge successful, so save the target project
+ # to persist the changes
+ target_project.save()
+
+ target_project.close()
+ source_project.close()
+
+ if temp_cpf_folder:
+ logger.debug("Removing temporary CPF directory '%s'" % temp_cpf_folder)
+ shutil.rmtree(temp_cpf_folder)
+
+
+if __name__ == "__main__":
+ main()