mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 01:07:15 +03:00
3d461ae600
Summary: Enhance check-ext script to be more strict: - Only one foreign extension is allowed: `remotenames` - Require explicit path for in-repo extensions to avoid wrong extensions being tested This would make the test more predicatable since system extensions will be less likely to be imported. Explicit path is better than setting `PYTHONPATH` since `hgext/name.py` could override `hgext3rd/name.py` regardless of `PYTHONPATH`. Test Plan: arc unit Reviewers: phillco, durham, ikostia, #mercurial, stash Reviewed By: stash Subscribers: medson, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D5271430 Signature: t1:5271430:1497861776:7dd35ec7c522cd9b26aa0871cb4306b4f1b8993a
91 lines
3.1 KiB
Python
Executable File
91 lines
3.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
from __future__ import absolute_import, print_function
|
|
|
|
from glob import glob
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
"""
|
|
Check if:
|
|
- a test is using foreign extensions without proper checks
|
|
- a test is using an extension in this repo without absolute path
|
|
"""
|
|
|
|
# whitelisted foreign extensions
|
|
foreignexts = set(['remotenames'])
|
|
foreignextre = re.compile(r'(%s)' % '|'.join(foreignexts))
|
|
|
|
# extensions in this repo
|
|
repoexts = set(os.path.basename(p).split('.')[0]
|
|
for p in glob('hgext3rd/*.py*') if '__' not in p)
|
|
repoexts.update(os.path.basename(os.path.dirname(p))
|
|
for p in glob('hgext3rd/*/__init__.py'))
|
|
repoexts.update(os.path.basename(os.path.dirname(p))
|
|
for p in glob('*/__init__.py'))
|
|
repoextre = re.compile(r'(%s)' % '|'.join(repoexts))
|
|
|
|
checkres = [
|
|
(re.compile(r'^\s*>\s*%s\s*=\s*$' % foreignextre.pattern),
|
|
'use "$ . $TESTDIR/require-ext.sh %(name)s" to skip the test'
|
|
' if %(name)s is not available'),
|
|
(re.compile(r'^\s*\$.*--config[ =\']*extensions.%s='
|
|
% foreignextre.pattern),
|
|
'use "$ . $TESTDIR/require-ext.sh %(name)s" to skip the test'
|
|
' if %(name)s is not available'),
|
|
(re.compile(r'^\s*>\s*%s\s*=\s*$' % repoextre.pattern),
|
|
'use full path like $TESTDIR/../hgext3rd/%(name)s.py for extension '
|
|
'in this repo'),
|
|
(re.compile(r'^\s*\$.*--config[ =\']*extensions.%s=[ \'"]'
|
|
% repoextre.pattern),
|
|
'use full path like $TESTDIR/../hgext3rd/%(name)s.py for extension '
|
|
'in this repo'),
|
|
]
|
|
|
|
requirere = re.compile(r'require-ext\.sh (.*)$')
|
|
|
|
def checkfile(path):
|
|
errors = []
|
|
with open(path) as f:
|
|
required = set()
|
|
for i, line in enumerate(f):
|
|
msg = None
|
|
m = requirere.search(line)
|
|
if m:
|
|
requiredexts = set(m.group(1).split())
|
|
unknownexts = requiredexts - foreignexts
|
|
for e in unknownexts:
|
|
if e in repoexts:
|
|
msg = 'do not require non-foreign extension %s'
|
|
else:
|
|
# change foreignexts if this error is a false postive
|
|
msg = 'do not require non-whitelisted extension %s'
|
|
errors.append((path, i + 1, line[:-1], msg % e))
|
|
required.update(requiredexts)
|
|
for regex, msg in checkres:
|
|
m = regex.search(line)
|
|
if not m:
|
|
continue
|
|
name = m.group(1)
|
|
if name in required:
|
|
continue
|
|
# line[:-1] is to remove the last "\n"
|
|
errors.append((path, i + 1, line[:-1], msg % {'name': name}))
|
|
# only one error per extension per file
|
|
required.add(name)
|
|
return errors
|
|
|
|
def checkfiles(paths):
|
|
errors = []
|
|
for path in sys.argv[1:]:
|
|
errors += checkfile(path)
|
|
return sorted(set(errors))
|
|
|
|
def printerrors(errors):
|
|
# same format with check-code.py
|
|
for fname, lineno, line, msg in errors:
|
|
print('%s:%d:\n > %s\n %s' % (fname, lineno, line, msg))
|
|
|
|
printerrors(checkfiles(sys.argv[1:]))
|