Ejemplo n.º 1
0
    def set(self, value):
        if isinstance(value, list):
            the_list = value
        else:
            the_list = ustr(value).split(",")

        self.value = [ustr(item.strip()) for item in the_list if item.strip() != ""]
Ejemplo n.º 2
0
def cli(ctx, target, config, c, commits, extra_path, ignore, verbose, silent,
        debug):
    """ Git lint tool, checks your git commit messages for styling issues """

    try:
        if debug:
            logging.getLogger("gitlint").setLevel(logging.DEBUG)

        log_system_info()

        # Get the lint config from the commandline parameters and
        # store it in the context (click allows storing an arbitrary object in ctx.obj).
        config, config_builder = build_config(ctx, target, config, c,
                                              extra_path, ignore, verbose,
                                              silent, debug)

        LOG.debug(u"Configuration\n%s", ustr(config))

        ctx.obj = (config, config_builder, commits)

        # If no subcommand is specified, then just lint
        if ctx.invoked_subcommand is None:
            ctx.invoke(lint)

    except GitContextError as e:
        click.echo(ustr(e))
        ctx.exit(GIT_CONTEXT_ERROR_CODE)
Ejemplo n.º 3
0
    def contrib(self, value):
        try:
            self._contrib.set(value)

            # Make sure we unload any previously loaded contrib rules when re-setting the value
            self.rules.delete_rules_by_attr("is_contrib", True)

            # Load all classes from the contrib directory
            contrib_dir_path = os.path.dirname(
                os.path.realpath(contrib_rules.__file__))
            rule_classes = rule_finder.find_rule_classes(contrib_dir_path)

            # For each specified contrib rule, check whether it exists among the contrib classes
            for rule_id_or_name in self.contrib:
                rule_class = next(
                    (rc
                     for rc in rule_classes if rc.id == ustr(rule_id_or_name)
                     or rc.name == ustr(rule_id_or_name)), False)

                # If contrib rule exists, instantiate it and add it to the rules list
                if rule_class:
                    self.rules.add_rule(rule_class, rule_class.id,
                                        {'is_contrib': True})
                else:
                    raise LintConfigError(
                        u"No contrib rule with id or name '{0}' found.".format(
                            ustr(rule_id_or_name)))

        except (options.RuleOptionError, rules.UserRuleError) as e:
            raise LintConfigError(ustr(e))
Ejemplo n.º 4
0
def lint(ctx):
    """ Lints a git repository [default command] """
    lint_config = ctx.obj[0]
    try:
        if sys.stdin.isatty():
            # If target has not been set explicitly before, fallback to the current directory
            gitcontext = GitContext.from_local_repository(lint_config.target, ctx.obj[2])
        else:
            stdin_str = ustr(sys.stdin.read())
            gitcontext = GitContext.from_commit_msg(stdin_str)
    except GitContextError as e:
        click.echo(ustr(e))
        ctx.exit(GIT_CONTEXT_ERROR_CODE)

    number_of_commits = len(gitcontext.commits)
    # Exit if we don't have commits in the specified range. Use a 0 exit code, since a popular use-case is one
    # where users are using --commits in a check job to check the commit messages inside a CI job. By returning 0, we
    # ensure that these jobs don't fail if for whatever reason the specified commit range is empty.
    if number_of_commits == 0:
        click.echo(u'No commits in range "{0}".'.format(ctx.obj[2]))
        ctx.exit(0)

    general_config_builder = ctx.obj[1]
    last_commit = gitcontext.commits[-1]

    # Let's get linting!
    first_violation = True
    exit_code = 0
    for commit in gitcontext.commits:
        # Build a config_builder and linter taking into account the commit specific config (if any)
        config_builder = general_config_builder.clone()
        config_builder.set_config_from_commit(commit)
        lint_config = config_builder.build(lint_config)
        linter = GitLinter(lint_config)

        # Actually do the linting
        violations = linter.lint(commit)
        # exit code equals the total number of violations in all commits
        exit_code += len(violations)
        if violations:
            # Display the commit hash & new lines intelligently
            if number_of_commits > 1 and commit.sha:
                linter.display.e(u"{0}Commit {1}:".format(
                    "\n" if not first_violation or commit is last_commit else "",
                    commit.sha[:10]
                ))
            linter.print_violations(violations)
            first_violation = False

    # cap actual max exit code because bash doesn't like exit codes larger than 255:
    # http://tldp.org/LDP/abs/html/exitcodes.html
    exit_code = min(MAX_VIOLATION_ERROR_CODE, exit_code)
    LOG.debug("Exit Code = %s", exit_code)
    ctx.exit(exit_code)
Ejemplo n.º 5
0
    def _get_option(self, rule_name_or_id, option_name):
        rule_name_or_id = ustr(rule_name_or_id)  # convert to unicode first
        option_name = ustr(option_name)
        rule = self.get_rule(rule_name_or_id)
        if not rule:
            raise LintConfigError(u"No such rule '{0}'".format(rule_name_or_id))

        option = rule.options.get(option_name)
        if not option:
            raise LintConfigError(u"Rule '{0}' has no option '{1}'".format(rule_name_or_id, option_name))

        return option
Ejemplo n.º 6
0
    def test_contrib(self):
        config = LintConfig()
        contrib_rules = ["contrib-title-conventional-commits", "CC1"]
        config.set_general_option("contrib", ",".join(contrib_rules))
        self.assertEqual(config.contrib, contrib_rules)

        # Check contrib-title-conventional-commits contrib rule
        actual_rule = config.get_rule("contrib-title-conventional-commits")
        self.assertTrue(actual_rule.is_contrib)

        self.assertEqual(ustr(type(actual_rule)),
                         "<class 'conventional_commit.ConventionalCommit'>")
        self.assertEqual(actual_rule.id, 'CT1')
        self.assertEqual(actual_rule.name,
                         u'contrib-title-conventional-commits')
        self.assertEqual(actual_rule.target, rules.CommitMessageTitle)

        expected_rule_option = options.ListOption(
            "types",
            [
                "fix", "feat", "chore", "docs", "style", "refactor", "perf",
                "test", "revert"
            ],
            "Comma separated list of allowed commit types.",
        )

        self.assertListEqual(actual_rule.options_spec, [expected_rule_option])
        self.assertDictEqual(actual_rule.options,
                             {'types': expected_rule_option})

        # Check contrib-body-requires-signed-off-by contrib rule
        actual_rule = config.get_rule("contrib-body-requires-signed-off-by")
        self.assertTrue(actual_rule.is_contrib)

        self.assertEqual(ustr(type(actual_rule)),
                         "<class 'signedoff_by.SignedOffBy'>")
        self.assertEqual(actual_rule.id, 'CC1')
        self.assertEqual(actual_rule.name,
                         u'contrib-body-requires-signed-off-by')

        # reset value (this is a different code path)
        config.set_general_option("contrib",
                                  "contrib-body-requires-signed-off-by")
        self.assertEqual(
            actual_rule,
            config.get_rule("contrib-body-requires-signed-off-by"))
        self.assertIsNone(
            config.get_rule("contrib-title-conventional-commits"))

        # empty value
        config.set_general_option("contrib", "")
        self.assertListEqual(config.contrib, [])
Ejemplo n.º 7
0
def cli(  # pylint: disable=too-many-arguments
    ctx,
    target,
    config,
    c,
    commits,
    extra_path,
    ignore,
    contrib,
    msg_filename,
    ignore_stdin,
    staged,
    verbose,
    silent,
    debug,
):
    """ Git lint tool, checks your git commit messages for styling issues

        Documentation: http://jorisroovers.github.io/gitlint
    """

    try:
        if debug:
            logging.getLogger("gitlint").setLevel(logging.DEBUG)
        LOG.debug(
            "To report issues, please visit https://github.com/jorisroovers/gitlint/issues"
        )

        log_system_info()

        # Get the lint config from the commandline parameters and
        # store it in the context (click allows storing an arbitrary object in ctx.obj).
        config, config_builder = build_config(target, config, c, extra_path,
                                              ignore, contrib, ignore_stdin,
                                              staged, verbose, silent, debug)
        LOG.debug(u"Configuration\n%s", ustr(config))

        ctx.obj = (config, config_builder, commits, msg_filename)

        # If no subcommand is specified, then just lint
        if ctx.invoked_subcommand is None:
            ctx.invoke(lint)

    except GitContextError as e:
        click.echo(ustr(e))
        ctx.exit(GIT_CONTEXT_ERROR_CODE)
    except GitLintUsageError as e:
        click.echo(u"Error: {0}".format(ustr(e)))
        ctx.exit(USAGE_ERROR_CODE)
    except LintConfigError as e:
        click.echo(u"Config Error: {0}".format(ustr(e)))
        ctx.exit(CONFIG_ERROR_CODE)
Ejemplo n.º 8
0
    def set_from_config_file(self, filename):
        """ Loads lint config from a ini-style config file """
        if not os.path.exists(filename):
            raise LintConfigError(u"Invalid file path: {0}".format(filename))
        self._config_path = os.path.abspath(filename)
        try:
            parser = ConfigParser()
            parser.read(filename)

            for section_name in parser.sections():
                for option_name, option_value in parser.items(section_name):
                    self.set_option(section_name, option_name, ustr(option_value))

        except ConfigParserError as e:
            raise LintConfigError(ustr(e))
Ejemplo n.º 9
0
def lint(ctx):
    """ Lints a git repository [default command] """
    lint_config = ctx.obj[0]
    try:
        if sys.stdin.isatty():
            # If target has not been set explicitly before, fallback to the current directory
            gitcontext = GitContext.from_local_repository(
                lint_config.target, ctx.obj[2])
        else:
            stdin_str = ustr(sys.stdin.read())
            gitcontext = GitContext.from_commit_msg(stdin_str)
    except GitContextError as e:
        click.echo(ustr(e))
        ctx.exit(GIT_CONTEXT_ERROR_CODE)

    number_of_commits = len(gitcontext.commits)

    # Exit if we don't have commits in the specified range. Use a 0 exit code, since a popular use-case is one
    # where users are using --commits in a check job to check the commit messages inside a CI job. By returning 0, we
    # ensure that these jobs don't fail if for whatever reason the specified commit range is empty.

    if number_of_commits == 0:
        click.echo(u'No commits in range "{0}".'.format(ctx.obj[2]))
        ctx.exit(0)

    config_builder = ctx.obj[1]
    last_commit = gitcontext.commits[-1]
    # Apply an additional config that is specified in the last commit message
    config_builder.set_config_from_commit(last_commit)
    lint_config = config_builder.build(lint_config)

    # Let's get linting!
    linter = GitLinter(lint_config)
    first_violation = True

    for commit in gitcontext.commits:
        violations = linter.lint(commit)
        if violations:
            # Display the commit hash & new lines intelligently
            if number_of_commits > 1 and commit.sha:
                click.echo(u"{0}Commit {1}:".format(
                    "\n" if not first_violation or commit is last_commit else
                    "", commit.sha[:10]))
            linter.print_violations(violations)
            first_violation = False

    exit_code = min(MAX_VIOLATION_ERROR_CODE, len(violations))
    ctx.exit(exit_code)
Ejemplo n.º 10
0
def _git(*command_parts, **kwargs):
    """ Convenience function for running git commands. Automatically deals with exceptions and unicode. """
    git_kwargs = {'_tty_out': False}
    git_kwargs.update(kwargs)
    try:
        LOG.debug(sstr(command_parts))
        result = sh.git(*command_parts, **git_kwargs)  # pylint: disable=unexpected-keyword-arg
        # If we reach this point and the result has an exit_code that is larger than 0, this means that we didn't
        # get an exception (which is the default sh behavior for non-zero exit codes) and so the user is expecting
        # a non-zero exit code -> just return the entire result
        if hasattr(result, 'exit_code') and result.exit_code > 0:
            return result
        return ustr(result)
    except CommandNotFound:
        raise GitNotInstalledError()
    except ErrorReturnCode as e:  # Something went wrong while executing the git command
        error_msg = e.stderr.strip()
        error_msg_lower = error_msg.lower()
        if '_cwd' in git_kwargs and b"not a git repository" in error_msg_lower:
            error_msg = u"{0} is not a git repository.".format(
                git_kwargs['_cwd'])
            raise GitContextError(error_msg)

        if (b"does not have any commits yet" in error_msg_lower
                or b"ambiguous argument 'head': unknown revision"
                in error_msg_lower):
            raise GitContextError(
                u"Current branch has no commits. Gitlint requires at least one commit to function."
            )

        raise GitExitCodeError(e.full_cmd, error_msg)
Ejemplo n.º 11
0
    def extra_path(self, value):
        try:
            if self.extra_path:
                self._extra_path.set(value)
            else:
                self._extra_path = options.PathOption(
                    'extra-path', value,
                    "Path to a directory or module with extra user-defined rules",
                    type='both'
                )

            # Make sure we unload any previously loaded extra-path rules
            for rule in self.rules:
                if hasattr(rule, 'user_defined') and rule.user_defined:
                    del self._rules[rule.id]

            # Find rules in the new extra-path
            rule_classes = user_rules.find_rule_classes(self.extra_path)

            # Add the newly found rules to the existing rules
            for rule_class in rule_classes:
                rule_obj = rule_class()
                rule_obj.user_defined = True
                self._rules[rule_class.id] = rule_obj

        except (options.RuleOptionError, user_rules.UserRuleError) as e:
            raise LintConfigError(ustr(e))
Ejemplo n.º 12
0
    def _log(self):
        """ Does a call to `git log` to determine a bunch of information about the commit. """
        long_format = "--pretty=%aN%x00%aE%x00%ai%x00%P%n%B"
        raw_commit = _git("log",
                          self.sha,
                          "-1",
                          long_format,
                          _cwd=self.context.repository_path).split("\n")

        (name, email, date,
         parents), commit_msg = raw_commit[0].split('\x00'), "\n".join(
             raw_commit[1:])

        commit_parents = parents.split(" ")
        commit_is_merge_commit = len(commit_parents) > 1

        # "YYYY-MM-DD HH:mm:ss Z" -> ISO 8601-like format
        # Use arrow for datetime parsing, because apparently python is quirky around ISO-8601 dates:
        # http://stackoverflow.com/a/30696682/381010
        commit_date = arrow.get(ustr(date), GIT_TIMEFORMAT).datetime

        # Create Git commit object with the retrieved info
        commit_msg_obj = GitCommitMessage.from_full_message(
            self.context, commit_msg)

        self._cache.update({
            'message': commit_msg_obj,
            'author_name': name,
            'author_email': email,
            'date': commit_date,
            'parents': commit_parents,
            'is_merge_commit': commit_is_merge_commit
        })
Ejemplo n.º 13
0
    def lint(self, commit):
        """ Lint the last commit in a given git context by applying all ignore, title, body and commit rules. """
        LOG.debug("Linting commit %s", commit.sha or "[SHA UNKNOWN]")
        LOG.debug("Commit Object\n" + ustr(commit))

        # Apply config rules
        for rule in self.configuration_rules:
            rule.apply(self.config, commit)

        # Skip linting if this is a special commit type that is configured to be ignored
        ignore_commit_types = ["merge", "squash", "fixup"]
        for commit_type in ignore_commit_types:
            if getattr(commit, "is_{0}_commit".format(commit_type)) and \
               getattr(self.config, "ignore_{0}_commits".format(commit_type)):
                return []

        violations = []
        # determine violations by applying all rules
        violations.extend(
            self._apply_line_rules([commit.message.title], commit,
                                   self.title_line_rules, 1))
        violations.extend(
            self._apply_line_rules(commit.message.body, commit,
                                   self.body_line_rules, 2))
        violations.extend(self._apply_commit_rules(self.commit_rules, commit))

        # Sort violations by line number and rule_id. If there's no line nr specified (=common certain commit rules),
        # we replace None with -1 so that it always get's placed first. Note that we need this to do this to support
        # python 3, as None is not allowed in a list that is being sorted.
        violations.sort(
            key=lambda v: (-1 if v.line_nr is None else v.line_nr, v.rule_id))
        return violations
Ejemplo n.º 14
0
 def set(self, value):
     value = ustr(value)
     if not os.path.isdir(value):
         msg = u"Option {0} must be an existing directory (current value: '{1}')".format(
             self.name, value)
         raise RuleOptionError(msg)
     self.value = os.path.abspath(value)
Ejemplo n.º 15
0
    def _exec(*args, **kwargs):
        if sys.version_info[0] == 2:
            no_command_error = OSError  # noqa pylint: disable=undefined-variable,invalid-name
        else:
            no_command_error = FileNotFoundError  # noqa pylint: disable=undefined-variable

        pipe = subprocess.PIPE
        popen_kwargs = {
            'stdout': pipe,
            'stderr': pipe,
            'shell': kwargs['_tty_out']
        }
        if '_cwd' in kwargs:
            popen_kwargs['cwd'] = kwargs['_cwd']

        try:
            p = subprocess.Popen(args, **popen_kwargs)
            result = p.communicate()
        except no_command_error:
            raise CommandNotFound

        exit_code = p.returncode
        stdout = ustr(result[0])
        stderr = result[1]  # 'sh' does not decode the stderr bytes to unicode
        full_cmd = '' if args is None else ' '.join(args)

        # If not _ok_code is specified, then only a 0 exit code is allowed
        ok_exit_codes = kwargs.get('_ok_code', [0])

        if exit_code in ok_exit_codes:
            return ShResult(full_cmd, stdout, stderr, exit_code)

        # Unexpected error code => raise ErrorReturnCode
        raise ErrorReturnCode(full_cmd, stdout, stderr, p.returncode)
Ejemplo n.º 16
0
def git_commentchar():
    """ Shortcut for retrieving comment char from git config """
    commentchar = _git("config", "--get", "core.commentchar", _ok_code=[1])
    # git will return an exit code of 1 if it can't find a config value, in this case we fall-back to # as commentchar
    if commentchar.exit_code == 1:  # pylint: disable=no-member
        commentchar = "#"
    return ustr(commentchar).replace(u"\n", u"")
Ejemplo n.º 17
0
 def set(self, value):
     value = ustr(value).strip().lower()
     if value not in ['true', 'false']:
         raise RuleOptionError(
             u"Option '{0}' must be either 'true' or 'false'".format(
                 self.name))
     self.value = value == 'true'
Ejemplo n.º 18
0
    def set(self, value):
        value = ustr(value)

        error_msg = u""

        if self.type == 'dir':
            if not os.path.isdir(value):
                error_msg = u"Option {0} must be an existing directory (current value: '{1}')".format(
                    self.name, value)
        elif self.type == 'file':
            if not os.path.isfile(value):
                error_msg = u"Option {0} must be an existing file (current value: '{1}')".format(
                    self.name, value)
        elif self.type == 'both':
            if not os.path.isdir(value) and not os.path.isfile(value):
                error_msg = (
                    u"Option {0} must be either an existing directory or file "
                    u"(current value: '{1}')").format(self.name, value)
        else:
            error_msg = u"Option {0} type must be one of: 'file', 'dir', 'both' (current: '{1}')".format(
                self.name, self.type)

        if error_msg:
            raise RuleOptionError(error_msg)

        self.value = os.path.realpath(value)
Ejemplo n.º 19
0
def get_stdin_data():
    """ Helper function that returns data send to stdin or False if nothing is send """
    # STDIN can only be 3 different types of things ("modes")
    #  1. An interactive terminal device (i.e. a TTY -> sys.stdin.isatty() or stat.S_ISCHR)
    #  2. A (named) pipe (stat.S_ISFIFO)
    #  3. A regular file (stat.S_ISREG)
    # Technically, STDIN can also be other device type like a named unix socket (stat.S_ISSOCK), but we don't
    # support that in gitlint (at least not today).
    #
    # Now, the behavior that we want is the following:
    # If someone sends something directly to gitlint via a pipe or a regular file, read it. If not, read from the
    # local repository.
    # Note that we don't care about whether STDIN is a TTY or not, we only care whether data is via a pipe or regular
    # file.
    # However, in case STDIN is not a TTY, it HAS to be one of the 2 other things (pipe or regular file), even if
    # no-one is actually sending anything to gitlint over them. In this case, we still want to read from the local
    # repository.
    # To support this use-case (which is common in CI runners such as Jenkins and Gitlab), we need to actually attempt
    # to read from STDIN in case it's a pipe or regular file. In case that fails, then we'll fall back to reading
    # from the local repo.

    mode = os.fstat(sys.stdin.fileno()).st_mode
    stdin_is_pipe_or_file = stat.S_ISFIFO(mode) or stat.S_ISREG(mode)
    if stdin_is_pipe_or_file:
        input_data = sys.stdin.read()
        # Only return the input data if there's actually something passed
        # i.e. don't consider empty piped data
        if input_data:
            return ustr(input_data)
    return False
Ejemplo n.º 20
0
 def current_branch(self):
     current_branch = ustr(
         _git("rev-parse",
              "--abbrev-ref",
              "HEAD",
              _cwd=self.repository_path)).strip()
     return current_branch
Ejemplo n.º 21
0
def build_git_context(lint_config, msg_filename, refspec):
    """ Builds a git context based on passed parameters and order of precedence """

    # Determine which GitContext method to use if a custom message is passed
    from_commit_msg = GitContext.from_commit_msg
    if lint_config.staged:
        LOG.debug("Fetching additional meta-data from staged commit")
        from_commit_msg = lambda message: GitContext.from_staged_commit(
            message, lint_config.target)  # noqa

    # Order of precedence:
    # 1. Any data specified via --msg-filename
    if msg_filename:
        LOG.debug("Using --msg-filename.")
        return from_commit_msg(ustr(msg_filename.read()))

    # 2. Any data sent to stdin (unless stdin is being ignored)
    if not lint_config.ignore_stdin:
        stdin_input = get_stdin_data()
        if stdin_input:
            LOG.debug("Stdin data: '%s'", stdin_input)
            LOG.debug("Stdin detected and not ignored. Using as input.")
            return from_commit_msg(stdin_input)

    if lint_config.staged:
        raise GitLintUsageError(
            u"The 'staged' option (--staged) can only be used when using '--msg-filename' or "
            u"when piping data to gitlint via stdin.")

    # 3. Fallback to reading from local repository
    LOG.debug(
        "No --msg-filename flag, no or empty data passed to stdin. Using the local repo."
    )
    return GitContext.from_local_repository(lint_config.target, refspec)
Ejemplo n.º 22
0
def _git(*command_parts, **kwargs):
    """ Convenience function for running git commands. Automatically deals with exceptions and unicode. """
    # Special arguments passed to sh: http://amoffat.github.io/sh/special_arguments.html
    git_kwargs = {'_tty_out': False}
    git_kwargs.update(kwargs)
    try:
        result = sh.git(*command_parts, **git_kwargs)  # pylint: disable=unexpected-keyword-arg
        # If we reach this point and the result has an exit_code that is larger than 0, this means that we didn't
        # get an exception (which is the default sh behavior for non-zero exit codes) and so the user is expecting
        # a non-zero exit code -> just return the entire result
        if hasattr(result, 'exit_code') and result.exit_code > 0:
            return result
        return ustr(result)
    except CommandNotFound:
        raise GitNotInstalledError()
    except ErrorReturnCode as e:  # Something went wrong while executing the git command
        error_msg = e.stderr.strip()
        if '_cwd' in git_kwargs and b"not a git repository" in error_msg.lower(
        ):
            error_msg = u"{0} is not a git repository.".format(
                git_kwargs['_cwd'])
        else:
            error_msg = u"An error occurred while executing '{0}': {1}".format(
                e.full_cmd, error_msg)
        raise GitContextError(error_msg)
Ejemplo n.º 23
0
    def set_from_config_file(self, filename):
        """ Loads lint config from a ini-style config file """
        if not os.path.exists(filename):
            raise LintConfigError(u"Invalid file path: {0}".format(filename))
        self._config_path = os.path.realpath(filename)
        try:
            parser = ConfigParser()

            with io.open(filename, encoding=DEFAULT_ENCODING) as config_file:
                parser.read_file(config_file)

            for section_name in parser.sections():
                for option_name, option_value in parser.items(section_name):
                    self.set_option(section_name, option_name, ustr(option_value))

        except ConfigParserError as e:
            raise LintConfigError(ustr(e))
Ejemplo n.º 24
0
 def get_rule(self, rule_id_or_name):
     # try finding rule by id
     rule_id_or_name = ustr(rule_id_or_name)  # convert to unicode first
     rule = self._rules.get(rule_id_or_name)
     # if not found, try finding rule by name
     if not rule:
         rule = next((rule for rule in self._rules.values() if rule.name == rule_id_or_name), None)
     return rule
Ejemplo n.º 25
0
    def set_from_config_file(self, filename):
        """ Loads lint config from a ini-style config file """
        if not os.path.exists(filename):
            raise LintConfigError(u"Invalid file path: {0}".format(filename))
        self._config_path = os.path.realpath(filename)
        try:
            parser = ConfigParser()

            with io.open(filename, encoding=DEFAULT_ENCODING) as config_file:
                # readfp() is deprecated in python 3.2+, but compatible with 2.7
                parser.readfp(config_file, filename)  # pylint: disable=deprecated-method

            for section_name in parser.sections():
                for option_name, option_value in parser.items(section_name):
                    self.set_option(section_name, option_name, ustr(option_value))

        except ConfigParserError as e:
            raise LintConfigError(ustr(e))
Ejemplo n.º 26
0
    def get_expected(filename="", variable_dict=None):
        """ Utility method to read an expected file from gitlint/tests/expected and return it as a string.
        Optionally replace template variables specified by variable_dict. """
        expected_path = os.path.join(BaseTestCase.EXPECTED_DIR, filename)
        with io.open(expected_path, encoding=DEFAULT_ENCODING) as content:
            expected = ustr(content.read())

        if variable_dict:
            expected = expected.format(**variable_dict)
        return expected
Ejemplo n.º 27
0
 def author_email(self):
     try:
         return ustr(
             _git("config",
                  "--get",
                  "user.email",
                  _cwd=self.context.repository_path)).strip()
     except GitExitCodeError:
         raise GitContextError(
             "Missing git configuration: please set user.email")
Ejemplo n.º 28
0
 def __unicode__(self):
     format_str = u"--- Commit Message ----\n%s\n" + \
                  u"--- Meta info ---------\n" + \
                  u"Author: %s <%s>\nDate:   %s\n" + \
                  u"is-merge-commit:  %s\nis-fixup-commit:  %s\n" + \
                  u"is-squash-commit: %s\nis-revert-commit: %s\n" + \
                  u"-----------------------"  # pragma: no cover
     return format_str % (
         ustr(self.message), self.author_name, self.author_email, self.date,
         self.is_merge_commit, self.is_fixup_commit, self.is_squash_commit,
         self.is_revert_commit)  # pragma: no cover
Ejemplo n.º 29
0
    def get_expected(filename="", variable_dict=None):
        """ Utility method to read an expected file from gitlint/tests/expected and return it as a string.
        Optionally replace template variables specified by variable_dict. """
        expected_dir = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), "expected")
        expected_path = os.path.join(expected_dir, filename)
        expected = ustr(open(expected_path).read())

        if variable_dict:
            expected = expected.format(**variable_dict)
        return expected
Ejemplo n.º 30
0
 def set_rule_option(self, rule_name_or_id, option_name, option_value):
     """ Attempts to set a given value for a given option for a given rule.
         LintConfigErrors will be raised if the rule or option don't exist or if the value is invalid. """
     option = self._get_option(rule_name_or_id, option_name)
     try:
         option.set(option_value)
     except options.RuleOptionError as e:
         msg = u"'{0}' is not a valid value for option '{1}.{2}'. {3}."
         raise LintConfigError(
             msg.format(option_value, rule_name_or_id, option_name,
                        ustr(e)))