|
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 re |
|
19 import fnmatch |
|
20 import logging |
|
21 from optparse import OptionParser, OptionGroup |
|
22 |
|
23 import cone_common |
|
24 from cone.public import api, plugin, utils, exceptions |
|
25 |
|
26 |
|
27 VERSION = '1.0' |
|
28 DEFAULT_EXT = '.cpf' |
|
29 CPF_NAMESPACE = "http://www.nokia.com/xml/cpf-id/1" |
|
30 CPF_META_TAG = "configuration-property" |
|
31 |
|
32 logger = logging.getLogger('cone') |
|
33 |
|
34 def main(): |
|
35 parser = OptionParser(version="%%prog %s" % VERSION) |
|
36 |
|
37 parser.add_options(cone_common.COMMON_OPTIONS) |
|
38 |
|
39 parser.add_option("-c", "--configuration", |
|
40 dest="configs", |
|
41 action="append", |
|
42 help="Defines the name of the configuration for the action, can be "\ |
|
43 "specified multiple times to include multiple configurations.", |
|
44 metavar="CONFIG", |
|
45 default=[]) |
|
46 |
|
47 parser.add_option("--config-wildcard", |
|
48 action="append", |
|
49 dest="config_wildcards", |
|
50 help="Wildcard pattern for including configurations, e.g. "\ |
|
51 "product_langpack_*_root.confml", |
|
52 metavar="WILDCARD", |
|
53 default=[]) |
|
54 |
|
55 parser.add_option("--config-regex", |
|
56 action="append", |
|
57 dest="config_regexes", |
|
58 help="Regular expression for including configurations, e.g. "\ |
|
59 "product_langpack_\\d{2}_root.confml", |
|
60 metavar="REGEX", |
|
61 default=[]) |
|
62 |
|
63 parser.add_option("-p", "--project",\ |
|
64 dest="project",\ |
|
65 help="defines the location of current project. Default is the current working directory.",\ |
|
66 default=".",\ |
|
67 metavar="STORAGE") |
|
68 |
|
69 group = OptionGroup(parser, 'Update options', |
|
70 'The update functionality is meant for ConfML manipulation ' |
|
71 'in current project (defined with -p). ' |
|
72 'Default value for the current project is the currently working directory. ' |
|
73 'A project can be either a folder or a cpf/zip file.') |
|
74 |
|
75 |
|
76 group.add_option("-m","--add-meta",\ |
|
77 dest="meta",\ |
|
78 action="append", |
|
79 type="string", |
|
80 help="Add given metadata to defined configuration."\ |
|
81 "Example --add-meta \"owner=John Cone\" -m product=E75", |
|
82 default=None) |
|
83 |
|
84 group.add_option("--add-cpf-meta",\ |
|
85 dest="cpfmeta",\ |
|
86 action="append", |
|
87 type="string", |
|
88 help="Add given CPF identification metadata to defined configuration."\ |
|
89 "Example --add-cpf-meta \"coreplat_name=Platform1\"", |
|
90 default=None) |
|
91 |
|
92 group.add_option("-d","--add-desc",\ |
|
93 dest="desc",\ |
|
94 type="string",\ |
|
95 help="Add given description to defined configuration."\ |
|
96 "Example --add-desc \"Customer one CPF\" -d Description1", |
|
97 default=None) |
|
98 |
|
99 group.add_option("--remove-meta",\ |
|
100 dest="remove_meta",\ |
|
101 action="append", |
|
102 type="string", |
|
103 help="Removes given metadata from defined configuration."\ |
|
104 "Example --remove-meta owner --remove-meta coreplat_name", |
|
105 metavar="META",\ |
|
106 default=None) |
|
107 |
|
108 group.add_option("--remove-desc",\ |
|
109 dest="remove_desc",\ |
|
110 action="store_true",\ |
|
111 help="Removes description from defined configuration."\ |
|
112 "Example --remove-desc", |
|
113 default=False) |
|
114 |
|
115 group.add_option("--add-data",\ |
|
116 dest="data",\ |
|
117 action="append", |
|
118 type="string", |
|
119 help="Add given ConfML data to defined configuration."\ |
|
120 "Example --add-data \"KCRUidAvkon.KAknDefaultAppOrientation=1\"", |
|
121 default=None) |
|
122 |
|
123 parser.add_option_group(group) |
|
124 (options, args) = parser.parse_args() |
|
125 |
|
126 cone_common.handle_common_options(options) |
|
127 |
|
128 # Open the project and find out the active configuration |
|
129 project = api.Project(api.Storage.open(options.project, "a")) |
|
130 try: |
|
131 active_root = project.get_storage().get_active_configuration() |
|
132 except AttributeError: |
|
133 active_root = None |
|
134 |
|
135 # Collect the list of configurations specified from the command line |
|
136 config_list = [] |
|
137 if options.configs or options.config_wildcards or options.config_regexes: |
|
138 try: |
|
139 config_list = cone_common.get_config_list_from_project( |
|
140 project = project, |
|
141 configs = options.configs, |
|
142 config_wildcards = options.config_wildcards, |
|
143 config_regexes = options.config_regexes) |
|
144 except cone_common.ConfigurationNotFoundError, e: |
|
145 parser.error(str(e)) |
|
146 |
|
147 # Use the active configuration if no configurations are specifically given |
|
148 if len(config_list) == 0: |
|
149 if active_root is None: |
|
150 parser.error("No configurations given and the project does not have an active root") |
|
151 else: |
|
152 logger.info('No configurations given! Using active root configuration %s' % active_root) |
|
153 config_list = [active_root] |
|
154 |
|
155 |
|
156 |
|
157 # Parse added meta and data definitions |
|
158 added_meta = _parse_name_value_pairs(options.meta, 'metadata') |
|
159 added_cpf_meta = _parse_name_value_pairs(options.cpfmeta, 'CPF metadata') |
|
160 added_data = _parse_name_value_pairs(options.data, 'data') |
|
161 |
|
162 for config_name in config_list: |
|
163 print "Updating %s" % config_name |
|
164 config = project.get_configuration(config_name) |
|
165 |
|
166 # Handle metadata and data additions |
|
167 if added_meta: _add_meta(config, added_meta) |
|
168 if added_cpf_meta: _add_cpf_meta(config, added_cpf_meta) |
|
169 if added_data: _add_data(config, added_data) |
|
170 |
|
171 # Handle description |
|
172 if options.desc: |
|
173 logger.info("Setting description to %s" % options.desc) |
|
174 config.desc = options.desc |
|
175 if options.remove_desc: |
|
176 if config.desc: |
|
177 logger.info("Removing description") |
|
178 del config.desc |
|
179 |
|
180 # Handle metadata removals |
|
181 if options.remove_meta: |
|
182 for remove_meta in options.remove_meta: |
|
183 if config.meta: |
|
184 index = config.meta.find_by_tag(remove_meta) |
|
185 if index != -1: |
|
186 del config.meta[index] |
|
187 logger.info("Removed %s" % remove_meta) |
|
188 else: |
|
189 index = config.meta.find_by_attribute("name", remove_meta) |
|
190 if index != -1: |
|
191 del config.meta[index] |
|
192 logger.info("Removed %s" % remove_meta) |
|
193 else: |
|
194 logger.info("Could not remove metadata entry %s: not found." % remove_meta) |
|
195 |
|
196 project.save() |
|
197 project.close() |
|
198 |
|
199 def _parse_name_value_pairs(entries, entry_type_name): |
|
200 """ |
|
201 Parse a list of 'name=value' pairs into a dictionary. |
|
202 @param entries: The list of entries to parse. |
|
203 @param entry_type_name: Entry type name shown in the error message if an entry |
|
204 could not be parsed into a name-value pair. |
|
205 """ |
|
206 if not entries: |
|
207 return {} |
|
208 |
|
209 result = {} |
|
210 pattern = re.compile("(.+)=(.+)") |
|
211 for entry in entries: |
|
212 mo = pattern.search(entry) |
|
213 if mo: |
|
214 name = mo.group(1) |
|
215 value = mo.group(2) |
|
216 result[name] = value |
|
217 else: |
|
218 logger.error("Illegal %s definition: %s" % (entry_name, entry)) |
|
219 return result |
|
220 |
|
221 def _add_meta(config, added_meta): |
|
222 if not config.meta: |
|
223 config.meta = [] |
|
224 |
|
225 for tag, value in added_meta.iteritems(): |
|
226 index = config.meta.find_by_tag(tag) |
|
227 if index != -1: |
|
228 logger.info("Replacing %s's value %s with %s" % \ |
|
229 (tag, config.meta[index].value, value)) |
|
230 config.meta.replace(index, tag, value) |
|
231 else: |
|
232 logger.info("Adding value %s for %s." % (value, tag)) |
|
233 config.meta.add(tag, value) |
|
234 |
|
235 def _add_cpf_meta(config, added_cpf_meta): |
|
236 if not config.meta: |
|
237 config.meta = [] |
|
238 for attrName, attrValue in added_cpf_meta.iteritems(): |
|
239 index = config.meta.find_by_attribute("name", attrName) |
|
240 if index != -1: |
|
241 logger.info("Replacing %s's value %s with %s" % \ |
|
242 (attrName, config.meta[index].attrs["value"], attrValue)) |
|
243 config.meta.replace(index, CPF_META_TAG, None, CPF_NAMESPACE, {"name": attrName, "value": attrValue}) |
|
244 else: |
|
245 logger.info("Adding value %s for %s." % \ |
|
246 (attrName, attrValue)) |
|
247 config.meta.add(CPF_META_TAG, None, CPF_NAMESPACE, {"name": attrName, "value": attrValue}) |
|
248 |
|
249 def _add_data(config, added_data): |
|
250 for ref, value in added_data.iteritems(): |
|
251 if value.startswith("["): |
|
252 value = eval(value) |
|
253 for value_item in value: |
|
254 config.get_default_view().get_feature(ref).add_sequence(value_item, 0) |
|
255 logger.info("Set %s=%s" % (ref, repr(value))) |
|
256 else: |
|
257 config.get_default_view().get_feature(ref).set_value(value) |
|
258 logger.info("Set %s=%s" % (ref, value)) |
|
259 |
|
260 if __name__ == "__main__": |
|
261 main() |
|
262 |
|
263 |
|
264 |