#! /usr/bin/env python
-# Copyright (c) 2007 The Regents of The University of Michigan
+# Copyright (c) 2006 The Regents of The University of Michigan
+# Copyright (c) 2007 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
's' : "asm",
'S' : "asm",
'isa' : "isa" }
-whitespace_types = ('C', 'C++', 'swig', 'python', 'asm', 'isa')
-format_types = ( 'C', 'C++' )
-
def file_type(filename):
extension = filename.split('.')
extension = len(extension) > 1 and extension[-1]
return lang_types.get(extension, None)
+whitespace_types = ('C', 'C++', 'swig', 'python', 'asm', 'isa')
+def whitespace_file(filename):
+ if file_type(filename) in whitespace_types:
+ return True
+
+ if filename.startswith("SCons"):
+ return True
+
+ return False
+
+format_types = ( 'C', 'C++' )
+def format_file(filename):
+ if file_type(filename) in format_types:
+ return True
+
+ return True
+
def checkwhite_line(line):
match = lead.search(line)
if match and match.group(1).find('\t') != -1:
return True
def checkwhite(filename):
- if file_type(filename) not in whitespace_types:
+ if not whitespace_file(filename):
return
try:
return line.rstrip() + '\n'
def fixwhite(filename, tabsize, fixonly=None):
- if file_type(filename) not in whitespace_types:
+ if not whitespace_file(filename):
return
try:
self.trailwhite or self.badcontrol or self.cret
def validate(filename, stats, verbose, exit_code):
- if file_type(filename) not in format_types:
+ if not format_file(filename):
return
def msg(lineno, line, message):
msg(i, line, 'improper spacing after %s' % match.group(1))
bad()
-def check_whitespace(ui, repo, hooktype, node, parent1, parent2):
- from mercurial import bdiff, mdiff, util
- if hooktype != 'pretxncommit':
- raise AttributeError, \
- "This hook is only meant for pretxncommit, not %s" % hooktype
+def modified_lines(old_data, new_data, max_lines):
+ from itertools import count
+ from mercurial import bdiff, mdiff
+
+ modified = set()
+ counter = count()
+ for pbeg, pend, fbeg, fend in bdiff.blocks(old_data, new_data):
+ for i in counter:
+ if i < fbeg:
+ modified.add(i)
+ elif i + 1 >= fend:
+ break
+ elif i > max_lines:
+ break
+ return modified
+
+def do_check_whitespace(ui, repo, *files, **args):
+ """check files for proper m5 style guidelines"""
+ from mercurial import mdiff, util
+
+ if files:
+ files = frozenset(files)
+
+ def skip(name):
+ return files and name in files
- tabsize = 8
- verbose = ui.configbool('style', 'verbose', False)
def prompt(name, fixonly=None):
- result = ui.prompt("(a)bort, (i)gnore, or (f)ix?", "^[aif]$", "a")
+ if args.get('auto', False):
+ result = 'f'
+ else:
+ while True:
+ result = ui.prompt("(a)bort, (i)gnore, or (f)ix?", default='a')
+ if result in 'aif':
+ break
+
if result == 'a':
return True
- elif result == 'i':
- pass
elif result == 'f':
- fixwhite(name, tabsize, fixonly)
- else:
- raise RepoError, "Invalid response: '%s'" % result
+ fixwhite(repo.wjoin(name), args['tabsize'], fixonly)
return False
modified, added, removed, deleted, unknown, ignore, clean = repo.status()
for fname in added:
+ if skip(fname):
+ continue
+
ok = True
- for line,num in checkwhite(fname):
+ for line,num in checkwhite(repo.wjoin(fname)):
ui.write("invalid whitespace in %s:%d\n" % (fname, num))
- if verbose:
+ if ui.verbose:
ui.write(">>%s<<\n" % line[-1])
ok = False
if prompt(fname):
return True
- wctx = repo.workingctx()
+ try:
+ wctx = repo.workingctx()
+ except:
+ from mercurial import context
+ wctx = context.workingctx(repo)
+
for fname in modified:
+ if skip(fname):
+ continue
+
+ if not whitespace_file(fname):
+ continue
+
fctx = wctx.filectx(fname)
pctx = fctx.parents()
- assert len(pctx) == 1
- pdata = pctx[0].data()
- fdata = fctx.data()
+ file_data = fctx.data()
+ lines = mdiff.splitnewlines(file_data)
+ if len(pctx) in (1, 2):
+ mod_lines = modified_lines(pctx[0].data(), file_data, len(lines))
+ if len(pctx) == 2:
+ m2 = modified_lines(pctx[1].data(), file_data, len(lines))
+ # only the lines that are new in both
+ mod_lines = mod_lines & m2
+ else:
+ mod_lines = xrange(0, len(lines))
fixonly = set()
- lines = enumerate(mdiff.splitnewlines(fdata))
- for pbeg, pend, fbeg, fend in bdiff.blocks(pdata, fdata):
- for i, line in lines:
- if i < fbeg:
- if checkwhite_line(line):
- continue
-
- ui.write("invalid whitespace: %s:%d\n" % (fname, i+1))
- if verbose:
- ui.write(">>%s<<\n" % line[:-1])
- fixonly.add(i)
- elif i + 1 >= fend:
- break
+ for i,line in enumerate(lines):
+ if i not in mod_lines:
+ continue
+
+ if checkwhite_line(line):
+ continue
+
+ ui.write("invalid whitespace: %s:%d\n" % (fname, i+1))
+ if ui.verbose:
+ ui.write(">>%s<<\n" % line[:-1])
+ fixonly.add(i)
if fixonly:
if prompt(fname, fixonly):
return True
-def check_format(ui, repo, hooktype, node, parent1, parent2):
+def check_whitespace(ui, repo, hooktype, node, parent1, parent2, **kwargs):
+ if hooktype != 'pretxncommit':
+ raise AttributeError, \
+ "This hook is only meant for pretxncommit, not %s" % hooktype
+
+ args = { 'tabsize' : 8 }
+ return do_check_whitespace(ui, repo, **args)
+
+def check_format(ui, repo, hooktype, node, parent1, parent2, **kwargs):
if hooktype != 'pretxncommit':
raise AttributeError, \
"This hook is only meant for pretxncommit, not %s" % hooktype
elif result.startswith('a'):
return True
else:
- raise RepoError, "Invalid response: '%s'" % result
+ raise util.Abort(_("Invalid response: '%s'") % result)
return False
+try:
+ from mercurial.i18n import _
+except ImportError:
+ def _(arg):
+ return arg
+
+cmdtable = {
+ '^m5style' :
+ ( do_check_whitespace,
+ [ ('a', 'auto', False, _("automatically fix whitespace")),
+ ('t', 'tabsize', 8, _("Number of spaces TAB indents")) ],
+ _('hg m5check [-t <tabsize>] [FILE]...')),
+}
if __name__ == '__main__':
import getopt
fixwhite(filename, tabsize)
elif command == 'chkwhite':
for filename in args:
- line = checkwhite(filename)
- if line:
- print 'invalid whitespace at %s:%d' % (filename, line)
+ for line,num in checkwhite(filename):
+ print 'invalid whitespace: %s:%d' % (filename, num)
+ if verbose:
+ print '>>%s<<' % line[:-1]
elif command == 'chkformat':
stats = ValidationStats()
- for filename in files:
+ for filename in args:
validate(filename, stats=stats, verbose=verbose, exit_code=code)
if verbose > 0: