OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 | 2 |
3 # Copyright (c) 2009 Google Inc. All rights reserved. | 3 # Copyright (c) 2012 Google Inc. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Make the format of a vcproj really pretty. | 7 """Make the format of a vcproj really pretty. |
8 | 8 |
9 This script normalize and sort an xml. It also fetches all the properties | 9 This script normalize and sort an xml. It also fetches all the properties |
10 inside linked vsprops and include them explicitly in the vcproj. | 10 inside linked vsprops and include them explicitly in the vcproj. |
11 | 11 |
12 It outputs the resulting xml to stdout. | 12 It outputs the resulting xml to stdout. |
13 """ | 13 """ |
14 | 14 |
15 __author__ = 'nsylvain (Nicolas Sylvain)' | 15 __author__ = 'nsylvain (Nicolas Sylvain)' |
16 | 16 |
17 import os | 17 import os |
18 import sys | 18 import sys |
19 | 19 |
20 from xml.dom.minidom import parse | 20 from xml.dom.minidom import parse |
21 from xml.dom.minidom import Node | 21 from xml.dom.minidom import Node |
22 | 22 |
23 REPLACEMENTS = dict() | 23 REPLACEMENTS = dict() |
24 ARGUMENTS = None | 24 ARGUMENTS = None |
25 | 25 |
26 | 26 |
27 class CmpTuple(object): | 27 class CmpTuple(object): |
28 """Compare function between 2 tuple.""" | 28 """Compare function between 2 tuple.""" |
29 def __call__(self, x, y): | 29 def __call__(self, x, y): |
30 (key1, value1) = x | 30 return cmp(x[0], y[0]) |
31 (key2, value2) = y | |
32 return cmp(key1, key2) | |
33 | 31 |
34 | 32 |
35 class CmpNode(object): | 33 class CmpNode(object): |
36 """Compare function between 2 xml nodes.""" | 34 """Compare function between 2 xml nodes.""" |
37 | 35 |
38 def get_string(self, node): | 36 def __call__(self, x, y): |
39 node_string = "node" | 37 def get_string(node): |
40 node_string += node.nodeName | 38 node_string = "node" |
41 if node.nodeValue: | 39 node_string += node.nodeName |
42 node_string += node.nodeValue | 40 if node.nodeValue: |
| 41 node_string += node.nodeValue |
43 | 42 |
44 if node.attributes: | 43 if node.attributes: |
45 # We first sort by name, if present. | 44 # We first sort by name, if present. |
46 node_string += node.getAttribute("Name") | 45 node_string += node.getAttribute("Name") |
47 | 46 |
48 all_nodes = [] | 47 all_nodes = [] |
49 for (name, value) in node.attributes.items(): | 48 for (name, value) in node.attributes.items(): |
50 all_nodes.append((name, value)) | 49 all_nodes.append((name, value)) |
51 | 50 |
52 all_nodes.sort(CmpTuple()) | 51 all_nodes.sort(CmpTuple()) |
53 for (name, value) in all_nodes: | 52 for (name, value) in all_nodes: |
54 node_string += name | 53 node_string += name |
55 node_string += value | 54 node_string += value |
56 | 55 |
57 return node_string | 56 return node_string |
58 | 57 |
59 def __call__(self, x, y): | 58 return cmp(get_string(x), get_string(y)) |
60 return cmp(self.get_string(x), self.get_string(y)) | |
61 | 59 |
62 | 60 |
63 def PrettyPrintNode(node, indent=0): | 61 def PrettyPrintNode(node, indent=0): |
64 if node.nodeType == Node.TEXT_NODE: | 62 if node.nodeType == Node.TEXT_NODE: |
65 if node.data.strip(): | 63 if node.data.strip(): |
66 print '%s%s' % (' '*indent, node.data.strip()) | 64 print '%s%s' % (' '*indent, node.data.strip()) |
67 return | 65 return |
68 | 66 |
69 if node.childNodes: | 67 if node.childNodes: |
70 node.normalize() | 68 node.normalize() |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 | 143 |
146 def CleanupVcproj(node): | 144 def CleanupVcproj(node): |
147 """For each sub node, we call recursively this function.""" | 145 """For each sub node, we call recursively this function.""" |
148 for sub_node in node.childNodes: | 146 for sub_node in node.childNodes: |
149 AbsoluteNode(sub_node) | 147 AbsoluteNode(sub_node) |
150 CleanupVcproj(sub_node) | 148 CleanupVcproj(sub_node) |
151 | 149 |
152 # Normalize the node, and remove all extranous whitespaces. | 150 # Normalize the node, and remove all extranous whitespaces. |
153 for sub_node in node.childNodes: | 151 for sub_node in node.childNodes: |
154 if sub_node.nodeType == Node.TEXT_NODE: | 152 if sub_node.nodeType == Node.TEXT_NODE: |
155 sub_node.data = sub_node.data.replace("\r", "") | 153 sub_node.data = sub_node.data.replace("\r", "") |
156 sub_node.data = sub_node.data.replace("\n", "") | 154 sub_node.data = sub_node.data.replace("\n", "") |
157 sub_node.data = sub_node.data.rstrip() | 155 sub_node.data = sub_node.data.rstrip() |
158 | 156 |
159 # Fix all the semicolon separated attributes to be sorted, and we also | 157 # Fix all the semicolon separated attributes to be sorted, and we also |
160 # remove the dups. | 158 # remove the dups. |
161 if node.attributes: | 159 if node.attributes: |
162 for (name, value) in node.attributes.items(): | 160 for (name, value) in node.attributes.items(): |
163 sorted_list = sorted(value.split(';')) | 161 sorted_list = sorted(value.split(';')) |
164 unique_list = [] | 162 unique_list = [] |
165 [unique_list.append(i) for i in sorted_list if not unique_list.count(i)] | 163 for i in sorted_list: |
| 164 if not unique_list.count(i): |
| 165 unique_list.append(i) |
166 node.setAttribute(name, ';'.join(unique_list)) | 166 node.setAttribute(name, ';'.join(unique_list)) |
167 if not value: | 167 if not value: |
168 node.removeAttribute(name) | 168 node.removeAttribute(name) |
169 | 169 |
170 if node.childNodes: | 170 if node.childNodes: |
171 node.normalize() | 171 node.normalize() |
172 | 172 |
173 # For each node, take a copy, and remove it from the list. | 173 # For each node, take a copy, and remove it from the list. |
174 node_array = [] | 174 node_array = [] |
175 while node.childNodes and node.childNodes[0]: | 175 while node.childNodes and node.childNodes[0]: |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 MergeAttributes(node1, node2) | 270 MergeAttributes(node1, node2) |
271 for child2 in node2.childNodes: | 271 for child2 in node2.childNodes: |
272 child1 = SeekToNode(node1, child2) | 272 child1 = SeekToNode(node1, child2) |
273 if child1: | 273 if child1: |
274 MergeProperties(child1, child2) | 274 MergeProperties(child1, child2) |
275 else: | 275 else: |
276 node1.appendChild(child2.cloneNode(True)) | 276 node1.appendChild(child2.cloneNode(True)) |
277 | 277 |
278 | 278 |
279 def main(argv): | 279 def main(argv): |
280 global REPLACEMENTS | 280 """Main function of this vcproj prettifier.""" |
281 global ARGUMENTS | 281 global ARGUMENTS |
282 ARGUMENTS = argv | 282 ARGUMENTS = argv |
283 """Main function of this vcproj prettifier.""" | |
284 | 283 |
285 # check if we have exactly 1 parameter. | 284 # check if we have exactly 1 parameter. |
286 if len(argv) < 2: | 285 if len(argv) < 2: |
287 print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' | 286 print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' |
288 '[key2=value2]' % argv[0]) | 287 '[key2=value2]' % argv[0]) |
289 return 1 | 288 return 1 |
290 | 289 |
291 # Parse the keys | 290 # Parse the keys |
292 for i in range(2, len(argv)): | 291 for i in range(2, len(argv)): |
293 (key, value) = argv[i].split('=') | 292 (key, value) = argv[i].split('=') |
294 REPLACEMENTS[key] = value | 293 REPLACEMENTS[key] = value |
295 | 294 |
296 # Open the vcproj and parse the xml. | 295 # Open the vcproj and parse the xml. |
297 dom = parse(argv[1]) | 296 dom = parse(argv[1]) |
298 | 297 |
299 # First thing we need to do is find the Configuration Node and merge them | 298 # First thing we need to do is find the Configuration Node and merge them |
300 # with the vsprops they include. | 299 # with the vsprops they include. |
301 for configuration_node in GetConfiguationNodes(dom.documentElement): | 300 for configuration_node in GetConfiguationNodes(dom.documentElement): |
302 # Get the property sheets associated with this configuration. | 301 # Get the property sheets associated with this configuration. |
303 vsprops = configuration_node.getAttribute('InheritedPropertySheets') | 302 vsprops = configuration_node.getAttribute('InheritedPropertySheets') |
304 | 303 |
305 # Fix the filenames to be absolute. | 304 # Fix the filenames to be absolute. |
306 vsprops_list = FixFilenames(vsprops.strip().split(';'), | 305 vsprops_list = FixFilenames(vsprops.strip().split(';'), |
307 os.path.dirname(argv[1])) | 306 os.path.dirname(argv[1])) |
308 | 307 |
309 # Extend the list of vsprops with all vsprops contained in the current | 308 # Extend the list of vsprops with all vsprops contained in the current |
310 # vsprops. | 309 # vsprops. |
311 for current_vsprops in vsprops_list: | 310 for current_vsprops in vsprops_list: |
312 vsprops_list.extend(GetChildrenVsprops(current_vsprops)) | 311 vsprops_list.extend(GetChildrenVsprops(current_vsprops)) |
313 | 312 |
314 # Now that we have all the vsprops, we need to merge them. | 313 # Now that we have all the vsprops, we need to merge them. |
315 for current_vsprops in vsprops_list: | 314 for current_vsprops in vsprops_list: |
316 MergeProperties(configuration_node, | 315 MergeProperties(configuration_node, |
317 parse(current_vsprops).documentElement) | 316 parse(current_vsprops).documentElement) |
318 | 317 |
319 # Now that everything is merged, we need to cleanup the xml. | 318 # Now that everything is merged, we need to cleanup the xml. |
320 CleanupVcproj(dom.documentElement) | 319 CleanupVcproj(dom.documentElement) |
321 | 320 |
322 # Finally, we use the prett xml function to print the vcproj back to the | 321 # Finally, we use the prett xml function to print the vcproj back to the |
323 # user. | 322 # user. |
324 #print dom.toprettyxml(newl="\n") | 323 #print dom.toprettyxml(newl="\n") |
325 PrettyPrintNode(dom.documentElement) | 324 PrettyPrintNode(dom.documentElement) |
326 return 0 | 325 return 0 |
327 | 326 |
328 | 327 |
329 if __name__ == '__main__': | 328 if __name__ == '__main__': |
330 sys.exit(main(sys.argv)) | 329 sys.exit(main(sys.argv)) |
OLD | NEW |