style: Make the style fixers safe

Adds a wrapper to the fix functions of the verifiers. This wrapper first
copies the original file to a backup file, then performs the fix. If an
error occurs, the backup file is used to restore the original file.

Also fixed a line-length error in verifiers.py
This commit is contained in:
Jason Lowe-Power 2016-08-03 11:10:46 -05:00
parent ba09d8ac92
commit 8eb9cf8e94

View file

@ -56,6 +56,40 @@ import sort_includes
from region import * from region import *
from file_types import lang_type from file_types import lang_type
def safefix(fix_func):
""" Decorator for the fix functions of the Verifier class.
This function wraps the fix function and creates a backup file
just in case there is an error.
"""
def safefix_wrapper(*args, **kwargs):
# Check to be sure that this is decorating a function we expect:
# a class method with filename as the first argument (after self)
assert(os.path.exists(args[1]))
self = args[0]
assert(is_verifier(self.__class__))
filename = args[1]
# Now, Let's make a backup file.
from shutil import copyfile
backup_name = filename+'.bak'
copyfile(filename, backup_name)
# Try to apply the fix. If it fails, then we revert the file
# Either way, we need to clean up our backup file
try:
fix_func(*args, **kwargs)
except Exception as e:
# Restore the original file to the backup file
self.ui.write("Error! Restoring the original file.\n")
copyfile(backup_name, filename)
raise
finally:
# Clean up the backup file
os.remove(backup_name)
return safefix_wrapper
def _modified_regions(old, new): def _modified_regions(old, new):
try: try:
m = SequenceMatcher(a=old, b=new, autojunk=False) m = SequenceMatcher(a=old, b=new, autojunk=False)
@ -122,11 +156,11 @@ class Verifier(object):
return f return f
def skip(self, filename): def skip(self, filename):
# We never want to handle symlinks, so always skip them: If the location # We never want to handle symlinks, so always skip them: If the
# pointed to is a directory, skip it. If the location is a file inside # location pointed to is a directory, skip it. If the location is a
# the gem5 directory, it will be checked as a file, so symlink can be # file inside the gem5 directory, it will be checked as a file, so
# skipped. If the location is a file outside gem5, we don't want to # symlink can be skipped. If the location is a file outside gem5, we
# check it anyway. # don't want to check it anyway.
if os.path.islink(filename): if os.path.islink(filename):
return True return True
return lang_type(filename) not in self.languages return lang_type(filename) not in self.languages
@ -202,6 +236,7 @@ class LineVerifier(Verifier):
f.close() f.close()
return errors return errors
@safefix
def fix(self, filename, regions=all_regions): def fix(self, filename, regions=all_regions):
f = self.open(filename, 'r+') f = self.open(filename, 'r+')
@ -318,6 +353,7 @@ class SortedIncludes(Verifier):
return 0 return 0
@safefix
def fix(self, filename, regions=all_regions): def fix(self, filename, regions=all_regions):
f = self.open(filename, 'r+') f = self.open(filename, 'r+')