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

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: Improve 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:
Nico 2012/11/21 18:35:36 I'd do `def auto_confirm(a, b): return true; FixFi
Jói 2012/11/22 09:42:50 Done.
120 sort_headers.FixFileWithConfirmFunction(changed_file, lambda a, b: True)
121
122 # Update comments; only supports // comments, which are primarily
123 # used in our code.
124 MultiFileFindReplace(
125 r'(//.*)%s' % re.escape(from_path),
126 r'\1%s' % to_path,
127 ['*.cc', '*.h', '*.m', '*.mm'])
Nico 2012/11/21 18:35:36 I'd omit this as I said. It only finds comments th
Jói 2012/11/22 09:42:50 I'll leave it in since it's safe and convenient an
119 128
120 # Update references in .gyp(i) files. 129 # Update references in .gyp(i) files.
121 def PathMinusFirstComponent(path): 130 def PathMinusFirstComponent(path):
122 """foo/bar/baz -> bar/baz""" 131 """foo/bar/baz -> bar/baz"""
123 parts = re.split(r"[/\\]", path, 1) 132 parts = re.split(r"[/\\]", path, 1)
124 if len(parts) == 2: 133 if len(parts) == 2:
125 return parts[1] 134 return parts[1]
126 else: 135 else:
127 return parts[0] 136 return parts[0]
128 MultiFileFindReplace(PathMinusFirstComponent(from_path), 137 MultiFileFindReplace(
129 PathMinusFirstComponent(to_path), 138 r'([\'"])%s([\'"])' % re.escape(PathMinusFirstComponent(from_path)),
130 r'[\'"]%s[\'"]', 139 r'\1%s\2' % PathMinusFirstComponent(to_path),
131 ['*.gyp*'], 140 ['*.gyp*'])
132 ["'%s'", '"%s"'])
133 141
134 142
135 def MakeIncludeGuardName(path_from_root): 143 def MakeIncludeGuardName(path_from_root):
136 """Returns an include guard name given a path from root.""" 144 """Returns an include guard name given a path from root."""
137 guard = path_from_root.replace('/', '_') 145 guard = path_from_root.replace('/', '_')
138 guard = guard.replace('\\', '_') 146 guard = guard.replace('\\', '_')
139 guard = guard.replace('.', '_') 147 guard = guard.replace('.', '_')
140 guard += '_' 148 guard += '_'
141 return guard.upper() 149 return guard.upper()
142 150
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 191
184 to_path = MakeDestinationPath(from_path, to_path) 192 to_path = MakeDestinationPath(from_path, to_path)
185 if not already_moved: 193 if not already_moved:
186 MoveFile(from_path, to_path) 194 MoveFile(from_path, to_path)
187 UpdatePostMove(from_path, to_path) 195 UpdatePostMove(from_path, to_path)
188 return 0 196 return 0
189 197
190 198
191 if __name__ == '__main__': 199 if __name__ == '__main__':
192 sys.exit(main()) 200 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