summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-26 00:23:26 +0000
committerevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-26 00:23:26 +0000
commit50e5a3dbf067d3c0bdfce8ab8df62a2130bc0e4b (patch)
tree8af465317172de1f21b3e26ff23813cafd5b5531
parent37858e5c2f58f4b46117c65df2ab3da8a7b2e6e2 (diff)
downloadchromium_src-50e5a3dbf067d3c0bdfce8ab8df62a2130bc0e4b.zip
chromium_src-50e5a3dbf067d3c0bdfce8ab8df62a2130bc0e4b.tar.gz
chromium_src-50e5a3dbf067d3c0bdfce8ab8df62a2130bc0e4b.tar.bz2
Check in a quick tool for sorting the #includes in a file.
This is especially useful when you do a mass-rename of a header and now need to fix every user of it. Special thanks to pamg for fixing my Python style! Review URL: http://codereview.chromium.org/3149032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57435 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-xtools/sort-headers.py94
1 files changed, 94 insertions, 0 deletions
diff --git a/tools/sort-headers.py b/tools/sort-headers.py
new file mode 100755
index 0000000..b18ac6c
--- /dev/null
+++ b/tools/sort-headers.py
@@ -0,0 +1,94 @@
+#!/usr/bin/python
+
+"""Given a filename as an argument, sort the #include/#imports in that file.
+
+Shows a diff and prompts for confirmation before doing the deed.
+"""
+
+import optparse
+import os
+import sys
+import termios
+import tty
+
+def YesNo(prompt):
+ """Prompts with a yes/no question, returns True if yes."""
+ print prompt,
+ sys.stdout.flush()
+ # http://code.activestate.com/recipes/134892/
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ ch = 'n'
+ try:
+ tty.setraw(sys.stdin.fileno())
+ ch = sys.stdin.read(1)
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+ print ch
+ return ch in ('Y', 'y')
+
+
+def IncludeCompareKey(line):
+ """Sorting comparator key used for comparing two #include lines.
+ Returns the filename without the #include/#import prefix.
+ """
+ for prefix in ('#include ', '#import '):
+ if line.startswith(prefix):
+ return line[len(prefix):]
+ return line
+
+
+def IsInclude(line):
+ """Returns True if the line is an #include/#import line."""
+ return line.startswith('#include ') or line.startswith('#import ')
+
+
+def SortHeader(infile, outfile):
+ """Sorts the headers in infile, writing the sorted file to outfile."""
+ for line in infile:
+ if IsInclude(line):
+ headerblock = []
+ while IsInclude(line):
+ headerblock.append(line)
+ line = infile.next()
+ for header in sorted(headerblock, key=IncludeCompareKey):
+ outfile.write(header)
+ # Intentionally fall through, to write the line that caused
+ # the above while loop to exit.
+ outfile.write(line)
+
+
+def main():
+ parser = optparse.OptionParser(usage='%prog filename1 filename2 ...')
+ opts, args = parser.parse_args()
+
+ if len(args) < 1:
+ parser.print_help()
+ sys.exit(1)
+
+ for filename in args:
+ fixfilename = filename + '.new'
+ infile = open(filename, 'r')
+ outfile = open(fixfilename, 'w')
+ SortHeader(infile, outfile)
+ infile.close()
+ outfile.close() # Important so the below diff gets the updated contents.
+
+ try:
+ diff = os.system('diff -u %s %s' % (filename, fixfilename))
+ if diff >> 8 == 0: # Check exit code.
+ print '%s: no change' % filename
+ continue
+
+ if YesNo('Use new file (y/N)?'):
+ os.rename(fixfilename, filename)
+ finally:
+ try:
+ os.remove(fixfilename)
+ except OSError:
+ # If the file isn't there, we don't care.
+ pass
+
+
+if __name__ == '__main__':
+ main()