Esempio n. 1
0
def cli(config, c, ignore, verbose, silent):
    """ Git lint tool, checks your git commit messages for styling issues """

    try:
        # Config precedence:
        # First, load default config or config from configfile
        lint_config = get_lint_config(config)
        # Then process any commandline configuration flags
        try:
            lint_config.apply_config_options(c)
        except LintConfigError as e:
            click.echo("Config Error: {}".format(e.message))
            exit(CONFIG_ERROR_CODE)

        # Finally, overwrite with any convenience commandline flags
        lint_config.apply_on_csv_string(ignore, lint_config.disable_rule)
        if silent:
            lint_config.verbosity = 0
        elif verbose > 0:
            lint_config.verbosity = verbose
    except LintConfigError as e:
        click.echo("Config Error: {0}".format(e.message))
        exit(CONFIG_ERROR_CODE)  # return 10000 on config error

    if sys.stdin.isatty():
        gitcontext = GitContext.from_environment()
    else:
        gitcontext = GitContext()
        gitcontext.set_commit_msg(sys.stdin.read())

    linter = GitLinter(lint_config)
    violations = linter.lint(gitcontext)
    linter.print_violations(violations)
    exit(len(violations))
Esempio n. 2
0
def cli(config, c, ignore, verbose, silent):
    """ Git lint tool, checks your git commit messages for styling issues """

    try:
        # Config precedence:
        # First, load default config or config from configfile
        lint_config = get_lint_config(config)
        # Then process any commandline configuration flags
        try:
            lint_config.apply_config_options(c)
        except LintConfigError as e:
            click.echo("Config Error: {}".format(e.message))
            exit(CONFIG_ERROR_CODE)

        # Finally, overwrite with any convenience commandline flags
        lint_config.apply_on_csv_string(ignore, lint_config.disable_rule)
        if silent:
            lint_config.verbosity = 0
        elif verbose > 0:
            lint_config.verbosity = verbose
    except LintConfigError as e:
        click.echo("Config Error: {0}".format(e.message))
        exit(CONFIG_ERROR_CODE)  # return 10000 on config error

    if sys.stdin.isatty():
        gitcontext = GitContext.from_environment()
    else:
        gitcontext = GitContext()
        gitcontext.set_commit_msg(sys.stdin.read())

    linter = GitLinter(lint_config)
    violations = linter.lint(gitcontext)
    linter.print_violations(violations)
    exit(len(violations))
Esempio n. 3
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)
        else:
            gitcontext = GitContext.from_commit_msg(sys.stdin.read())
    except GitContextError as e:
        click.echo(str(e))
        ctx.exit(GIT_CONTEXT_ERROR_CODE)

    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)
    violations = linter.lint(last_commit)
    linter.print_violations(violations)
    exit_code = min(MAX_VIOLATION_ERROR_CODE, len(violations))
    ctx.exit(exit_code)
Esempio n. 4
0
def lint(ctx):
    """ Lints a git repository [default command] """
    lint_config = ctx.obj.config
    refspec = ctx.obj.refspec
    msg_filename = ctx.obj.msg_filename

    gitcontext = build_git_context(lint_config, msg_filename, refspec)
    # Set gitcontext in the click context, so we can use it in command that are ran after this
    # in particular, this is used by run-hook
    ctx.obj.gitcontext = gitcontext

    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:
        LOG.debug(u'No commits in range "%s"', refspec)
        ctx.exit(0)

    LOG.debug(u'Linting %d commit(s)', number_of_commits)
    general_config_builder = ctx.obj.config_builder
    last_commit = gitcontext.commits[-1]

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

        # Create a deepcopy from the original config, so we have a unique config object per commit
        # This is important for configuration rules to be able to modifying the config on a per commit basis
        commit_config = config_builder.build(copy.deepcopy(lint_config))

        # Actually do the linting
        linter = GitLinter(commit_config)
        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("{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)
Esempio n. 5
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)
Esempio n. 6
0
    def test_print_violations(self):
        violations = [RuleViolation("RULE_ID_1", "Error Message 1", "Violating Content 1", 1),
                      RuleViolation("RULE_ID_2", "Error Message 2", "Violating Content 2", 2)]
        linter = GitLinter(LintConfig())

        # test output with increasing verbosity
        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 0
            linter.print_violations(violations)
            self.assertEqual("", stderr.getvalue())

        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 1
            linter.print_violations(violations)
            expected = "1: RULE_ID_1\n2: RULE_ID_2\n"
            self.assertEqual(expected, stderr.getvalue())

        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 2
            linter.print_violations(violations)
            expected = "1: RULE_ID_1 Error Message 1\n2: RULE_ID_2 Error Message 2\n"
            self.assertEqual(expected, stderr.getvalue())

        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 3
            linter.print_violations(violations)
            expected = "1: RULE_ID_1 Error Message 1: \"Violating Content 1\"\n" + \
                       "2: RULE_ID_2 Error Message 2: \"Violating Content 2\"\n"
            self.assertEqual(expected, stderr.getvalue())
Esempio n. 7
0
    def test_print_violations(self):
        violations = [
            RuleViolation("RULE_ID_1", u"Error Messåge 1",
                          "Violating Content 1", None),
            RuleViolation("RULE_ID_2", "Error Message 2",
                          u"Violåting Content 2", 2)
        ]
        linter = GitLinter(LintConfig())

        # test output with increasing verbosity
        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 0
            linter.print_violations(violations)
            self.assertEqual("", stderr.getvalue())

        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 1
            linter.print_violations(violations)
            expected = u"-: RULE_ID_1\n2: RULE_ID_2\n"
            self.assertEqual(expected, stderr.getvalue())

        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 2
            linter.print_violations(violations)
            expected = u"-: RULE_ID_1 Error Messåge 1\n2: RULE_ID_2 Error Message 2\n"
            self.assertEqual(expected, stderr.getvalue())

        with patch('gitlint.display.stderr', new=StringIO()) as stderr:
            linter.config.verbosity = 3
            linter.print_violations(violations)
            expected = u"-: RULE_ID_1 Error Messåge 1: \"Violating Content 1\"\n" + \
                       u"2: RULE_ID_2 Error Message 2: \"Violåting Content 2\"\n"
            self.assertEqual(expected, stderr.getvalue())
Esempio n. 8
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)
Esempio n. 9
0
def lint(ctx):
    """ Lints a git repository [default command] """
    lint_config = ctx.obj
    try:
        if sys.stdin.isatty():
            gitcontext = GitContext.from_local_repository(lint_config.target)
        else:
            gitcontext = GitContext.from_commit_msg(sys.stdin.read())
    except GitContextError as e:
        click.echo(str(e))
        ctx.exit(GIT_CONTEXT_ERROR_CODE)

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

    # Let's get linting!
    linter = GitLinter(lint_config)
    violations = linter.lint(last_commit, gitcontext)
    linter.print_violations(violations)
    exit_code = min(MAX_VIOLATION_ERROR_CODE, len(violations))
    ctx.exit(exit_code)
Esempio n. 10
0
def lint(ctx):
    """ Lints a git repository [default command] """
    lint_config = ctx.obj
    try:
        if sys.stdin.isatty():
            gitcontext = GitContext.from_local_repository(lint_config.target)
        else:
            gitcontext = GitContext.from_commit_msg(sys.stdin.read())
    except GitContextError as e:
        click.echo(str(e))
        ctx.exit(GIT_CONTEXT_ERROR_CODE)

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

    # Let's get linting!
    linter = GitLinter(lint_config)
    violations = linter.lint(last_commit)
    linter.print_violations(violations)
    exit_code = min(MAX_VIOLATION_ERROR_CODE, len(violations))
    ctx.exit(exit_code)
Esempio n. 11
0
def lint(ctx):
    """ Lints a git repository [default command] """
    lint_config = ctx.obj[0]
    msg_filename = ctx.obj[3]

    # Let's determine where our input data is coming from:
    # Order of precedence:
    # 1. Any data specified via --msg-filename
    # 2. Any data sent to stdin
    # 3. Fallback to reading from local repository
    stdin_input = get_stdin_data()
    if msg_filename:
        LOG.debug("Attempting to read from --msg-filename.")
        gitcontext = GitContext.from_commit_msg(ustr(msg_filename.read()))
    elif stdin_input:
        LOG.debug("No --msg-filename flag. Attempting to read from stdin.")
        gitcontext = GitContext.from_commit_msg(stdin_input)
    else:
        LOG.debug(
            "No --msg-filename flag, no or empty data passed to stdin. Attempting to read from the local repo."
        )
        gitcontext = GitContext.from_local_repository(lint_config.target,
                                                      ctx.obj[2])

    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:
        LOG.debug(u'No commits in range "%s"', 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 taking into account the commit specific config (if any)
        config_builder = general_config_builder.clone()
        config_builder.set_config_from_commit(commit)

        # Create a deepcopy from the original config, so we have a unique config object per commit
        # This is important for configuration rules to be able to modifying the config on a per commit basis
        commit_config = config_builder.build(copy.deepcopy(lint_config))

        # Actually do the linting
        linter = GitLinter(commit_config)
        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)