Chromium Code Reviews| Index: tools/git/move_source_file.py |
| diff --git a/tools/refactor/move_file.py b/tools/git/move_source_file.py |
| similarity index 43% |
| rename from tools/refactor/move_file.py |
| rename to tools/git/move_source_file.py |
| index c379cdf38af2521e3cda9c8b0f40962a85d32b60..58938deee632b3b37e427b0f591f9f2021ce4995 100755 |
| --- a/tools/refactor/move_file.py |
| +++ b/tools/git/move_source_file.py |
| @@ -7,14 +7,20 @@ |
| point to it. Updates include guards in moved header files. Assumes |
| Chromium coding style. |
| -Does not reorder headers (you can use tools/sort-headers.py), and does |
| -not update .gypi files. |
| +Does not reorder headers; instead, use this after committing all of |
| +your moves: |
| + ./tools/git/for-all-touched-files.py -c "tools/sort-headers.py [[FILENAME]]" |
| -Relies on git for a fast way to find files that include the moved file. |
| +Updates paths used in .gyp(i) files, but does not reorder or |
| +restructure .gyp(i) files in any way. |
| + |
| +Must run in a git checkout, as it relies on git for a fast way to find |
| +files that reference the moved file. |
| """ |
| import os |
| +import re |
| import subprocess |
| import sys |
| @@ -22,30 +28,35 @@ import sys |
| HANDLED_EXTENSIONS = ['.cc', '.mm', '.h', '.hh'] |
| -def MoveFile(from_path, to_path): |
| - """Moves a file from |from_path| to |to_path|, updating its include |
| - guard to match the new path and updating all #includes and #imports |
| - of the file in other files in the same git repository, with the |
| +def MoveFile(from_path, to_path, already_moved): |
|
Nico
2012/11/14 19:51:36
It's a bit confusing that this is called MoveFile
Jói
2012/11/15 15:13:10
Done.
|
| + """Moves a file from |from_path| to |to_path| (unless |
| + |already_moved|), then updates the moved file's include guard to |
| + match the new path and updates all references to the file in other |
| + source files and .gyp(i) files in the same git repository, with the |
| assumption that they include it using the Chromium style |
| - guide-standard full path from root. |
| + guide-standard full path from root, or the .gyp(i) standard full |
| + path from root minus first path component. |
| """ |
| extension = os.path.splitext(from_path)[1] |
| - if extension not in HANDLED_EXTENSIONS: |
| - raise Exception('Only intended to move individual source files.') |
| - dest_extension = os.path.splitext(to_path)[1] |
| - if dest_extension not in HANDLED_EXTENSIONS: |
| - if to_path.endswith('/') or to_path.endswith('\\'): |
| - to_path += os.path.basename(from_path) |
| - else: |
| - raise Exception('Destination must be either full path or end with /.') |
| + if not already_moved: |
| + if extension not in HANDLED_EXTENSIONS: |
| + raise Exception('Only intended to move individual source files.') |
| + dest_extension = os.path.splitext(to_path)[1] |
| + if dest_extension not in HANDLED_EXTENSIONS: |
| + if to_path.endswith('/') or to_path.endswith('\\'): |
| + to_path += os.path.basename(from_path) |
| + else: |
| + raise Exception('Destination must be either full path or end with /.') |
| - if not os.system('git mv %s %s' % (from_path, to_path)) == 0: |
| - raise Exception('Fatal: Failed to run git mv command.') |
| + if not os.system('git mv %s %s' % (from_path, to_path)) == 0: |
| + raise Exception('Fatal: Failed to run git mv command.') |
| if extension in ['.h', '.hh']: |
| UpdateIncludeGuard(from_path, to_path) |
| - UpdateIncludes(from_path, to_path) |
| + UpdateUsages(from_path, to_path, includes=True) |
| + |
| + UpdateUsages(from_path, to_path, includes=False) |
| def MakeIncludeGuardName(path_from_root): |
| @@ -79,28 +90,50 @@ def UpdateIncludeGuard(old_path, new_path): |
| f.write(new_contents) |
| -def UpdateIncludes(old_path, new_path): |
| +def UpdateUsages(old_path, new_path, includes): |
| """Given the |old_path| and |new_path| of a file being moved, update |
| - #include and #import statements in all files in the same git |
| - repository referring to the moved file. |
| + usages (#include, #import, or reference in a .gyp(i) file) in all files |
| + in the same git repository referring to the moved file. |
| + |
| + Updates includes when |includes| is True, .gyp(i) files when |
| + |includes| is False. |
| """ |
| # Include paths always use forward slashes. |
| old_path = old_path.replace('\\', '/') |
| new_path = new_path.replace('\\', '/') |
| - out, err = subprocess.Popen( |
| - ['git', 'grep', '--name-only', |
| - r'#\(include\|import\)\s*["<]%s[>"]' % old_path], |
| - stdout=subprocess.PIPE).communicate() |
| - includees = out.splitlines() |
| + if includes: |
| + out, err = subprocess.Popen( |
| + ['git', 'grep', '--name-only', |
| + r'#\(include\|import\)\s*["<]%s[>"]' % old_path, |
| + '--', '*.cc', '*.h', '*.m', '*.mm'], |
| + stdout=subprocess.PIPE).communicate() |
| + includees = out.splitlines() |
| + else: |
| + def PathMinusFirstComponent(path): |
| + parts = re.split(r"[/\\]", path, 1) |
| + if len(parts) == 2: |
| + return parts[1] |
| + else: |
| + return parts[0] |
| + old_path = PathMinusFirstComponent(old_path) |
| + new_path = PathMinusFirstComponent(new_path) |
| + out, err = subprocess.Popen( |
| + ['git', 'grep', '--name-only', |
| + r'[\'"]%s[\'"]' % old_path, '--', '*.gyp*'], |
| + stdout=subprocess.PIPE).communicate() |
| + includees = out.splitlines() |
| for includee in includees: |
| with open(includee) as f: |
| contents = f.read() |
| new_contents = contents.replace('"%s"' % old_path, '"%s"' % new_path) |
| - new_contents = new_contents.replace('<%s>' % old_path, '<%s>' % new_path) |
| + if includes: |
| + new_contents = new_contents.replace('<%s>' % old_path, '<%s>' % new_path) |
| + else: |
| + new_contents = new_contents.replace("'%s'" % old_path, "'%s'" % new_path) |
| if new_contents == contents: |
| - raise Exception('Error updating include in file %s' % includee) |
| + raise Exception('Error updating usage in file %s' % includee) |
| with open(includee, 'w') as f: |
| f.write(new_contents) |
| @@ -110,10 +143,16 @@ def main(): |
| print 'Fatal: You must run from the root of a git checkout.' |
| return 1 |
| args = sys.argv[1:] |
| - if len(args) != 2: |
| - print 'Usage: move_file.py FROM_PATH TO_PATH\n\n%s' % __doc__ |
| + if not len(args) in [2, 3]: |
| + print ('Usage: move_source_file.py [--already-moved] FROM_PATH TO_PATH' |
| + '\n\n%s' % __doc__) |
| return 1 |
| - MoveFile(args[0], args[1]) |
| + already_moved = False |
| + if args[0] == '--already-moved': |
| + args = args[1:] |
| + already_moved = True |
| + |
| + MoveFile(args[0], args[1], already_moved) |
| return 0 |