Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # Copyright 2017 The Chromium Authors. All rights reserved. | 2 # Copyright 2017 The Chromium Authors. All rights reserved. | 
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be | 
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. | 
| 5 | 5 | 
| 6 """Fix header files missing in GN. | 6 """Fix header files missing in GN. | 
| 7 | 7 | 
| 8 This script takes the missing header files from check_gn_headers.py, and | 8 This script takes the missing header files from check_gn_headers.py, and | 
| 9 try to fix them by adding them to the GN files. | 9 try to fix them by adding them to the GN files. | 
| 10 Manual cleaning up is likely required afterwards. | 10 Manual cleaning up is likely required afterwards. | 
| 11 """ | 11 """ | 
| 12 | 12 | 
| 13 import argparse | 13 import argparse | 
| 14 import os | 14 import os | 
| 15 import re | 15 import re | 
| 16 import subprocess | 16 import subprocess | 
| 17 import sys | 17 import sys | 
| 18 | 18 | 
| 19 | 19 | 
| 20 def GitGrep(pattern): | |
| 
 
wychen
2017/03/31 16:42:39
Locally I use joblib.Memory to decorate this, so I
 
 | |
| 21 p = subprocess.Popen( | |
| 22 ['git', 'grep', '-En', pattern, '--', '*.gn', '*.gni'], | |
| 23 stdout=subprocess.PIPE) | |
| 24 out, _ = p.communicate() | |
| 25 return out, p.returncode | |
| 26 | |
| 27 | |
| 28 def ValidMatches(basename, cc, grep_lines): | |
| 
 
Nico
2017/03/31 16:50:57
function-level comment summarizing what this does
 
wychen
2017/04/01 05:32:04
Done.
 
 | |
| 29 matches = [] | |
| 30 for line in grep_lines: | |
| 31 gnfile, linenr, contents = line.split(':') | |
| 32 linenr = int(linenr) | |
| 33 new = re.sub(cc, basename, contents) | |
| 34 lines = open(gnfile).read().splitlines() | |
| 35 assert contents in lines[linenr - 1] | |
| 36 # Skip if it's already there. It could be before or after the match. | |
| 37 if lines[linenr] == new: | |
| 38 continue | |
| 39 if lines[linenr - 2] == new: | |
| 40 continue | |
| 41 print ' ', gnfile, linenr, new | |
| 42 matches.append((gnfile, linenr, new)) | |
| 43 return matches | |
| 44 | |
| 45 | |
| 20 def AddHeadersNextToCC(headers, skip_ambiguous=True): | 46 def AddHeadersNextToCC(headers, skip_ambiguous=True): | 
| 21 """Add header files next to the corresponding .cc files in GN files. | 47 """Add header files next to the corresponding .cc files in GN files. | 
| 22 | 48 | 
| 23 When skip_ambiguous is True, skip if multiple .cc files are found. | 49 When skip_ambiguous is True, skip if multiple .cc files are found. | 
| 24 Returns unhandled headers. | 50 Returns unhandled headers. | 
| 25 | 51 | 
| 26 Manual cleaning up is likely required, especially if not skip_ambiguous. | 52 Manual cleaning up is likely required, especially if not skip_ambiguous. | 
| 27 """ | 53 """ | 
| 28 edits = {} | 54 edits = {} | 
| 29 unhandled = [] | 55 unhandled = [] | 
| 30 for filename in headers: | 56 for filename in headers: | 
| 31 filename = filename.strip() | 57 filename = filename.strip() | 
| 32 if not (filename.endswith('.h') or filename.endswith('.hh')): | 58 if not (filename.endswith('.h') or filename.endswith('.hh')): | 
| 33 continue | 59 continue | 
| 34 basename = os.path.basename(filename) | 60 basename = os.path.basename(filename) | 
| 35 print filename | 61 print filename | 
| 36 cc = r'\b' + os.path.splitext(basename)[0] + r'\.(cc|cpp|mm)\b' | 62 cc = r'\b' + os.path.splitext(basename)[0] + r'\.(cc|cpp|mm)\b' | 
| 37 p = subprocess.Popen( | 63 out, returncode = GitGrep('(/|")' + cc + '"') | 
| 
 
Nico
2017/03/31 16:50:57
nit: r'\b' instead of '(/|")'
 
wychen
2017/03/31 16:56:56
'\b' is already there, but it's not enough. For ex
 
wychen
2017/03/31 16:58:08
Ah. using sep might be better since we might want
 
 | |
| 38 ['git', 'grep', '-En', cc + '"', '--', '*.gn', '*.gni'], | 64 if returncode != 0 or not out: | 
| 39 stdout=subprocess.PIPE) | |
| 40 out, _ = p.communicate() | |
| 41 if p.returncode != 0 or not out: | |
| 42 unhandled.append(filename) | 65 unhandled.append(filename) | 
| 43 continue | 66 continue | 
| 44 | 67 | 
| 45 if skip_ambiguous and len(out.splitlines()) > 1: | 68 matches = ValidMatches(basename, cc, out.splitlines()) | 
| 69 | |
| 70 if len(matches) == 0: | |
| 71 continue | |
| 72 if len(matches) > 1: | |
| 46 print '\n[WARNING] Ambiguous matching for', filename | 73 print '\n[WARNING] Ambiguous matching for', filename | 
| 47 print out | 74 for i in enumerate(matches, 1): | 
| 48 continue | 75 print '%d: %s' % (i[0], i[1]) | 
| 76 print | |
| 77 if skip_ambiguous: | |
| 78 continue | |
| 49 | 79 | 
| 50 for gnline in out.splitlines(): | 80 picked = raw_input('Pick the matches ("2,3" for multiple): ') | 
| 51 gnfile, linenr, contents = gnline.split(':') | 81 try: | 
| 52 linenr = int(linenr) | 82 matches = [matches[int(i) - 1] for i in picked.split(',')] | 
| 53 new = re.sub(cc, basename, contents) | 83 except (ValueError, IndexError): | 
| 54 lines = open(gnfile).read().splitlines() | |
| 55 # Skip if it's already there. It could be before or after the match. | |
| 56 if lines[linenr] == new: | |
| 57 continue | 84 continue | 
| 58 if lines[linenr - 2] == new: | 85 | 
| 59 continue | 86 for match in matches: | 
| 87 gnfile, linenr, new = match | |
| 60 print ' ', gnfile, linenr, new | 88 print ' ', gnfile, linenr, new | 
| 61 edits.setdefault(gnfile, {})[linenr] = new | 89 edits.setdefault(gnfile, {})[linenr] = new | 
| 62 | 90 | 
| 63 for gnfile in edits: | 91 for gnfile in edits: | 
| 64 lines = open(gnfile).read().splitlines() | 92 lines = open(gnfile).read().splitlines() | 
| 65 for l in sorted(edits[gnfile].keys(), reverse=True): | 93 for l in sorted(edits[gnfile].keys(), reverse=True): | 
| 66 lines.insert(l, edits[gnfile][l]) | 94 lines.insert(l, edits[gnfile][l]) | 
| 67 open(gnfile, 'w').write('\n'.join(lines) + '\n') | 95 open(gnfile, 'w').write('\n'.join(lines) + '\n') | 
| 68 | 96 | 
| 69 return unhandled | 97 return unhandled | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 | 144 | 
| 117 if args.prefix: | 145 if args.prefix: | 
| 118 headers = [i for i in headers if i.startswith(args.prefix)] | 146 headers = [i for i in headers if i.startswith(args.prefix)] | 
| 119 | 147 | 
| 120 unhandled = AddHeadersNextToCC(headers) | 148 unhandled = AddHeadersNextToCC(headers) | 
| 121 AddHeadersToSources(unhandled) | 149 AddHeadersToSources(unhandled) | 
| 122 | 150 | 
| 123 | 151 | 
| 124 if __name__ == '__main__': | 152 if __name__ == '__main__': | 
| 125 sys.exit(main()) | 153 sys.exit(main()) | 
| OLD | NEW |