Skip to content

Instantly share code, notes, and snippets.

@elijahr
Created August 24, 2011 18:13
Show Gist options
  • Save elijahr/1168739 to your computer and use it in GitHub Desktop.
Save elijahr/1168739 to your computer and use it in GitHub Desktop.
A script to aid in refactoring a git-managed codebase
#!/opt/pypy/bin/pypy
# easy project refactoring.
import os
import shutil
from subprocess import Popen
def build_parser():
"""
Returns an argparse.ArgumentParser instance to parse the command line
arguments for rfr
"""
import argparse
description = "A simple refactoring tool"
parser = argparse.ArgumentParser(description=description)
parser.add_argument('--dry-run', '-d', dest='dry_run', action='store_true',
default=False, help='Print expected output but do not actually move or edit any files')
parser.add_argument('--ignore-binary', '-i', dest='ignore_binary', action='store_true',
default=False, help='Don\'t warn about binary file content matches')
parser.add_argument('oldstring', metavar='OLDSTRING', action='store',
help='a string that you wish to replace both inside of files and in file/directory names')
parser.add_argument('newstring', metavar='NEWSTRING', action='store',
help='a string that you wish to replace OLDSTRING with')
parser.add_argument('directory', metavar='DIRECTORY', nargs='?',
default=os.getcwd(), help='a directory to search in (default cwd)')
return parser
if __name__ == '__main__':
parser = build_parser()
args = parser.parse_args()
# first, ensure that no instances of newstring exist already
for dirpath, dirnames, filenames in os.walk(args.directory):
if '.git' in dirnames:
dirnames.remove('.git')
for dirname in dirnames:
if dirname.find(args.oldstring) >= 0:
olddir = os.path.join(dirpath, dirname)
newdir = os.path.join(dirpath, dirname.replace(args.oldstring, args.newstring))
if not os.path.exists(newdir):
if not args.dry_run:
pargs = ['/bin/sh -c "cd %s && git mv %s %s"' % (args.directory, olddir, newdir)]
p = Popen(pargs, shell=True)
p.communicate()
print "Renamed directory %s to %s" % (olddir, newdir)
else:
print "Warning: could not rename directory %s to %s, path already exists" % (olddir, newdir)
for dirpath, dirnames, filenames in os.walk(args.directory):
if '.git' in dirnames:
dirnames.remove('.git')
for filename in filenames:
if filename.find(args.oldstring) >= 0:
oldfile = os.path.join(dirpath, filename)
newfile = os.path.join(dirpath, filename.replace(args.oldstring, args.newstring))
if not os.path.exists(newfile):
if not args.dry_run:
pargs = ['/bin/sh -c "cd %s && git mv %s %s"' % (args.directory, oldfile, newfile)]
p = Popen(args, shell=True)
p.communicate()
print "Renamed file %s to %s" % (oldfile, newfile)
else:
print "Warning: could not rename file %s to %s, path already exists" % (oldfile, newfile)
for dirpath, dirnames, filenames in os.walk(args.directory):
if '.git' in dirnames:
dirnames.remove('.git')
for filename in filenames:
newfile = os.path.join(dirpath, filename)
f = open(newfile, 'r+b')
old_file_contents = f.read()
f.close()
new_file_contents = old_file_contents.replace(args.oldstring, args.newstring)
if new_file_contents.find('\000') >= 0:
if not args.ignore_binary and old_file_contents != new_file_contents:
print "Warning, binary file %s contains match. I won't modify it but I thought you should know..." % newfile
else:
if old_file_contents != new_file_contents:
if not args.dry_run:
f = open(newfile, 'w+b')
f.write(new_file_contents)
f.close()
print "Replacements made in %s" % newfile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment