| 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 |