def get_config(repo_root): """ Gets the configuration file either from the repository, the user ``.gitlint`` directory or the default. """ config = None if repo_root: repo_config = os.path.join(repo_root, '.gitlint.yaml') if os.path.exists(repo_config): config = repo_config if not config: home_folder = os.path.expanduser('~') user_config = os.path.join(home_folder, '.git-lint', 'config.yaml') if os.path.exists(user_config): config = os.path.join(home_folder, '.git-lint', 'config.yaml') if not config: config = os.path.join( os.path.dirname(__file__), 'configs', 'config.yaml') with open(config) as f: # We have to read the content first as yaml hangs up when reading from # MockOpen content = f.read() # Yaml.load will return None when the input is empty. if not content: yaml_config = {} else: yaml_config = yaml.load(content) return linters.parse_yaml_config(yaml_config, repo_root)
def test_parse_yaml_config_requirements_not_in_path(self): yaml_config = { 'linter': { 'arguments': [], 'command': 'ls', 'requirements': [ 'some_unexistent_command_one', 'ls', 'some_unexistent_command_two', ], 'extensions': ['.foo'], 'filter': '.*', 'installation': 'Run apt-get install command_one command_two', } } config = linters.parse_yaml_config(yaml_config, '') self.assertEqual({ 'filename': { 'skipped': [ 'some_unexistent_command_one, ' + 'some_unexistent_command_two are not ' 'installed. Run apt-get install command_one ' + 'command_two' ] } }, config['.foo'][0]('filename', []))
def test_parse_yaml_config_requirements_not_in_path(self): yaml_config = { 'linter': { 'arguments': [], 'command': 'ls', 'requirements': [ 'some_unexistent_command_one', 'ls', 'some_unexistent_command_two', ], 'extensions': ['.foo'], 'filter': '.*', 'installation': 'Run apt-get install command_one command_two', } } config = linters.parse_yaml_config(yaml_config, '') self.assertEqual( { 'filename': { 'skipped': [ 'some_unexistent_command_one, ' + 'some_unexistent_command_two are not ' 'installed. Run apt-get install command_one ' + 'command_two' ] } }, config['extensions']['.foo'][0]('filename', []))
def test_parse_yaml_config_with_variables(self): yaml_config_with_vars = { 'linter': { 'arguments': ['--config', '{DEFAULT_CONFIGS}/foo.config'], 'command': '{REPO_HOME}/bin/linter', 'requirements': [ '{REPO_HOME}/bin/dep1', ], 'extensions': ['.foo'], 'filter': '.*', 'installation': 'install', } } variables = { 'DEFAULT_CONFIGS': os.path.join(os.path.dirname(gitlint.__file__), 'configs'), 'REPO_HOME': '/usr/home/repo', } yaml_config_no_vars = { 'linter': { 'arguments': [ '--config', '{DEFAULT_CONFIGS}/foo.config'.format(**variables), ], 'command': '{REPO_HOME}/bin/linter'.format(**variables), 'requirements': [ '{REPO_HOME}/bin/dep1'.format(**variables), ], 'extensions': ['.foo'], 'filter': '.*', 'installation': 'install', } } with mock.patch('gitlint.utils.which', return_value=['lint']): config_with_vars = linters.parse_yaml_config( yaml_config_with_vars, variables['REPO_HOME']) config_no_vars = linters.parse_yaml_config(yaml_config_no_vars, variables['REPO_HOME']) self.assertEqual(config_with_vars, config_no_vars)
def get_config(repo_root): """Gets the configuration file either from the repository or the default.""" config = os.path.join(os.path.dirname(__file__), 'configs', 'config.yaml') if repo_root: repo_config = os.path.join(repo_root, '.gitlint.yaml') if os.path.exists(repo_config): config = repo_config with open(config) as f: # We have to read the content first as yaml hangs up when reading from # MockOpen content = f.read() # Yaml.load will return None when the input is empty. if not content: yaml_config = {} else: yaml_config = yaml.load(content) return linters.parse_yaml_config(yaml_config, repo_root)
def get_config(repo_root): """Gets the configuration file either from the repository or the default.""" config = os.path.join(os.path.dirname(__file__), 'configs', 'config.yaml') if repo_root: repo_config = os.path.join(repo_root, '.gitlint.yaml') if os.path.exists(repo_config): config = repo_config with open(config) as f: # We have to read the content first as yaml hangs up when reading from # MockOpen content = f.read() # Yaml.load will return None when the input is empty. if not content: yaml_config = {} else: yaml_config = yaml.load(content, Loader=yaml.FullLoader) return linters.parse_yaml_config(yaml_config, repo_root)
def test_parse_yaml_config_command_not_in_path(self): yaml_config = { 'linter': { 'arguments': [], 'command': 'some_unexistent_program_name', 'extensions': ['.foo'], 'filter': '.*', 'installation': ('Go to some_unexistent_program_name.com to ' + 'install it.'), } } config = linters.parse_yaml_config(yaml_config, '') self.assertEqual( { 'filename': { 'skipped': ['some_unexistent_program_name is not ' + 'installed. Go to some_unexistent_program_' + 'name.com to install it.'] } }, config['.foo'][0]('filename', []))
def test_parse_yaml_config_command_not_in_path(self): yaml_config = { 'linter': { 'arguments': [], 'command': 'some_unexistent_program_name', 'extensions': ['.foo'], 'filter': '.*', 'installation': ('Go to some_unexistent_program_name.com to ' + 'install it.'), } } config = linters.parse_yaml_config(yaml_config, '') self.assertEqual( { 'filename': { 'skipped': [ 'some_unexistent_program_name is not ' + 'installed. Go to some_unexistent_program_' + 'name.com to install it.' ] } }, config['extensions']['.foo'][0]('filename', []))
def main(argv, stdout=sys.stdout, stderr=sys.stderr): """Main gitlint routine. To be called from scripts.""" # Wrap sys stdout for python 2, so print can understand unicode. linesep = os.linesep if sys.version_info[0] < 3: if stdout == sys.stdout: stdout = codecs.getwriter("utf-8")(stdout) if stderr == sys.stderr: stderr = codecs.getwriter("utf-8")(stderr) linesep = unicode(os.linesep) # pylint: disable=undefined-variable arguments = docopt.docopt( __doc__, argv=argv[1:], version='git-lint v%s' % __VERSION__) json_output = arguments['--json'] vcs, repository_root = get_vcs_root() if vcs is None: stderr.write('fatal: Not a git repository' + linesep) return 128 commit = None mode = arguments['--mode'] if not mode or mode == 'merge-base': commit = vcs.merge_base_commit() elif mode == 'last-commit': commit = vcs.last_commit() elif mode != 'local': raise ValueError( 'Invalid mode. Valid modes are: merge-base, local, or last-commit.') config = get_config(repository_root) if arguments['FILENAME']: invalid_filenames = find_invalid_filenames(arguments['FILENAME'], repository_root) if invalid_filenames: invalid_filenames.append(('', '')) stderr.write( linesep.join(invalid[1] for invalid in invalid_filenames)) return 2 changed_files = vcs.modified_files( repository_root, tracked_only=arguments['--tracked'], commit=commit) modified_files = {} for filename in arguments['FILENAME']: normalized_filename = os.path.abspath(filename) modified_files[normalized_filename] = changed_files.get( normalized_filename) else: modified_files = vcs.modified_files( repository_root, tracked_only=arguments['--tracked'], commit=commit) if config.get('ignore-regex'): regex_list = [ '(%s)' % r for r in config.get('ignore-regex').split() ] regex = re.compile('|'.join(regex_list)) modified_files = { k: v for k, v in modified_files.items() if not regex.match(k) } linter_not_found = False files_with_problems = 0 linter_config = linters.parse_yaml_config( config.get('linters', {}), repository_root, not arguments['--no-cache']) fixer_config = fixers.parse_yaml_config(config.get('fixers', {}), repository_root, arguments['--fix-linexp']) json_result = {} with futures.ThreadPoolExecutor(max_workers=multiprocessing.cpu_count())\ as executor: processfile = functools.partial(process_file, vcs, commit, arguments['--force'], linter_config, fixer_config, arguments['--fix'], arguments['--fix-all']) for filename, result in executor.map( processfile, [(filename, modified_files[filename]) for filename in sorted(modified_files.keys())]): rel_filename = os.path.relpath(filename) if not json_output: stdout.write('Processing file: %s%s' % (termcolor.colored( rel_filename, attrs=('bold',)), linesep)) output_lines = [] if result.get('error'): output_lines.extend('%s: %s' % (ERROR, reason) for reason in result.get('error')) linter_not_found = True if result.get('skipped'): output_lines.extend('%s: %s' % (SKIPPED, reason) for reason in result.get('skipped')) if not result.get('comments', []): if not output_lines: output_lines.append(OK) else: files_with_problems += 1 for data in result['comments']: formatted_message = format_comment(data) output_lines.append(formatted_message) data['formatted_message'] = formatted_message if json_output: json_result[filename] = result else: output = linesep.join(output_lines) stdout.write(output) stdout.write(linesep + linesep) if json_output: # Hack to convert to unicode, Python3 returns unicode, wheres Python2 # returns str. stdout.write( json.dumps(json_result, ensure_ascii=False).encode('utf-8').decode('utf-8')) if files_with_problems > 0: return 1 if linter_not_found: return 4 return 0