commit
e9cc242322
@ -0,0 +1,6 @@
|
||||
language: cpp
|
||||
script:
|
||||
- python travis/lint.py
|
||||
- python travis/pr-check-base.py
|
||||
notifications:
|
||||
email: false
|
@ -1 +1 @@
|
||||
Subproject commit a80abe848e4886a210e7a5123192e9221dc85810
|
||||
Subproject commit 5b167d2ba89b877d80e0609feae8771aeaef356d
|
@ -1 +1 @@
|
||||
Subproject commit 07750ad7f7ce7c2506e5198ffb80ca50a73e9c4e
|
||||
Subproject commit 85dcde97197bdde1c1e97ccb536f2cc4cab6818f
|
@ -1 +1 @@
|
||||
Subproject commit 8270ef2892b640a2e5753844a5e917ba96523fbb
|
||||
Subproject commit a8c5bd263306050ac1dc21140ce52719b0dd598b
|
@ -0,0 +1,122 @@
|
||||
import re, os, sys
|
||||
|
||||
valid_extensions = ['c', 'cpp', 'h', 'hpp', 'mm', 'lua', 'rb', 'proto',
|
||||
'init', 'init-example']
|
||||
path_blacklist = [
|
||||
'library/include/df/',
|
||||
'plugins/stonesense/allegro',
|
||||
'plugins/isoworld/allegro',
|
||||
'plugins/isoworld/agui',
|
||||
'depends/',
|
||||
'.git/',
|
||||
'build',
|
||||
]
|
||||
|
||||
def valid_file(filename):
|
||||
return len(filter(lambda ext: filename.endswith('.' + ext), valid_extensions)) and \
|
||||
not len(filter(lambda path: path.replace('\\', '/') in filename.replace('\\', '/'), path_blacklist))
|
||||
|
||||
success = True
|
||||
def error(msg):
|
||||
global success
|
||||
success = False
|
||||
sys.stderr.write(msg + '\n')
|
||||
|
||||
class LinterError(Exception): pass
|
||||
|
||||
class Linter(object):
|
||||
def check(self, lines):
|
||||
failures = []
|
||||
for i, line in enumerate(lines):
|
||||
if not self.check_line(line):
|
||||
failures.append(i + 1)
|
||||
if len(failures):
|
||||
raise LinterError('%s: %s' % (self.msg, self.display_lines(failures, len(lines))))
|
||||
|
||||
def fix(self, lines):
|
||||
for i in range(len(lines)):
|
||||
lines[i] = self.fix_line(lines[i])
|
||||
|
||||
def display_lines(self, lines, total):
|
||||
if len(lines) == total - 1:
|
||||
return 'entire file'
|
||||
if not len(lines):
|
||||
# should never happen
|
||||
return 'nowhere'
|
||||
if len(lines) == 1:
|
||||
return 'line %i' % lines[0]
|
||||
s = 'lines '
|
||||
range_start = range_end = lines[0]
|
||||
for i, line in enumerate(lines):
|
||||
if line > range_end + 1:
|
||||
if range_start == range_end:
|
||||
s += ('%i, ' % range_end)
|
||||
else:
|
||||
s += ('%i-%i, ' % (range_start, range_end))
|
||||
range_start = range_end = line
|
||||
if i == len(lines) - 1:
|
||||
s += ('%i' % line)
|
||||
else:
|
||||
range_end = line
|
||||
if i == len(lines) - 1:
|
||||
s += ('%i-%i, ' % (range_start, range_end))
|
||||
return s.rstrip(' ').rstrip(',')
|
||||
|
||||
class NewlineLinter(Linter):
|
||||
msg = 'Contains DOS-style newlines'
|
||||
def check_line(self, line):
|
||||
return '\r' not in line
|
||||
def fix_line(self, line):
|
||||
return line.replace('\r', '')
|
||||
|
||||
class TrailingWhitespaceLinter(Linter):
|
||||
msg = 'Contains trailing whitespace'
|
||||
def check_line(self, line):
|
||||
line = line.replace('\r', '')
|
||||
return not line.endswith(' ') and not line.endswith('\t')
|
||||
def fix_line(self, line):
|
||||
return line.rstrip('\t ')
|
||||
|
||||
class TabLinter(Linter):
|
||||
msg = 'Contains tabs'
|
||||
def check_line(self, line):
|
||||
return '\t' not in line
|
||||
def fix_line(self, line):
|
||||
return line.replace('\t', ' ')
|
||||
|
||||
linters = [NewlineLinter(), TrailingWhitespaceLinter(), TabLinter()]
|
||||
|
||||
def main():
|
||||
root_path = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else '.')
|
||||
fix = (len(sys.argv) > 2 and sys.argv[2] == '--fix')
|
||||
global path_blacklist
|
||||
path_blacklist = map(lambda s: os.path.join(root_path, s), path_blacklist)
|
||||
|
||||
for cur, dirnames, filenames in os.walk(root_path):
|
||||
for filename in filenames:
|
||||
full_path = os.path.join(cur, filename)
|
||||
rel_path = full_path.replace(root_path, '.')
|
||||
if not valid_file(full_path):
|
||||
continue
|
||||
lines = []
|
||||
with open(full_path, 'rb') as f:
|
||||
lines = f.read().split('\n')
|
||||
for linter in linters:
|
||||
try:
|
||||
linter.check(lines)
|
||||
except LinterError as e:
|
||||
error('%s: %s' % (rel_path, e))
|
||||
if fix:
|
||||
linter.fix(lines)
|
||||
contents = '\n'.join(lines)
|
||||
with open(full_path, 'wb') as f:
|
||||
f.write(contents)
|
||||
|
||||
if success:
|
||||
print('All linters completed successfully')
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -0,0 +1,29 @@
|
||||
import json, os, sys
|
||||
if sys.version.startswith('2'):
|
||||
from urllib2 import urlopen, HTTPError
|
||||
else:
|
||||
from urllib.request import urlopen
|
||||
from urllib.error import HTTPError
|
||||
try:
|
||||
pr_id = int(os.environ.get('TRAVIS_PULL_REQUEST', 'false'))
|
||||
except ValueError:
|
||||
print('Not a pull request')
|
||||
sys.exit(0)
|
||||
print('Pull request %i' % pr_id)
|
||||
res = {}
|
||||
try:
|
||||
res = json.loads(urlopen('https://api.github.com/repos/dfhack/dfhack/pulls/%i' % pr_id).read().decode('utf-8'))
|
||||
except ValueError:
|
||||
pass
|
||||
except HTTPError:
|
||||
print('Failed to retrieve PR information from API')
|
||||
sys.exit(2)
|
||||
if 'base' not in res or 'ref' not in res['base']:
|
||||
print('Invalid JSON returned from API')
|
||||
sys.exit(2)
|
||||
if res['base']['ref'] != 'develop':
|
||||
print('Not based on develop branch')
|
||||
sys.exit(1)
|
||||
else:
|
||||
print('Ok')
|
||||
sys.exit(0)
|
Loading…
Reference in New Issue