Fixing merge.
This commit is contained in:
commit
ec439aab81
|
@ -2,7 +2,7 @@
|
||||||
comment = Check to Ensure no debugger commands get checked in
|
comment = Check to Ensure no debugger commands get checked in
|
||||||
output = Checking for debugger commands in Javascript...
|
output = Checking for debugger commands in Javascript...
|
||||||
command = grep -n debugger
|
command = grep -n debugger
|
||||||
files = .js
|
match = .js
|
||||||
print = True
|
print = True
|
||||||
condition = output
|
condition = output
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import ConfigParser
|
from __future__ import print_function
|
||||||
|
from functools import reduce
|
||||||
import getopt
|
import getopt
|
||||||
import gettext
|
import gettext
|
||||||
import operator
|
import operator
|
||||||
|
@ -15,6 +16,9 @@ _ = gettext.gettext
|
||||||
VERSION = '0.0.4'
|
VERSION = '0.0.4'
|
||||||
NAME = 'git-lint'
|
NAME = 'git-lint'
|
||||||
|
|
||||||
|
def tap(a):
|
||||||
|
print("TAP:", a)
|
||||||
|
return a
|
||||||
|
|
||||||
# ___ _ _ _
|
# ___ _ _ _
|
||||||
# / __|___ _ __ _ __ __ _ _ _ __| | | | (_)_ _ ___
|
# / __|___ _ __ _ __ __ _ _ _ __| | | | (_)_ _ ___
|
||||||
|
@ -132,7 +136,8 @@ def get_git_response_raw(cmd):
|
||||||
fullcmd = (['git'] + cmd)
|
fullcmd = (['git'] + cmd)
|
||||||
process = subprocess.Popen(fullcmd,
|
process = subprocess.Popen(fullcmd,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
(out, err) = process.communicate()
|
(out, err) = process.communicate()
|
||||||
return (out, err, process.returncode)
|
return (out, err, process.returncode)
|
||||||
|
|
||||||
|
@ -151,14 +156,16 @@ def run_git_command(cmd):
|
||||||
fullcmd = (['git'] + cmd)
|
fullcmd = (['git'] + cmd)
|
||||||
return subprocess.call(fullcmd,
|
return subprocess.call(fullcmd,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
|
|
||||||
|
|
||||||
def get_shell_response(fullcmd):
|
def get_shell_response(fullcmd):
|
||||||
process = subprocess.Popen(fullcmd,
|
process = subprocess.Popen(fullcmd,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
shell=True)
|
shell=True,
|
||||||
|
universal_newlines=True)
|
||||||
(out, err) = process.communicate()
|
(out, err) = process.communicate()
|
||||||
return (out, err, process.returncode)
|
return (out, err, process.returncode)
|
||||||
|
|
||||||
|
@ -191,15 +198,15 @@ def base_file_cleaner(files):
|
||||||
|
|
||||||
|
|
||||||
def make_match_filter_matcher(extensions):
|
def make_match_filter_matcher(extensions):
|
||||||
trimmed = reduce(operator.add, [s.strip for s in
|
trimmed = [s.strip() for s in reduce(operator.add,
|
||||||
[ex.split(',') for ex in extension-s]])
|
[ex.split(',') for ex in extensions], [])]
|
||||||
cleaned = [re.sub(r'^\.', s.strip(), '') for s in trimmed]
|
cleaned = [re.sub(r'^\.', '', s) for s in trimmed]
|
||||||
return re.compile(r'\.' + '|'.join(cleaned) + r'$')
|
return re.compile(r'\.' + '|'.join(cleaned) + r'$')
|
||||||
|
|
||||||
|
|
||||||
def make_match_filter(config):
|
def make_match_filter(config):
|
||||||
matcher = make_match_filter_matcher([v.get('match', '')
|
matcher = make_match_filter_matcher([v.get('match', '')
|
||||||
for v in config.itervalues()])
|
for v in config.values()])
|
||||||
|
|
||||||
def match_filter(path):
|
def match_filter(path):
|
||||||
return matcher.search(path)
|
return matcher.search(path)
|
||||||
|
@ -279,7 +286,7 @@ def get_filelist(cmdline, extras):
|
||||||
def check_for_conflicts(filesets):
|
def check_for_conflicts(filesets):
|
||||||
""" Scan list of porcelain files for merge conflic state. """
|
""" Scan list of porcelain files for merge conflic state. """
|
||||||
MERGE_CONFLICT_PAIRS = set(['DD', 'DU', 'AU', 'AA', 'UD', 'UA', 'UU'])
|
MERGE_CONFLICT_PAIRS = set(['DD', 'DU', 'AU', 'AA', 'UD', 'UA', 'UU'])
|
||||||
status_pairs = set(['' + f[0] + f[1] for f in files])
|
status_pairs = set(['' + f[0] + f[1] for f in filesets])
|
||||||
if len(status_pairs & MERGE_CONFLICT_PAIRS):
|
if len(status_pairs & MERGE_CONFLICT_PAIRS):
|
||||||
sys.exit(
|
sys.exit(
|
||||||
_('Current repository contains merge conflicts. Linters will not be run.'))
|
_('Current repository contains merge conflicts. Linters will not be run.'))
|
||||||
|
@ -363,7 +370,7 @@ def get_filelist(cmdline, extras):
|
||||||
if 'staging' in keys:
|
if 'staging' in keys:
|
||||||
file_list_generator = staging_list
|
file_list_generator = staging_list
|
||||||
|
|
||||||
return working_directory_trans(remove_submodules(file_list_generator))
|
return working_directory_trans(remove_submodules(file_list_generator()))
|
||||||
|
|
||||||
|
|
||||||
# ___ _ _
|
# ___ _ _
|
||||||
|
@ -372,7 +379,7 @@ def get_filelist(cmdline, extras):
|
||||||
# |___/\__\__,_\__, |_|_||_\__, | \_/\_/|_| \__,_| .__/ .__/\___|_|
|
# |___/\__\__,_\__, |_|_||_\__, | \_/\_/|_| \__,_| .__/ .__/\___|_|
|
||||||
# |___/ |___/ |_| |_|
|
# |___/ |___/ |_| |_|
|
||||||
|
|
||||||
def pick_runner(cmdline):
|
def pick_stash_runner(cmdline):
|
||||||
"""Choose a runner.
|
"""Choose a runner.
|
||||||
|
|
||||||
This is the operation that will run the linters. It exists to
|
This is the operation that will run the linters. It exists to
|
||||||
|
@ -410,7 +417,7 @@ def pick_runner(cmdline):
|
||||||
# |_|_\\_,_|_||_| |_|_|_||_\__| | .__/\__,_/__/__/
|
# |_|_\\_,_|_||_| |_|_|_||_\__| | .__/\__,_/__/__/
|
||||||
# |_|
|
# |_|
|
||||||
|
|
||||||
def run_external_linter(filename, linter):
|
def run_external_linter(filename, linter, linter_name):
|
||||||
|
|
||||||
"""Run one linter against one file.
|
"""Run one linter against one file.
|
||||||
|
|
||||||
|
@ -420,17 +427,20 @@ def run_external_linter(filename, linter):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def encode_shell_messages(prefix, messages):
|
def encode_shell_messages(prefix, messages):
|
||||||
return ['{}{}'.format(prefix, line.decode('utf-8'))
|
return ['{}{}'.format(prefix, line)
|
||||||
for line in messages.splitlines()]
|
for line in messages.splitlines()]
|
||||||
|
|
||||||
|
|
||||||
cmd = linter['command'] + '"' + filename + '"'
|
cmd = linter['command'] + ' "' + filename + '"'
|
||||||
(out, err, returncode) = get_shell_response(cmd)
|
(out, err, returncode) = get_shell_response(cmd)
|
||||||
if ((out and (linter.get('condition', 'error') == 'output')) or err or (not (returncode == 0L))):
|
failed = ((out and (linter.get('condition', 'error') == 'output')) or err or (not (returncode == 0)))
|
||||||
prefix = linter.get('print', False) and '\t{}:'.format(filename) or '\t'
|
if not failed:
|
||||||
output = encode_shell_messages(prefix, out) + (err and encode_shell_messages(prefix, err) or [])
|
return (filename, linter_name, 0, [])
|
||||||
return ((returncode or 1), output)
|
|
||||||
return (0, [])
|
prefix = linter.get('print', False) and '\t{}:'.format(filename) or '\t'
|
||||||
|
output = encode_shell_messages(prefix, out) + (err and encode_shell_messages(prefix, err) or [])
|
||||||
|
return (filename, linter_name, (returncode or 1), output)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def run_one_linter(linter, filenames):
|
def run_one_linter(linter, filenames):
|
||||||
|
@ -442,11 +452,10 @@ def run_one_linter(linter, filenames):
|
||||||
result as a list of successes and failures. Failures have a
|
result as a list of successes and failures. Failures have a
|
||||||
return code and the output of the lint process.
|
return code and the output of the lint process.
|
||||||
"""
|
"""
|
||||||
|
linter_name, config = list(linter.items()).pop()
|
||||||
match_filter = make_match_filter(linter)
|
match_filter = make_match_filter(linter)
|
||||||
config = linter.values()[0]
|
|
||||||
files = set([file for file in filenames if match_filter(file)])
|
files = set([file for file in filenames if match_filter(file)])
|
||||||
return [run_external_linter(file, config) for file in files]
|
return [run_external_linter(file, config, linter_name) for file in files]
|
||||||
|
|
||||||
|
|
||||||
def build_lint_runner(linters, filenames):
|
def build_lint_runner(linters, filenames):
|
||||||
|
@ -458,7 +467,8 @@ def build_lint_runner(linters, filenames):
|
||||||
"""
|
"""
|
||||||
def lint_runner():
|
def lint_runner():
|
||||||
keys = sorted(linters.keys())
|
keys = sorted(linters.keys())
|
||||||
return [run_one_linter({key: linters[key]}, filenames) for key in keys]
|
return reduce(operator.add,
|
||||||
|
[run_one_linter({key: linters[key]}, filenames) for key in keys], [])
|
||||||
return lint_runner
|
return lint_runner
|
||||||
|
|
||||||
|
|
||||||
|
@ -477,21 +487,21 @@ def run_gitlint(cmdline, config, extras):
|
||||||
|
|
||||||
""" Runs the requested linters """
|
""" Runs the requested linters """
|
||||||
all_files = get_filelist(cmdline, extras)
|
all_files = get_filelist(cmdline, extras)
|
||||||
runner = pick_runner(cmdline)
|
stash_runner = pick_runner(cmdline)
|
||||||
|
is_lintable = make_match_filter(config)
|
||||||
lintable = make_match_filter(config)
|
|
||||||
lintable_files = set([file for file in all_files if lintable(file)])
|
lintable_files = set([file for file in all_files if lintable(file)])
|
||||||
unlintables = (set(all_files) - lintable_files)
|
unlintable_files = (set(all_files) - lintable_files)
|
||||||
|
|
||||||
working_linters = get_working_linters(config)
|
working_linters = get_working_linters(config)
|
||||||
broken_linters = (set(config) - set(working_linters))
|
broken_linters = (set(config) - set(working_linters))
|
||||||
cant_lint = make_match_filter(subset_config(config, broken_linters))
|
cant_lint_filter = make_match_filter(build_config_subset(broken_linters))
|
||||||
cant_lintable = set([file for file in lintable_files if cant_lint(file)])
|
cant_lint_files = set([file for file in lintable_files if cant_lint_filter(file)])
|
||||||
lint_runner = build_lint_runner(build_config_subset(working_linters), lintable_files)
|
lint_runner = build_lint_runner(build_config_subset(working_linters), lintable_files)
|
||||||
|
|
||||||
results = runner(lint_runner)
|
results = stash_runner(lint_runner)
|
||||||
|
|
||||||
print(list(results))
|
print(list(results))
|
||||||
return results
|
return max(*[i[2] for i in results if len(i)])
|
||||||
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import gettext
|
import gettext
|
||||||
import ConfigParser
|
try:
|
||||||
|
import configparser
|
||||||
|
except ImportError as e:
|
||||||
|
import ConfigParser as configparser
|
||||||
|
|
||||||
|
|
||||||
_ = gettext.gettext
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ def get_config(options, base):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = find_config_file(options, base)
|
path = find_config_file(options, base)
|
||||||
configloader = ConfigParser.SafeConfigParser()
|
configloader = configparser.SafeConfigParser()
|
||||||
configloader.read(path)
|
configloader.read(path)
|
||||||
configloader.set('DEFAULT', 'repodir', base)
|
configloader.set('DEFAULT', 'repodir', base)
|
||||||
return {section: {k: v for (k, v) in configloader.items(section)}
|
return {section: {k: v for (k, v) in configloader.items(section)}
|
||||||
|
|
|
@ -1,119 +1,75 @@
|
||||||
from hy.core.language import filter, map, name, reduce
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
|
||||||
import getopt
|
import getopt
|
||||||
import gettext
|
import gettext
|
||||||
|
|
||||||
_ = gettext.gettext
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
# -> scriptNameString
|
def make_rational_options(optlist, args):
|
||||||
|
|
||||||
def get_script_name():
|
# OptionTupleList -> (getOptOptions -> dictionaryOfOptions)
|
||||||
""" Returns the best possible name for the script. """
|
def make_options_rationalizer(optlist):
|
||||||
if getattr(sys, 'frozen', False):
|
"""Takes a list of option tuples, and returns a function that takes
|
||||||
(path, name) = os.path.split(sys.executable)
|
the output of getopt and reduces it to the longopt key and
|
||||||
return name
|
associated values as a dictionary.
|
||||||
|
"""
|
||||||
|
|
||||||
prefix = sys.exec_prefix.upper()
|
def make_opt_assoc(prefix, pos):
|
||||||
names = [name for name in [frame[1] for frame in inspect.stack()]
|
def associater(acc, it):
|
||||||
if name.startswith('<') or names.upper().startswith(prefix)]
|
acc[(prefix + it[pos])] = it[1]
|
||||||
return names.pop()
|
return acc
|
||||||
|
return associater
|
||||||
|
|
||||||
|
short_opt_assoc = make_opt_assoc('-', 0)
|
||||||
|
long_opt_assoc = make_opt_assoc('--', 1)
|
||||||
|
|
||||||
# OptionTupleList -> (getOptOptions -> dictionaryOfOptions)
|
def make_full_set(acc, i):
|
||||||
|
return long_opt_assoc(short_opt_assoc(acc, i), i)
|
||||||
|
|
||||||
def make_options_rationalizer(optlist):
|
fullset = reduce(make_full_set, optlist, {})
|
||||||
"""Takes a list of option tuples, and returns a function that takes
|
|
||||||
the output of getopt and reduces it to the longopt key and
|
|
||||||
associated values as a dictionary.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def make_opt_assoc(prefix, pos):
|
def rationalizer(acc, it):
|
||||||
def associater(acc, it):
|
acc[fullset[it[0]]] = it[1]
|
||||||
acc[(prefix + it[pos])] = it[1]
|
|
||||||
return acc
|
return acc
|
||||||
return associater
|
|
||||||
|
|
||||||
short_opt_assoc = make_opt_assoc('-', 0)
|
return rationalizer
|
||||||
long_opt_assoc = make_opt_assoc('--', 1)
|
|
||||||
|
|
||||||
def make_full_set(acc, i):
|
|
||||||
return long_opt_assoc(short_opt_assoc(acc, i), i)
|
|
||||||
|
|
||||||
fullset = reduce(make_full_set, optlist, {})
|
|
||||||
|
|
||||||
def rationalizer(acc, it):
|
|
||||||
acc[fullset[it[0]]] = it[1]
|
|
||||||
return acc
|
|
||||||
|
|
||||||
return rationalizer
|
|
||||||
|
|
||||||
|
|
||||||
# (OptionTupleList, dictionaryOfOptions) -> (dictionaryOfOptions, excludedOptions)
|
# (OptionTupleList, dictionaryOfOptions) -> (dictionaryOfOptions, excludedOptions)
|
||||||
|
def remove_conflicted_options(optlist, request):
|
||||||
|
"""Takes our list of option tuples, and a cleaned copy of what was
|
||||||
|
requested from getopt, and returns a copy of the request
|
||||||
|
without any options that are marked as superseded, along with
|
||||||
|
the list of superseded options
|
||||||
|
"""
|
||||||
|
def get_excluded_keys(memo, opt):
|
||||||
|
return memo + (len(opt) > 4 and opt[4] or [])
|
||||||
|
|
||||||
def remove_conflicted_options(optlist, request):
|
keys = request.keys()
|
||||||
"""Takes our list of option tuples, and a cleaned copy of what was
|
marked = [option for option in optlist if option[1] in keys]
|
||||||
requested from getopt, and returns a copy of the request
|
exclude = reduce(get_excluded_keys, marked, [])
|
||||||
without any options that are marked as superseded, along with
|
excluded = [key for key in keys if key in exclude]
|
||||||
the list of superseded options
|
cleaned = {key: request[key] for key in keys
|
||||||
"""
|
if key not in excluded}
|
||||||
def get_excluded_keys(memo, opt):
|
return (cleaned, excluded)
|
||||||
return memo + (len(opt) > 4 and opt[4] or [])
|
|
||||||
|
|
||||||
keys = request.keys()
|
def shortoptstogo(i):
|
||||||
marked = [option for option in optlist if option[1] in keys]
|
return i[0] + (i[2] and ':' or '')
|
||||||
exclude = reduce(get_excluded_keys, marked, [])
|
|
||||||
excluded = [key for key in keys if key in exclude]
|
|
||||||
cleaned = {key: request[key] for key in keys
|
|
||||||
if key not in excluded}
|
|
||||||
return (cleaned, excluded)
|
|
||||||
|
|
||||||
|
def longoptstogo(i):
|
||||||
|
return i[1] + (i[2] and '=' or '')
|
||||||
|
|
||||||
class RationalOptions:
|
optstringsshort = ''.join([shortoptstogo(opt) for opt in optlist])
|
||||||
|
optstringslong = [longoptstogo(opt) for opt in optlist]
|
||||||
|
(options, filenames) = getopt.getopt(args[1:], optstringsshort,
|
||||||
|
optstringslong)
|
||||||
|
|
||||||
def __init__(self, optlist, args, name='', copyright='', version='0.0.1'):
|
# Turns what getopt returns into something more human-readable
|
||||||
def shortoptstogo(i):
|
rationalize_options = make_options_rationalizer(optlist)
|
||||||
return i[0] + (i[2] and ':' or '')
|
|
||||||
|
|
||||||
def longoptstogo(i):
|
# Remove any options that
|
||||||
return i[1] + (i[2] and '=' or '')
|
(retoptions, excluded) = remove_conflicted_options(
|
||||||
|
optlist, reduce(rationalize_options, options, {}))
|
||||||
|
|
||||||
optstringsshort = ''.join([shortoptstogo(opt) for opt in optlist])
|
return (retoptions, filenames, excluded)
|
||||||
optstringslong = [longoptstogo(opt) for opt in optlist]
|
|
||||||
(options, arg) = getopt.getopt(args[1:], optstringsshort,
|
|
||||||
optstringslong)
|
|
||||||
|
|
||||||
# Turns what getopt returns into something more human-readable
|
|
||||||
rationalize_options = make_options_rationalizer(optlist)
|
|
||||||
|
|
||||||
# Remove any options that
|
|
||||||
(newoptions, excluded) = remove_conflicted_options(
|
|
||||||
optlist, reduce(rationalize_options, options, {}))
|
|
||||||
|
|
||||||
self.optlist = optlist
|
|
||||||
self.options = newoptions
|
|
||||||
self.excluded = excluded
|
|
||||||
self.filenames = arg
|
|
||||||
self.name = (name if name else get_script_name())
|
|
||||||
self.version = version
|
|
||||||
self.copyright = copyright
|
|
||||||
|
|
||||||
def get_options(self):
|
|
||||||
return self.options
|
|
||||||
|
|
||||||
def get_keys(self):
|
|
||||||
return set(self.options.keys())
|
|
||||||
|
|
||||||
def print_help(self):
|
|
||||||
print(_('Usage: {} [options] [filenames]').format(self.name))
|
|
||||||
for item in self.optlist:
|
|
||||||
print(' -{:<1} --{:<12} {}'.format(item[0], item[1], item[3]))
|
|
||||||
return sys.exit()
|
|
||||||
|
|
||||||
def print_version(self):
|
|
||||||
print('{}'.format(self.name, self.version))
|
|
||||||
if self.copyright:
|
|
||||||
print(self.copyright)
|
|
||||||
return sys.exit()
|
|
||||||
|
|
Loading…
Reference in New Issue