source: trip-planner-front/node_modules/node-gyp/gyp/tools/pretty_vcproj.py@ 6a80231

Last change on this file since 6a80231 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 10.5 KB
Line 
1#!/usr/bin/env python
2
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
5# found in the LICENSE file.
6
7"""Make the format of a vcproj really pretty.
8
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.
11
12 It outputs the resulting xml to stdout.
13"""
14
15from __future__ import print_function
16
17import os
18import sys
19
20from xml.dom.minidom import parse
21from xml.dom.minidom import Node
22
23__author__ = "nsylvain (Nicolas Sylvain)"
24
25try:
26 cmp
27except NameError:
28
29 def cmp(x, y):
30 return (x > y) - (x < y)
31
32
33REPLACEMENTS = dict()
34ARGUMENTS = None
35
36
37class CmpTuple(object):
38 """Compare function between 2 tuple."""
39
40 def __call__(self, x, y):
41 return cmp(x[0], y[0])
42
43
44class CmpNode(object):
45 """Compare function between 2 xml nodes."""
46
47 def __call__(self, x, y):
48 def get_string(node):
49 node_string = "node"
50 node_string += node.nodeName
51 if node.nodeValue:
52 node_string += node.nodeValue
53
54 if node.attributes:
55 # We first sort by name, if present.
56 node_string += node.getAttribute("Name")
57
58 all_nodes = []
59 for (name, value) in node.attributes.items():
60 all_nodes.append((name, value))
61
62 all_nodes.sort(CmpTuple())
63 for (name, value) in all_nodes:
64 node_string += name
65 node_string += value
66
67 return node_string
68
69 return cmp(get_string(x), get_string(y))
70
71
72def PrettyPrintNode(node, indent=0):
73 if node.nodeType == Node.TEXT_NODE:
74 if node.data.strip():
75 print("%s%s" % (" " * indent, node.data.strip()))
76 return
77
78 if node.childNodes:
79 node.normalize()
80 # Get the number of attributes
81 attr_count = 0
82 if node.attributes:
83 attr_count = node.attributes.length
84
85 # Print the main tag
86 if attr_count == 0:
87 print("%s<%s>" % (" " * indent, node.nodeName))
88 else:
89 print("%s<%s" % (" " * indent, node.nodeName))
90
91 all_attributes = []
92 for (name, value) in node.attributes.items():
93 all_attributes.append((name, value))
94 all_attributes.sort(CmpTuple())
95 for (name, value) in all_attributes:
96 print('%s %s="%s"' % (" " * indent, name, value))
97 print("%s>" % (" " * indent))
98 if node.nodeValue:
99 print("%s %s" % (" " * indent, node.nodeValue))
100
101 for sub_node in node.childNodes:
102 PrettyPrintNode(sub_node, indent=indent + 2)
103 print("%s</%s>" % (" " * indent, node.nodeName))
104
105
106def FlattenFilter(node):
107 """Returns a list of all the node and sub nodes."""
108 node_list = []
109
110 if node.attributes and node.getAttribute("Name") == "_excluded_files":
111 # We don't add the "_excluded_files" filter.
112 return []
113
114 for current in node.childNodes:
115 if current.nodeName == "Filter":
116 node_list.extend(FlattenFilter(current))
117 else:
118 node_list.append(current)
119
120 return node_list
121
122
123def FixFilenames(filenames, current_directory):
124 new_list = []
125 for filename in filenames:
126 if filename:
127 for key in REPLACEMENTS:
128 filename = filename.replace(key, REPLACEMENTS[key])
129 os.chdir(current_directory)
130 filename = filename.strip("\"' ")
131 if filename.startswith("$"):
132 new_list.append(filename)
133 else:
134 new_list.append(os.path.abspath(filename))
135 return new_list
136
137
138def AbsoluteNode(node):
139 """Makes all the properties we know about in this node absolute."""
140 if node.attributes:
141 for (name, value) in node.attributes.items():
142 if name in [
143 "InheritedPropertySheets",
144 "RelativePath",
145 "AdditionalIncludeDirectories",
146 "IntermediateDirectory",
147 "OutputDirectory",
148 "AdditionalLibraryDirectories",
149 ]:
150 # We want to fix up these paths
151 path_list = value.split(";")
152 new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1]))
153 node.setAttribute(name, ";".join(new_list))
154 if not value:
155 node.removeAttribute(name)
156
157
158def CleanupVcproj(node):
159 """For each sub node, we call recursively this function."""
160 for sub_node in node.childNodes:
161 AbsoluteNode(sub_node)
162 CleanupVcproj(sub_node)
163
164 # Normalize the node, and remove all extraneous whitespaces.
165 for sub_node in node.childNodes:
166 if sub_node.nodeType == Node.TEXT_NODE:
167 sub_node.data = sub_node.data.replace("\r", "")
168 sub_node.data = sub_node.data.replace("\n", "")
169 sub_node.data = sub_node.data.rstrip()
170
171 # Fix all the semicolon separated attributes to be sorted, and we also
172 # remove the dups.
173 if node.attributes:
174 for (name, value) in node.attributes.items():
175 sorted_list = sorted(value.split(";"))
176 unique_list = []
177 for i in sorted_list:
178 if not unique_list.count(i):
179 unique_list.append(i)
180 node.setAttribute(name, ";".join(unique_list))
181 if not value:
182 node.removeAttribute(name)
183
184 if node.childNodes:
185 node.normalize()
186
187 # For each node, take a copy, and remove it from the list.
188 node_array = []
189 while node.childNodes and node.childNodes[0]:
190 # Take a copy of the node and remove it from the list.
191 current = node.childNodes[0]
192 node.removeChild(current)
193
194 # If the child is a filter, we want to append all its children
195 # to this same list.
196 if current.nodeName == "Filter":
197 node_array.extend(FlattenFilter(current))
198 else:
199 node_array.append(current)
200
201 # Sort the list.
202 node_array.sort(CmpNode())
203
204 # Insert the nodes in the correct order.
205 for new_node in node_array:
206 # But don't append empty tool node.
207 if new_node.nodeName == "Tool":
208 if new_node.attributes and new_node.attributes.length == 1:
209 # This one was empty.
210 continue
211 if new_node.nodeName == "UserMacro":
212 continue
213 node.appendChild(new_node)
214
215
216def GetConfiguationNodes(vcproj):
217 # TODO(nsylvain): Find a better way to navigate the xml.
218 nodes = []
219 for node in vcproj.childNodes:
220 if node.nodeName == "Configurations":
221 for sub_node in node.childNodes:
222 if sub_node.nodeName == "Configuration":
223 nodes.append(sub_node)
224
225 return nodes
226
227
228def GetChildrenVsprops(filename):
229 dom = parse(filename)
230 if dom.documentElement.attributes:
231 vsprops = dom.documentElement.getAttribute("InheritedPropertySheets")
232 return FixFilenames(vsprops.split(";"), os.path.dirname(filename))
233 return []
234
235
236def SeekToNode(node1, child2):
237 # A text node does not have properties.
238 if child2.nodeType == Node.TEXT_NODE:
239 return None
240
241 # Get the name of the current node.
242 current_name = child2.getAttribute("Name")
243 if not current_name:
244 # There is no name. We don't know how to merge.
245 return None
246
247 # Look through all the nodes to find a match.
248 for sub_node in node1.childNodes:
249 if sub_node.nodeName == child2.nodeName:
250 name = sub_node.getAttribute("Name")
251 if name == current_name:
252 return sub_node
253
254 # No match. We give up.
255 return None
256
257
258def MergeAttributes(node1, node2):
259 # No attributes to merge?
260 if not node2.attributes:
261 return
262
263 for (name, value2) in node2.attributes.items():
264 # Don't merge the 'Name' attribute.
265 if name == "Name":
266 continue
267 value1 = node1.getAttribute(name)
268 if value1:
269 # The attribute exist in the main node. If it's equal, we leave it
270 # untouched, otherwise we concatenate it.
271 if value1 != value2:
272 node1.setAttribute(name, ";".join([value1, value2]))
273 else:
274 # The attribute does not exist in the main node. We append this one.
275 node1.setAttribute(name, value2)
276
277 # If the attribute was a property sheet attributes, we remove it, since
278 # they are useless.
279 if name == "InheritedPropertySheets":
280 node1.removeAttribute(name)
281
282
283def MergeProperties(node1, node2):
284 MergeAttributes(node1, node2)
285 for child2 in node2.childNodes:
286 child1 = SeekToNode(node1, child2)
287 if child1:
288 MergeProperties(child1, child2)
289 else:
290 node1.appendChild(child2.cloneNode(True))
291
292
293def main(argv):
294 """Main function of this vcproj prettifier."""
295 global ARGUMENTS
296 ARGUMENTS = argv
297
298 # check if we have exactly 1 parameter.
299 if len(argv) < 2:
300 print(
301 'Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] '
302 "[key2=value2]" % argv[0]
303 )
304 return 1
305
306 # Parse the keys
307 for i in range(2, len(argv)):
308 (key, value) = argv[i].split("=")
309 REPLACEMENTS[key] = value
310
311 # Open the vcproj and parse the xml.
312 dom = parse(argv[1])
313
314 # First thing we need to do is find the Configuration Node and merge them
315 # with the vsprops they include.
316 for configuration_node in GetConfiguationNodes(dom.documentElement):
317 # Get the property sheets associated with this configuration.
318 vsprops = configuration_node.getAttribute("InheritedPropertySheets")
319
320 # Fix the filenames to be absolute.
321 vsprops_list = FixFilenames(
322 vsprops.strip().split(";"), os.path.dirname(argv[1])
323 )
324
325 # Extend the list of vsprops with all vsprops contained in the current
326 # vsprops.
327 for current_vsprops in vsprops_list:
328 vsprops_list.extend(GetChildrenVsprops(current_vsprops))
329
330 # Now that we have all the vsprops, we need to merge them.
331 for current_vsprops in vsprops_list:
332 MergeProperties(configuration_node, parse(current_vsprops).documentElement)
333
334 # Now that everything is merged, we need to cleanup the xml.
335 CleanupVcproj(dom.documentElement)
336
337 # Finally, we use the prett xml function to print the vcproj back to the
338 # user.
339 # print dom.toprettyxml(newl="\n")
340 PrettyPrintNode(dom.documentElement)
341 return 0
342
343
344if __name__ == "__main__":
345 sys.exit(main(sys.argv))
Note: See TracBrowser for help on using the repository browser.