Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: tools/git/move_source_file.py

Issue 11412006: Automatically sort headers in files affected by move_source_file.py (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to review comments. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/sort-headers.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 """Moves a C++ file to a new location, updating any include paths that 6 """Moves a C++ file to a new location, updating any include paths that
7 point to it. Updates include guards in moved header files. Assumes 7 point to it, and re-ordering headers as needed. Updates include
8 Chromium coding style. 8 guards in moved header files. Assumes Chromium coding style.
9 9
10 Does not reorder headers; instead, use this after committing all of 10 Attempts to update paths used in .gyp(i) files, but does not reorder
11 your moves: 11 or restructure .gyp(i) files in any way.
12 ./tools/git/for-all-touched-files.py -c "tools/sort-headers.py [[FILENAME]]"
13 12
14 Updates paths used in .gyp(i) files, but does not reorder or 13 Updates full-path references to files in // comments in source files.
15 restructure .gyp(i) files in any way.
16 14
17 Must run in a git checkout, as it relies on git for a fast way to find 15 Must run in a git checkout, as it relies on git grep for a fast way to
18 files that reference the moved file. 16 find files that reference the moved file.
19 """ 17 """
20 18
21 19
22 import os 20 import os
23 import re 21 import re
24 import subprocess 22 import subprocess
25 import sys 23 import sys
26 24
25 if __name__ == '__main__':
26 # Need to add the directory containing sort-headers.py to the Python
27 # classpath.
28 sys.path.append(os.path.abspath(os.path.join(sys.path[0], '..')))
29 sort_headers = __import__('sort-headers')
30
31
27 HANDLED_EXTENSIONS = ['.cc', '.mm', '.h', '.hh'] 32 HANDLED_EXTENSIONS = ['.cc', '.mm', '.h', '.hh']
28 33
29 34
30 def MakeDestinationPath(from_path, to_path): 35 def MakeDestinationPath(from_path, to_path):
31 """Given the from and to paths, return a correct destination path. 36 """Given the from and to paths, return a correct destination path.
32 37
33 The initial destination path may either a full path or a directory, 38 The initial destination path may either a full path or a directory,
34 in which case the path must end with /. Also does basic sanity 39 in which case the path must end with /. Also does basic sanity
35 checks. 40 checks.
36 """ 41 """
(...skipping 10 matching lines...) Expand all
47 52
48 def MoveFile(from_path, to_path): 53 def MoveFile(from_path, to_path):
49 """Performs a git mv command to move a file from |from_path| to |to_path|. 54 """Performs a git mv command to move a file from |from_path| to |to_path|.
50 """ 55 """
51 if not os.system('git mv %s %s' % (from_path, to_path)) == 0: 56 if not os.system('git mv %s %s' % (from_path, to_path)) == 0:
52 raise Exception('Fatal: Failed to run git mv command.') 57 raise Exception('Fatal: Failed to run git mv command.')
53 58
54 59
55 def MultiFileFindReplace(original, 60 def MultiFileFindReplace(original,
56 replacement, 61 replacement,
57 grep_pattern, 62 file_globs):
58 file_globs, 63 """Implements fast multi-file find and replace.
59 guard_formats):
60 """Implements fast multi-file find and replace with optional guards.
61 64
62 Given an |original| string and a |replacement| string, search for 65 Given an |original| string and a |replacement| string, find matching
63 them by formatting |grep_pattern| with |original| and running 66 files by running git grep on |original| in files matching any
64 git grep on the result, for files matching any of |file_globs|. 67 pattern in |file_globs|.
65 68
66 Once files are found, the function searches for any of 69 Once files are found, |re.sub| is run to replace |original| with
67 |guard_formats| formatted with |original| and replaces each match 70 |replacement|. |replacement| may use capture group back-references.
68 with the same guard format as matched, formatted with |replacement|.
69 71
70 Args: 72 Args:
71 original: 'chrome/browser/ui/browser.h' 73 original: '(#(include|import)\s*["<])chrome/browser/ui/browser.h([>"])'
72 replacement: 'chrome/browser/ui/browser/browser.h' 74 replacement: '\1chrome/browser/ui/browser/browser.h\3'
73 grep_pattern: r'#(include|import)\s*["<]%s[>"]'
74 file_globs: ['*.cc', '*.h', '*.m', '*.mm'] 75 file_globs: ['*.cc', '*.h', '*.m', '*.mm']
75 guard_formats: None or ('"%s"', '<%s>') 76
77 Returns the list of files modified.
76 78
77 Raises an exception on error. 79 Raises an exception on error.
78 """ 80 """
79 out, err = subprocess.Popen( 81 out, err = subprocess.Popen(
80 ['git', 'grep', '-E', '--name-only', 82 ['git', 'grep', '-E', '--name-only', original, '--'] + file_globs,
81 grep_pattern % re.escape(original), '--'] + file_globs, 83 stdout=subprocess.PIPE).communicate()
82 stdout=subprocess.PIPE).communicate()
83 referees = out.splitlines() 84 referees = out.splitlines()
84 85
85 for referee in referees: 86 for referee in referees:
86 with open(referee) as f: 87 with open(referee) as f:
87 original_contents = f.read() 88 original_contents = f.read()
88 contents = original_contents 89 contents = re.sub(original, replacement, original_contents)
89 for guard_format in guard_formats or []:
90 contents = contents.replace(guard_format % original,
91 guard_format % replacement)
92 if contents == original_contents: 90 if contents == original_contents:
93 raise Exception('No change in file %s although matched in grep' % 91 raise Exception('No change in file %s although matched in grep' %
94 referee) 92 referee)
95 with open(referee, 'w') as f: 93 with open(referee, 'w') as f:
96 f.write(contents) 94 f.write(contents)
97 95
96 return referees
97
98 98
99 def UpdatePostMove(from_path, to_path): 99 def UpdatePostMove(from_path, to_path):
100 """Given a file that has moved from |from_path| to |to_path|, 100 """Given a file that has moved from |from_path| to |to_path|,
101 updates the moved file's include guard to match the new path and 101 updates the moved file's include guard to match the new path and
102 updates all references to the file in other source files. Also tries 102 updates all references to the file in other source files. Also tries
103 to update references in .gyp(i) files using a heuristic. 103 to update references in .gyp(i) files using a heuristic.
104 """ 104 """
105 # Include paths always use forward slashes. 105 # Include paths always use forward slashes.
106 from_path = from_path.replace('\\', '/') 106 from_path = from_path.replace('\\', '/')
107 to_path = to_path.replace('\\', '/') 107 to_path = to_path.replace('\\', '/')
108 108
109 if os.path.splitext(from_path)[1] in ['.h', '.hh']: 109 if os.path.splitext(from_path)[1] in ['.h', '.hh']:
110 UpdateIncludeGuard(from_path, to_path) 110 UpdateIncludeGuard(from_path, to_path)
111 111
112 # Update include/import references. 112 # Update include/import references.
113 MultiFileFindReplace( 113 files_with_changed_includes = MultiFileFindReplace(
114 from_path, 114 r'(#(include|import)\s*["<])%s([>"])' % re.escape(from_path),
115 to_path, 115 r'\1%s\3' % to_path,
116 r'#(include|import)\s*["<]%s[>"]', 116 ['*.cc', '*.h', '*.m', '*.mm'])
117 ['*.cc', '*.h', '*.m', '*.mm'], 117
118 ['"%s"', '<%s>']) 118 # Reorder headers in files that changed.
119 for changed_file in files_with_changed_includes:
120 def AlwaysConfirm(a, b): return True
121 sort_headers.FixFileWithConfirmFunction(changed_file, AlwaysConfirm)
122
123 # Update comments; only supports // comments, which are primarily
124 # used in our code.
125 #
126 # This work takes a bit of time. If this script starts feeling too
127 # slow, one good way to speed it up is to make the comment handling
128 # optional under a flag.
129 MultiFileFindReplace(
130 r'(//.*)%s' % re.escape(from_path),
131 r'\1%s' % to_path,
132 ['*.cc', '*.h', '*.m', '*.mm'])
119 133
120 # Update references in .gyp(i) files. 134 # Update references in .gyp(i) files.
121 def PathMinusFirstComponent(path): 135 def PathMinusFirstComponent(path):
122 """foo/bar/baz -> bar/baz""" 136 """foo/bar/baz -> bar/baz"""
123 parts = re.split(r"[/\\]", path, 1) 137 parts = re.split(r"[/\\]", path, 1)
124 if len(parts) == 2: 138 if len(parts) == 2:
125 return parts[1] 139 return parts[1]
126 else: 140 else:
127 return parts[0] 141 return parts[0]
128 MultiFileFindReplace(PathMinusFirstComponent(from_path), 142 MultiFileFindReplace(
129 PathMinusFirstComponent(to_path), 143 r'([\'"])%s([\'"])' % re.escape(PathMinusFirstComponent(from_path)),
130 r'[\'"]%s[\'"]', 144 r'\1%s\2' % PathMinusFirstComponent(to_path),
131 ['*.gyp*'], 145 ['*.gyp*'])
132 ["'%s'", '"%s"'])
133 146
134 147
135 def MakeIncludeGuardName(path_from_root): 148 def MakeIncludeGuardName(path_from_root):
136 """Returns an include guard name given a path from root.""" 149 """Returns an include guard name given a path from root."""
137 guard = path_from_root.replace('/', '_') 150 guard = path_from_root.replace('/', '_')
138 guard = guard.replace('\\', '_') 151 guard = guard.replace('\\', '_')
139 guard = guard.replace('.', '_') 152 guard = guard.replace('.', '_')
140 guard += '_' 153 guard += '_'
141 return guard.upper() 154 return guard.upper()
142 155
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 196
184 to_path = MakeDestinationPath(from_path, to_path) 197 to_path = MakeDestinationPath(from_path, to_path)
185 if not already_moved: 198 if not already_moved:
186 MoveFile(from_path, to_path) 199 MoveFile(from_path, to_path)
187 UpdatePostMove(from_path, to_path) 200 UpdatePostMove(from_path, to_path)
188 return 0 201 return 0
189 202
190 203
191 if __name__ == '__main__': 204 if __name__ == '__main__':
192 sys.exit(main()) 205 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/sort-headers.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698