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)
Lints a git repository [default command]