Added histograms for default search provider protection. Removed protection
[chromium-blink-merge.git] / tools / sort-headers.py
blobe51343ca861c54405e8c673e2985d075ff0e6480
1 #!/usr/bin/python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Given a filename as an argument, sort the #include/#imports in that file.
8 Shows a diff and prompts for confirmation before doing the deed.
9 """
11 import optparse
12 import os
13 import sys
14 import termios
15 import tty
17 def YesNo(prompt):
18 """Prompts with a yes/no question, returns True if yes."""
19 print prompt,
20 sys.stdout.flush()
21 # http://code.activestate.com/recipes/134892/
22 fd = sys.stdin.fileno()
23 old_settings = termios.tcgetattr(fd)
24 ch = 'n'
25 try:
26 tty.setraw(sys.stdin.fileno())
27 ch = sys.stdin.read(1)
28 finally:
29 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
30 print ch
31 return ch in ('Y', 'y')
34 def IncludeCompareKey(line):
35 """Sorting comparator key used for comparing two #include lines.
36 Returns the filename without the #include/#import prefix.
37 """
38 for prefix in ('#include ', '#import '):
39 if line.startswith(prefix):
40 line = line[len(prefix):]
41 break
43 # The win32 api has all sorts of implicit include order dependencies :-/
44 # Give a few headers special sort keys that make sure they appear before all
45 # other headers.
46 if line.startswith('<windows.h>'): # Must be before e.g. shellapi.h
47 return '0'
48 if line.startswith('<unknwn.h>'): # Must be before e.g. intshcut.h
49 return '1'
51 return line
54 def IsInclude(line):
55 """Returns True if the line is an #include/#import line."""
56 return line.startswith('#include ') or line.startswith('#import ')
59 def SortHeader(infile, outfile):
60 """Sorts the headers in infile, writing the sorted file to outfile."""
61 for line in infile:
62 if IsInclude(line):
63 headerblock = []
64 while IsInclude(line):
65 headerblock.append(line)
66 line = infile.next()
67 for header in sorted(headerblock, key=IncludeCompareKey):
68 outfile.write(header)
69 # Intentionally fall through, to write the line that caused
70 # the above while loop to exit.
71 outfile.write(line)
74 def main():
75 parser = optparse.OptionParser(usage='%prog filename1 filename2 ...')
76 opts, args = parser.parse_args()
78 if len(args) < 1:
79 parser.print_help()
80 sys.exit(1)
82 for filename in args:
83 fixfilename = filename + '.new'
84 infile = open(filename, 'r')
85 outfile = open(fixfilename, 'w')
86 SortHeader(infile, outfile)
87 infile.close()
88 outfile.close() # Important so the below diff gets the updated contents.
90 try:
91 diff = os.system('diff -u %s %s' % (filename, fixfilename))
92 if diff >> 8 == 0: # Check exit code.
93 print '%s: no change' % filename
94 continue
96 if YesNo('Use new file (y/N)?'):
97 os.rename(fixfilename, filename)
98 finally:
99 try:
100 os.remove(fixfilename)
101 except OSError:
102 # If the file isn't there, we don't care.
103 pass
106 if __name__ == '__main__':
107 main()