Hello community,

here is the log from the commit of package gitlint for openSUSE:Factory checked 
in at 2019-07-05 13:49:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gitlint (Old)
 and      /work/SRC/openSUSE:Factory/.gitlint.new.4615 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gitlint"

Fri Jul  5 13:49:11 2019 rev:2 rq:713565 version:0.11.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/gitlint/gitlint.changes  2017-06-26 
15:52:30.565578629 +0200
+++ /work/SRC/openSUSE:Factory/.gitlint.new.4615/gitlint.changes        
2019-07-05 13:49:14.501501751 +0200
@@ -1,0 +2,11 @@
+Thu Jul  4 11:56:39 UTC 2019 - Rick Salevsky <[email protected]>
+
+- Correct download target URL and fix relax-requirements.patch
+
+-------------------------------------------------------------------
+Tue Jul  2 12:12:25 UTC 2019 - Rick Salevsky <[email protected]>
+
+- Update to v0.11.0
+  * add relax-requirements.patch to make it work with openSUSE
+
+-------------------------------------------------------------------

Old:
----
  gitlint-0.8.2.tar.gz

New:
----
  gitlint-0.11.0.tar.gz
  relax-requirements.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gitlint.spec ++++++
--- /var/tmp/diff_new_pack.NBj2HW/_old  2019-07-05 13:49:15.281502953 +0200
+++ /var/tmp/diff_new_pack.NBj2HW/_new  2019-07-05 13:49:15.289502966 +0200
@@ -1,7 +1,7 @@
 #
-# spec file for package python-gitlint
+# spec file for package gitlint
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,24 +12,30 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
+#
 
 
 %define         modname gitlint
 Name:           %{modname}
-Version:        0.8.2
+Version:        0.11.0
 Release:        0
-License:        MIT
 Summary:        Git commit message linter checking
-Url:            https://github.com/jorisroovers/%{modname}
+License:        MIT
 Group:          Development/Languages/Python
-Source:         
https://files.pythonhosted.org/packages/source/g/%{modname}/%{modname}-%{version}.tar.gz
-BuildRequires:  python-rpm-macros
+Url:            https://github.com/jorisroovers/%{modname}
+Source:         
https://pypi.io/packages/source/g/%{modname}/%{modname}-%{version}.tar.gz
+# PATCH-FIX-OPENSUSE relax-requirements.patch -- relax requirements to work 
with openSUSE
+Patch0:         relax-requirements.patch
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module setuptools}
+BuildRequires:  fdupes
+BuildRequires:  python-rpm-macros
 Requires(post): update-alternatives
 Requires(postun): update-alternatives
-BuildRequires:  fdupes
+Requires:       python-arrow >= 0.10.0
+Requires:       python-click >= 6.7
+Requires:       python-sh >= 1.12.14
 BuildArch:      noarch
 
 %python_subpackages
@@ -43,6 +49,7 @@
 
 %prep
 %setup -q -n %{name}-%{version}
+%patch0 -p1
 
 %build
 %python_build

++++++ gitlint-0.8.2.tar.gz -> gitlint-0.11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/PKG-INFO new/gitlint-0.11.0/PKG-INFO
--- old/gitlint-0.8.2/PKG-INFO  2017-04-25 13:26:40.000000000 +0200
+++ new/gitlint-0.11.0/PKG-INFO 2019-03-13 14:16:59.000000000 +0100
@@ -1,13 +1,13 @@
 Metadata-Version: 1.1
 Name: gitlint
-Version: 0.8.2
+Version: 0.11.0
 Summary: Git commit message linter written in python, checks your commit 
messages for style.
 Home-page: https://github.com/jorisroovers/gitlint
 Author: Joris Roovers
 Author-email: UNKNOWN
 License: MIT
 Description: 
-        Great for use as a commit-msg git hook or as part of your gating 
script in a CI/CD pipeline (e.g. jenkins).
+        Great for use as a commit-msg git hook or as part of your gating 
script in a CI pipeline (e.g. jenkins, gitlab).
         Many of the gitlint validations are based on `well-known`_ community_ 
`standards`_, others are based on checks that
         we've found useful throughout the years. Gitlint has sane defaults, 
but you can also easily customize it to your
         own liking.
@@ -29,12 +29,12 @@
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Environment :: Console
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/README.md new/gitlint-0.11.0/README.md
--- old/gitlint-0.8.2/README.md 2017-04-05 09:42:05.000000000 +0200
+++ new/gitlint-0.11.0/README.md        2019-03-13 14:11:18.000000000 +0100
@@ -5,16 +5,18 @@
 [![PyPi 
Package](https://img.shields.io/pypi/v/gitlint.png)](https://pypi.python.org/pypi/gitlint)
 ![Supported Python 
Versions](https://img.shields.io/pypi/pyversions/gitlint.svg)
 
-Git commit message linter written in python, checks your commit messages for 
style.
+Git commit message linter written in python (for Linux and Mac), checks your 
commit messages for style.
 
-**See 
[jorisroovers.github.io/gitlint/](http://jorisroovers.github.io/gitlint/) for 
full documentation.**
+**See [jorisroovers.github.io/gitlint](http://jorisroovers.github.io/gitlint/) 
for full documentation.**
 
 <a href="http://jorisroovers.github.io/gitlint/"; target="_blank"><img 
src="https://asciinema.org/a/30477.png"; width="640"/></a>
 
 ## Contributing ##
 All contributions are welcome and very much appreciated!
 
+** I'm looking for contributors that are interested in taking a more active 
co-maintainer role as it's becoming increasingly difficult for me to find time 
to maintain gitlint. Please open a PR if you're interested - Thanks! **
+
 See 
[jorisroovers.github.io/gitlint/contributing](http://jorisroovers.github.io/gitlint/contributing)
 for details on
-how to get started - it's easy! 
+how to get started - it's easy!
 
 FYI, we maintain a [wishlist on our 
wiki](https://github.com/jorisroovers/gitlint/wiki/Wishlist).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/__init__.py 
new/gitlint-0.11.0/gitlint/__init__.py
--- old/gitlint-0.8.2/gitlint/__init__.py       2017-04-25 13:03:27.000000000 
+0200
+++ new/gitlint-0.11.0/gitlint/__init__.py      2019-03-13 13:53:55.000000000 
+0100
@@ -1 +1 @@
-__version__ = "0.8.2"
+__version__ = "0.11.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/cli.py 
new/gitlint-0.11.0/gitlint/cli.py
--- old/gitlint-0.8.2/gitlint/cli.py    2017-04-25 12:17:33.000000000 +0200
+++ new/gitlint-0.11.0/gitlint/cli.py   2019-03-13 10:29:52.000000000 +0100
@@ -1,10 +1,11 @@
 # pylint: disable=bad-option-value,wrong-import-position
 # We need to disable the import position checks because of the windows check 
that we need to do below
+import copy
 import logging
 import os
 import platform
+import stat
 import sys
-
 import click
 
 # Error codes
@@ -23,7 +24,7 @@
 import gitlint
 from gitlint.lint import GitLinter
 from gitlint.config import LintConfigBuilder, LintConfigError, 
LintConfigGenerator
-from gitlint.git import GitContext, GitContextError
+from gitlint.git import GitContext, GitContextError, git_version
 from gitlint import hooks
 from gitlint.utils import ustr, LOG_FORMAT
 
@@ -46,6 +47,13 @@
     root_log.setLevel(logging.ERROR)
 
 
+def log_system_info():
+    LOG.debug("Platform: %s", platform.platform())
+    LOG.debug("Python version: %s", sys.version)
+    LOG.debug("Git version: %s", git_version())
+    LOG.debug("Gitlint version: %s", gitlint.__version__)
+
+
 def build_config(ctx, target, config_path, c, extra_path, ignore, verbose, 
silent, debug):
     """ Creates a LintConfig object based on a set of commandline parameters. 
"""
     config_builder = LintConfigBuilder()
@@ -78,8 +86,6 @@
             config_builder.set_option('general', 'debug', debug)
 
         config = config_builder.build()
-        if debug:
-            click.echo(ustr(config), nl=True)
 
         return config, config_builder
     except LintConfigError as e:
@@ -87,6 +93,38 @@
     ctx.exit(CONFIG_ERROR_CODE)  # return CONFIG_ERROR_CODE on config error
 
 
+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
+
+
 @click.group(invoke_without_command=True, epilog="When no COMMAND is 
specified, gitlint defaults to 'gitlint lint'.")
 @click.option('--target', type=click.Path(exists=True, resolve_path=True, 
file_okay=False, readable=True),
               help="Path of the target git repository. [default: current 
working directory]")
@@ -95,31 +133,44 @@
 @click.option('-c', multiple=True,
               help="Config flags in format <rule>.<option>=<value> (e.g.: -c 
T1.line-length=80). " +
                    "Flag can be used multiple times to set multiple config 
values.")  # pylint: disable=bad-continuation
[email protected]('--commits', default="HEAD", help="The range of commits to lint. 
[default: HEAD]")
[email protected]('--commits', default=None, help="The range of commits to lint. 
[default: HEAD]")
 @click.option('-e', '--extra-path', help="Path to a directory or python module 
with extra user-defined rules",
               type=click.Path(exists=True, resolve_path=True, readable=True))
 @click.option('--ignore', default="", help="Ignore rules (comma-separated by 
id or name).")
[email protected]('--msg-filename', type=click.File(), help="Path to a file 
containing a commit-msg.")
 @click.option('-v', '--verbose', count=True, default=0,
               help="Verbosity, more v's for more verbose output (e.g.: -v, 
-vv, -vvv). [default: -vvv]", )
 @click.option('-s', '--silent', help="Silent mode (no output). Takes 
precedence over -v, -vv, -vvv.", is_flag=True)
 @click.option('-d', '--debug', help="Enable debugging output.", is_flag=True)
 @click.version_option(version=gitlint.__version__)
 @click.pass_context
-def cli(ctx, target, config, c, commits, extra_path, ignore, verbose, silent, 
debug):
+def cli(  # pylint: disable=too-many-arguments
+        ctx, target, config, c, commits, extra_path, ignore, msg_filename,
+        verbose, silent, debug,
+):
     """ Git lint tool, checks your git commit messages for styling issues """
 
-    if debug:
-        logging.getLogger("gitlint").setLevel(logging.DEBUG)
+    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))
 
-    # 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)
-
-    ctx.obj = (config, config_builder, commits)
-
-    # If no subcommand is specified, then just lint
-    if ctx.invoked_subcommand is None:
-        ctx.invoke(lint)
+        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)
 
 
 @cli.command("lint")
@@ -127,23 +178,30 @@
 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)
+    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:
-        click.echo(u'No commits in range "{0}".'.format(ctx.obj[2]))
+        LOG.debug(u'No commits in range "%s"', ctx.obj[2])
         ctx.exit(0)
 
     general_config_builder = ctx.obj[1]
@@ -153,13 +211,16 @@
     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)
+        # 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)
-        lint_config = config_builder.build(lint_config)
-        linter = GitLinter(lint_config)
+
+        # 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)
@@ -234,4 +295,5 @@
 # Let's Party!
 setup_logging()
 if __name__ == "__main__":
-    cli()  # pragma: no cover, # pylint: disable=no-value-for-parameter
+    # pylint: disable=no-value-for-parameter
+    cli()  # pragma: no cover
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/config.py 
new/gitlint-0.11.0/gitlint/config.py
--- old/gitlint-0.8.2/gitlint/config.py 2017-04-25 11:04:57.000000000 +0200
+++ new/gitlint-0.11.0/gitlint/config.py        2019-03-13 13:17:13.000000000 
+0100
@@ -46,7 +46,9 @@
     """
 
     # Default tuple of rule classes (tuple because immutable).
-    default_rule_classes = (rules.TitleMaxLength,
+    default_rule_classes = (rules.IgnoreByTitle,
+                            rules.IgnoreByBody,
+                            rules.TitleMaxLength,
                             rules.TitleTrailingWhitespace,
                             rules.TitleLeadingWhitespace,
                             rules.TitleTrailingPunctuation,
@@ -59,13 +61,16 @@
                             rules.BodyTrailingWhitespace,
                             rules.BodyHardTab,
                             rules.BodyFirstLineEmpty,
-                            rules.BodyChangedFileMention)
+                            rules.BodyChangedFileMention,
+                            rules.AuthorValidEmail)
 
     def __init__(self):
         # Use an ordered dict so that the order in which rules are applied is 
always the same
         self._rules = OrderedDict([(rule_cls.id, rule_cls()) for rule_cls in 
self.default_rule_classes])
         self._verbosity = options.IntOption('verbosity', 3, "Verbosity")
         self._ignore_merge_commits = 
options.BoolOption('ignore-merge-commits', True, "Ignore merge commits")
+        self._ignore_fixup_commits = 
options.BoolOption('ignore-fixup-commits', True, "Ignore fixup commits")
+        self._ignore_squash_commits = 
options.BoolOption('ignore-squash-commits', True, "Ignore squash commits")
         self._debug = options.BoolOption('debug', False, "Enable debug mode")
         self._extra_path = None
         target_description = "Path of the target git repository 
(default=current working directory)"
@@ -103,6 +108,24 @@
         return self._ignore_merge_commits.set(value)
 
     @property
+    def ignore_fixup_commits(self):
+        return self._ignore_fixup_commits.value
+
+    @ignore_fixup_commits.setter
+    @handle_option_error
+    def ignore_fixup_commits(self, value):
+        return self._ignore_fixup_commits.set(value)
+
+    @property
+    def ignore_squash_commits(self):
+        return self._ignore_squash_commits.value
+
+    @ignore_squash_commits.setter
+    @handle_option_error
+    def ignore_squash_commits(self, value):
+        return self._ignore_squash_commits.set(value)
+
+    @property
     def debug(self):
         return self._debug.value
 
@@ -202,8 +225,9 @@
         # only allow setting general options that exist and don't start with 
an underscore
         if not hasattr(self, attr_name) or attr_name[0] == "_":
             raise LintConfigError(u"'{0}' is not a valid gitlint 
option".format(option_name))
-        else:
-            setattr(self, attr_name, option_value)
+
+        # else:
+        setattr(self, attr_name, option_value)
 
     def __eq__(self, other):
         return isinstance(other, LintConfig) and \
@@ -212,6 +236,8 @@
                self.target == other.target and \
                self.extra_path == other.extra_path and \
                self.ignore_merge_commits == other.ignore_merge_commits and \
+               self.ignore_fixup_commits == other.ignore_fixup_commits and \
+               self.ignore_squash_commits == other.ignore_squash_commits and \
                self.debug == other.debug and \
                self.ignore == other.ignore and \
                self._config_path == other._config_path  # noqa
@@ -223,13 +249,15 @@
         return_str += u"extra-path: {0}\n".format(self.extra_path)
         return_str += u"ignore: {0}\n".format(",".join(self.ignore))
         return_str += u"ignore-merge-commits: 
{0}\n".format(self.ignore_merge_commits)
+        return_str += u"ignore-fixup-commits: 
{0}\n".format(self.ignore_fixup_commits)
+        return_str += u"ignore-squash-commits: 
{0}\n".format(self.ignore_squash_commits)
         return_str += u"verbosity: {0}\n".format(self.verbosity)
         return_str += u"debug: {0}\n".format(self.debug)
         return_str += u"target: {0}\n".format(self.target)
         return_str += u"[RULES]\n"
         for rule in self.rules:
             return_str += u"  {0}: {1}\n".format(rule.id, rule.name)
-            for option_name, option_value in rule.options.items():
+            for option_name, option_value in sorted(rule.options.items()):
                 if isinstance(option_value.value, list):
                     option_val_repr = ",".join(option_value.value)
                 else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/files/commit-msg 
new/gitlint-0.11.0/gitlint/files/commit-msg
--- old/gitlint-0.8.2/gitlint/files/commit-msg  2016-12-01 21:37:44.000000000 
+0100
+++ new/gitlint-0.11.0/gitlint/files/commit-msg 2018-04-02 11:59:07.000000000 
+0200
@@ -26,7 +26,7 @@
 
 run_gitlint(){
    echo "gitlint: checking commit message..."
-   cat "$1" | python -m gitlint.cli
+   python -m gitlint.cli --msg-filename "$1"
    gitlint_exit_code=$?
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/files/gitlint 
new/gitlint-0.11.0/gitlint/files/gitlint
--- old/gitlint-0.8.2/gitlint/files/gitlint     2016-12-02 15:21:52.000000000 
+0100
+++ new/gitlint-0.11.0/gitlint/files/gitlint    2018-04-02 11:59:07.000000000 
+0200
@@ -1,10 +1,20 @@
 # All these sections are optional, edit this file as you like.
 # [general]
+# Ignore certain rules, you can reference them by their id or by their full 
name
 # ignore=title-trailing-punctuation, T3
+
 # verbosity should be a value between 1 and 3, the commandline -v flags take 
precedence over this
 # verbosity = 2
+
 # By default gitlint will ignore merge commits. Set to 'false' to disable.
 # ignore-merge-commits=true
+
+# By default gitlint will ignore fixup commits. Set to 'false' to disable.
+# ignore-fixup-commits=true
+
+# By default gitlint will ignore squash commits. Set to 'false' to disable.
+# ignore-squash-commits=true
+
 # Enable debug mode (prints more output). Disabled by default.
 # debug=true
 
@@ -46,3 +56,27 @@
 # By specifying this rule, developers can only change the file when they 
explicitly reference
 # it in the commit message.
 # files=gitlint/rules.py,README.md
+
+# [author-valid-email]
+# python like regex (https://docs.python.org/2/library/re.html) that the
+# commit author email address should be matched to
+# For example, use the following regex if you only want to allow email 
addresses from foo.com
+# regex=[^@][email protected]
+
+# [ignore-by-title]
+# Ignore certain rules for commits of which the title matches a regex
+# E.g. Match commit titles that start with "Release"
+# regex=^Release(.*)
+#
+# Ignore certain rules, you can reference them by their id or by their full 
name
+# Use 'all' to ignore all rules
+# ignore=T1,body-min-length
+
+# [ignore-by-body]
+# Ignore certain rules for commits of which the body has a line that matches a 
regex
+# E.g. Match bodies that have a line that that contain "release"
+# regex=(.*)release(.*)
+#
+# Ignore certain rules, you can reference them by their id or by their full 
name
+# Use 'all' to ignore all rules
+# ignore=T1,body-min-length
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/git.py 
new/gitlint-0.11.0/gitlint/git.py
--- old/gitlint-0.8.2/gitlint/git.py    2017-03-14 10:16:31.000000000 +0100
+++ new/gitlint-0.11.0/gitlint/git.py   2019-03-13 12:27:10.000000000 +0100
@@ -11,6 +11,51 @@
     pass
 
 
+class GitNotInstalledError(GitContextError):
+    def __init__(self):
+        super(GitNotInstalledError, self).__init__(
+            u"'git' command not found. You need to install git to use gitlint 
on a local repository. " +
+            u"See 
https://git-scm.com/book/en/v2/Getting-Started-Installing-Git on how to install 
git.")
+
+
+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)
+
+
+def git_version():
+    """ Determine the git version installed on this host by calling git 
--version"""
+    return _git("--version").replace(u"\n", u"")
+
+
+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 hasattr(commentchar, 'exit_code') and commentchar.exit_code == 1:  # 
pylint: disable=no-member
+        commentchar = "#"
+    return ustr(commentchar).replace(u"\n", u"")
+
+
 class GitCommitMessage(object):
     """ Class representing a git commit message. A commit message consists of 
the following:
       - original: The actual commit message as returned by `git log`
@@ -18,6 +63,8 @@
       - title: the first line of full
       - body: all lines following the title
     """
+    COMMENT_CHAR = git_commentchar()
+    CUTLINE = '{0} ------------------------ >8 
------------------------'.format(COMMENT_CHAR)
 
     def __init__(self, original=None, full=None, title=None, body=None):
         self.original = original
@@ -28,9 +75,14 @@
     @staticmethod
     def from_full_message(commit_msg_str):
         """  Parses a full git commit message by parsing a given string into 
the different parts of a commit message """
-        lines = [line for line in commit_msg_str.splitlines() if not 
line.startswith("#")]
+        all_lines = commit_msg_str.splitlines()
+        try:
+            cutline_index = all_lines.index(GitCommitMessage.CUTLINE)
+        except ValueError:
+            cutline_index = None
+        lines = [line for line in all_lines[:cutline_index] if not 
line.startswith(GitCommitMessage.COMMENT_CHAR)]
         full = "\n".join(lines)
-        title = lines[0] if len(lines) > 0 else ""
+        title = lines[0] if lines else ""
         body = lines[1:] if len(lines) > 1 else []
         return GitCommitMessage(original=commit_msg_str, full=full, 
title=title, body=body)
 
@@ -38,7 +90,7 @@
         return self.full  # pragma: no cover
 
     def __str__(self):
-        return sstr(self)  # pragma: no cover
+        return sstr(self.__unicode__())  # pragma: no cover
 
     def __repr__(self):
         return self.__str__()  # pragma: no cover
@@ -54,8 +106,9 @@
         In the context of gitlint, only the git context and commit message are 
required.
     """
 
-    def __init__(self, context, message, sha=None, date=None, 
author_name=None, author_email=None, parents=None,
-                 is_merge_commit=False, changed_files=None):
+    def __init__(self, context, message, sha=None, date=None, 
author_name=None,  # pylint: disable=too-many-arguments
+                 author_email=None, parents=None, is_merge_commit=None, 
is_fixup_commit=None,
+                 is_squash_commit=None, changed_files=None):
         self.context = context
         self.message = message
         self.sha = sha
@@ -64,15 +117,19 @@
         self.author_email = author_email
         # parent commit hashes
         self.parents = parents or []
-        self.is_merge_commit = is_merge_commit
         self.changed_files = changed_files or []
 
+        # If it's not explicitely specified, we consider a commit a merge 
commit if its title starts with "Merge"
+        self.is_merge_commit = message.title.startswith(u"Merge") if 
is_merge_commit is None else is_merge_commit
+        self.is_fixup_commit = message.title.startswith(u"fixup!") if 
is_fixup_commit is None else is_fixup_commit
+        self.is_squash_commit = message.title.startswith(u"squash!") if 
is_squash_commit is None else is_squash_commit
+
     def __unicode__(self):
         format_str = u"Author: %s <%s>\nDate:   %s\n%s"  # pragma: no cover
         return format_str % (self.author_name, self.author_email, self.date, 
ustr(self.message))  # pragma: no cover
 
     def __str__(self):
-        return sstr(self)  # pragma: no cover
+        return sstr(self.__unicode__())  # pragma: no cover
 
     def __repr__(self):
         return self.__str__()  # pragma: no cover
@@ -83,7 +140,8 @@
                self.sha == other.sha and self.author_name == other.author_name 
and \
                self.author_email == other.author_email and \
                self.date == other.date and self.parents == other.parents and \
-               self.is_merge_commit == other.is_merge_commit and 
self.changed_files == other.changed_files  # noqa
+               self.is_merge_commit == other.is_merge_commit and 
self.is_fixup_commit == other.is_fixup_commit and \
+               self.is_squash_commit == other.is_squash_commit and 
self.changed_files == other.changed_files  # noqa
 
 
 class GitContext(object):
@@ -102,73 +160,55 @@
         context = GitContext()
         commit_msg_obj = GitCommitMessage.from_full_message(commit_msg_str)
 
-        # For now, we consider a commit a merge commit if its title starts 
with "Merge"
-        is_merge_commit = commit_msg_obj.title.startswith("Merge")
-        commit = GitCommit(context, commit_msg_obj, 
is_merge_commit=is_merge_commit)
+        commit = GitCommit(context, commit_msg_obj)
 
         context.commits.append(commit)
         return context
 
     @staticmethod
-    def from_local_repository(repository_path, refspec="HEAD"):
+    def from_local_repository(repository_path, refspec=None):
         """ Retrieves the git context from a local git repository.
         :param repository_path: Path to the git repository to retrieve the 
context from
         :param refspec: The commit(s) to retrieve
         """
 
         context = GitContext()
-        try:
-            # Special arguments passed to sh: 
http://amoffat.github.io/sh/special_arguments.html
-            sh_special_args = {
-                '_tty_out': False,
-                '_cwd': repository_path
-            }
-
-            sha_list = sh.git("rev-list",
-                              # If refspec contains a dot it is a range
-                              # eg HEAD^.., upstream/master...HEAD
-                              '--max-count={0}'.format(-1 if "." in refspec 
else 1),
-                              refspec, **sh_special_args).split()
-
-            for sha in sha_list:
-                # Get info from the local git repository: 
https://git-scm.com/docs/pretty-formats
-                raw_commit = sh.git.log(sha, "-1", 
"--pretty=%aN,%aE,%ai,%P%n%B",
-                                        **sh_special_args).split("\n")
-
-                (name, email, date, parents), commit_msg = 
raw_commit[0].split(","), "\n".join(raw_commit[1:])
-
-                commit_parents = parents.split(" ")
-                commit_is_merge_commit = len(commit_parents) > 1
-
-                # changed files in last commit
-                changed_files = sh.git("diff-tree", "--no-commit-id", 
"--name-only",
-                                       "-r", sha, **sh_special_args).split()
-
-                # "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), "YYYY-MM-DD HH:mm:ss 
Z").datetime
-
-                # Create Git commit object with the retrieved info
-                commit_msg_obj = GitCommitMessage.from_full_message(commit_msg)
-                commit = GitCommit(context, commit_msg_obj, sha=sha, 
author_name=name,
-                                   author_email=email, date=commit_date, 
changed_files=changed_files,
-                                   parents=commit_parents, 
is_merge_commit=commit_is_merge_commit)
-
-                context.commits.append(commit)
-
-        except CommandNotFound:
-            raise GitContextError(
-                u"'git' command not found. You need to install git to use 
gitlint on a local repository. "
-                u"See 
https://git-scm.com/book/en/v2/Getting-Started-Installing-Git on how to install 
git."
-            )
-        except ErrorReturnCode as e:  # Something went wrong while executing 
the git command
-            error_msg = e.stderr.strip()
-            if b"Not a git repository" in error_msg:
-                error_msg = u"{0} is not a git 
repository.".format(repository_path)
-            else:
-                error_msg = u"An error occurred while executing '{0}': 
{1}".format(e.full_cmd, error_msg)
-            raise GitContextError(error_msg)
+
+        # If no refspec is defined, fallback to the last commit on the current 
branch
+        if refspec is None:
+            # We tried many things here e.g.: defaulting to e.g. HEAD or 
HEAD^... (incl. dealing with
+            # repos that only have a single commit - HEAD^... doesn't work 
there), but then we still get into
+            # problems with e.g. merge commits. Easiest solution is just 
taking the SHA from `git log -1`.
+            sha_list = [_git("log", "-1", "--pretty=%H", 
_cwd=repository_path).replace(u"\n", u"")]
+        else:
+            sha_list = _git("rev-list", refspec, _cwd=repository_path).split()
+
+        for sha in sha_list:
+            # Get info from the local git repository: 
https://git-scm.com/docs/pretty-formats
+            long_format = "--pretty=%aN%x00%aE%x00%ai%x00%P%n%B"
+            raw_commit = _git("log", sha, "-1", long_format, 
_cwd=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
+
+            # changed files in last commit
+            changed_files = _git("diff-tree", "--no-commit-id", "--name-only", 
"-r", sha, _cwd=repository_path).split()
+
+            # "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), "YYYY-MM-DD HH:mm:ss 
Z").datetime
+
+            # Create Git commit object with the retrieved info
+            commit_msg_obj = GitCommitMessage.from_full_message(commit_msg)
+
+            commit = GitCommit(context, commit_msg_obj, sha=sha, 
author_name=name,
+                               author_email=email, date=commit_date, 
changed_files=changed_files,
+                               parents=commit_parents, 
is_merge_commit=commit_is_merge_commit)
+
+            context.commits.append(commit)
 
         return context
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/lint.py 
new/gitlint-0.11.0/gitlint/lint.py
--- old/gitlint-0.8.2/gitlint/lint.py   2017-04-25 11:14:33.000000000 +0200
+++ new/gitlint-0.11.0/gitlint/lint.py  2019-03-13 10:29:52.000000000 +0100
@@ -1,6 +1,8 @@
+# pylint: disable=logging-not-lazy
 import logging
 from gitlint import rules as gitlint_rules
 from gitlint import display
+from gitlint.utils import ustr
 
 LOG = logging.getLogger(__name__)
 logging.basicConfig()
@@ -14,25 +16,31 @@
 
         self.display = display.Display(config)
 
-    def ignore_rule(self, rule):
+    def should_ignore_rule(self, rule):
+        """ Determines whether a rule should be ignored based on the general 
list of commits to ignore """
         return rule.id in self.config.ignore or rule.name in self.config.ignore
 
     @property
+    def configuration_rules(self):
+        return [rule for rule in self.config.rules if
+                isinstance(rule, gitlint_rules.ConfigurationRule) and not 
self.should_ignore_rule(rule)]
+
+    @property
     def title_line_rules(self):
         return [rule for rule in self.config.rules if
                 isinstance(rule, gitlint_rules.LineRule) and
-                rule.target == gitlint_rules.CommitMessageTitle and not 
self.ignore_rule(rule)]
+                rule.target == gitlint_rules.CommitMessageTitle and not 
self.should_ignore_rule(rule)]
 
     @property
     def body_line_rules(self):
         return [rule for rule in self.config.rules if
                 isinstance(rule, gitlint_rules.LineRule) and
-                rule.target == gitlint_rules.CommitMessageBody and not 
self.ignore_rule(rule)]
+                rule.target == gitlint_rules.CommitMessageBody and not 
self.should_ignore_rule(rule)]
 
     @property
     def commit_rules(self):
         return [rule for rule in self.config.rules if isinstance(rule, 
gitlint_rules.CommitRule) and
-                not self.ignore_rule(rule)]
+                not self.should_ignore_rule(rule)]
 
     @staticmethod
     def _apply_line_rules(lines, commit, rules, line_nr_start):
@@ -60,11 +68,20 @@
         return all_violations
 
     def lint(self, commit):
-        """ Lint the last commit in a given git context by applying all title, 
body and general rules. """
+        """ 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]")
-        # Skip linting if this is merge commit and if the config is set to 
ignore those
-        if commit.is_merge_commit and self.config.ignore_merge_commits:
-            return []
+        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
@@ -72,17 +89,20 @@
         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
-        violations.sort(key=lambda v: (v.line_nr, v.rule_id))  # sort 
violations by line number and rule_id
+        # 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
 
     def print_violations(self, violations):
         """ Print a given set of violations to the standard error output """
         for v in violations:
-            self.display.e(u"{0}: {1}".format(v.line_nr, v.rule_id), 
exact=True)
-            self.display.ee(u"{0}: {1} {2}".format(v.line_nr, v.rule_id, 
v.message), exact=True)
+            line_nr = v.line_nr if v.line_nr else "-"
+            self.display.e(u"{0}: {1}".format(line_nr, v.rule_id), exact=True)
+            self.display.ee(u"{0}: {1} {2}".format(line_nr, v.rule_id, 
v.message), exact=True)
             if v.content:
-                self.display.eee(u"{0}: {1} {2}: \"{3}\"".format(v.line_nr, 
v.rule_id, v.message, v.content),
+                self.display.eee(u"{0}: {1} {2}: \"{3}\"".format(line_nr, 
v.rule_id, v.message, v.content),
                                  exact=True)
             else:
-                self.display.eee(u"{0}: {1} {2}".format(v.line_nr, v.rule_id, 
v.message), exact=True)
+                self.display.eee(u"{0}: {1} {2}".format(line_nr, v.rule_id, 
v.message), exact=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/rules.py 
new/gitlint-0.11.0/gitlint/rules.py
--- old/gitlint-0.8.2/gitlint/rules.py  2016-12-30 14:24:17.000000000 +0100
+++ new/gitlint-0.11.0/gitlint/rules.py 2019-03-13 10:29:52.000000000 +0100
@@ -1,9 +1,14 @@
+# pylint: disable=inconsistent-return-statements
 import copy
+import logging
 import re
 
 from gitlint.options import IntOption, BoolOption, StrOption, ListOption
 from gitlint.utils import sstr
 
+LOG = logging.getLogger(__name__)
+logging.basicConfig()
+
 
 class Rule(object):
     """ Class representing gitlint rules. """
@@ -36,6 +41,11 @@
         return self.__str__()  # pragma: no cover
 
 
+class ConfigurationRule(Rule):
+    """ Class representing rules that can dynamically change the configuration 
of gitlint during runtime. """
+    pass
+
+
 class CommitRule(Rule):
     """ Class representing rules that act on an entire commit at once """
     pass
@@ -253,7 +263,7 @@
         min_length = self.options['min-length'].value
         body_message_no_newline = "".join([line for line in 
commit.message.body if line is not None])
         actual_length = len(body_message_no_newline)
-        if actual_length > 0 and actual_length < min_length:
+        if 0 < actual_length < min_length:
             violation_message = "Body message is too short 
({0}<{1})".format(actual_length, min_length)
             return [RuleViolation(self.id, violation_message, 
body_message_no_newline, 3)]
 
@@ -286,3 +296,57 @@
                     violation_message = u"Body does not mention changed file 
'{0}'".format(needs_mentioned_file)
                     violations.append(RuleViolation(self.id, 
violation_message, None, len(commit.message.body) + 1))
         return violations if violations else None
+
+
+class AuthorValidEmail(CommitRule):
+    name = "author-valid-email"
+    id = "M1"
+    options_spec = [StrOption('regex', "[^@ ]+@[^@ ]+\.[^@ ]+", "Regex that 
author email address should match")]
+
+    def validate(self, commit):
+        # Note that unicode is allowed in email addresses
+        # See http://stackoverflow.com/questions/3844431
+        # /are-email-addresses-allowed-to-contain-non-alphanumeric-characters
+        email_regex = re.compile(self.options['regex'].value, re.UNICODE)
+
+        if commit.author_email and not email_regex.match(commit.author_email):
+            return [RuleViolation(self.id, "Author email for commit is 
invalid", commit.author_email)]
+
+
+class IgnoreByTitle(ConfigurationRule):
+    name = "ignore-by-title"
+    id = "I1"
+    options_spec = [StrOption('regex', None, "Regex matching the titles of 
commits this rule should apply to"),
+                    StrOption('ignore', "all", "Comman-seperate list of rules 
to ignore")]
+
+    def apply(self, config, commit):
+        title_regex = re.compile(self.options['regex'].value, re.UNICODE)
+
+        if title_regex.match(commit.message.title):
+            config.ignore = self.options['ignore'].value
+
+            message = u"Commit title '{0}' matches the regex '{1}', ignoring 
rules: {2}"
+            message = message.format(commit.message.title, 
self.options['regex'].value, self.options['ignore'].value)
+
+            LOG.debug("Ignoring commit because of rule '%s': %s", self.id, 
message)
+
+
+class IgnoreByBody(ConfigurationRule):
+    name = "ignore-by-body"
+    id = "I2"
+    options_spec = [StrOption('regex', None, "Regex matching lines of the body 
of commits this rule should apply to"),
+                    StrOption('ignore', "all", "Comman-seperate list of rules 
to ignore")]
+
+    def apply(self, config, commit):
+        body_line_regex = re.compile(self.options['regex'].value, re.UNICODE)
+
+        for line in commit.message.body:
+            if body_line_regex.match(line):
+                config.ignore = self.options['ignore'].value
+
+                message = u"Commit message line '{0}' matches the regex '{1}', 
ignoring rules: {2}"
+                message = message.format(line, self.options['regex'].value, 
self.options['ignore'].value)
+
+                LOG.debug("Ignoring commit because of rule '%s': %s", self.id, 
message)
+                # No need to check other lines if we found a match
+                return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/user_rules.py 
new/gitlint-0.11.0/gitlint/user_rules.py
--- old/gitlint-0.8.2/gitlint/user_rules.py     2017-04-25 12:34:00.000000000 
+0200
+++ new/gitlint-0.11.0/gitlint/user_rules.py    2019-03-13 10:29:52.000000000 
+0100
@@ -41,7 +41,7 @@
             modules.append(os.path.splitext(filename)[0])
 
     # No need to continue if there are no modules specified
-    if len(modules) == 0:
+    if not modules:
         return []
 
     # Append the extra rules path to python path so that we can import them
@@ -93,7 +93,7 @@
                                        rules.LineRule.__name__, 
rules.CommitRule.__name__))
 
     # Rules must have an id attribute
-    if not hasattr(clazz, 'id') or clazz.id is None or len(clazz.id) == 0:
+    if not hasattr(clazz, 'id') or clazz.id is None or not clazz.id:
         raise UserRuleError(u"User-defined rule class '{0}' must have an 'id' 
attribute".format(clazz.__name__))
 
     # Rule id's cannot start with gitlint reserved letters
@@ -102,7 +102,7 @@
         raise UserRuleError(msg.format(clazz.__name__, clazz.id[0]))
 
     # Rules must have a name attribute
-    if not hasattr(clazz, 'name') or clazz.name is None or len(clazz.name) == 
0:
+    if not hasattr(clazz, 'name') or clazz.name is None or not clazz.name:
         raise UserRuleError(u"User-defined rule class '{0}' must have a 'name' 
attribute".format(clazz.__name__))
 
     # if set, options_spec must be a list of RuleOption
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint/utils.py 
new/gitlint-0.11.0/gitlint/utils.py
--- old/gitlint-0.8.2/gitlint/utils.py  2017-04-25 12:17:39.000000000 +0200
+++ new/gitlint-0.11.0/gitlint/utils.py 2019-03-13 10:29:52.000000000 +0100
@@ -1,4 +1,4 @@
-# pylint: disable=bad-option-value,unidiomatic-typecheck,undefined-variable
+# pylint: 
disable=bad-option-value,unidiomatic-typecheck,undefined-variable,no-else-return
 import sys
 
 from locale import getpreferredencoding
@@ -17,7 +17,10 @@
         else:
             return unicode(obj)  # pragma: no cover # noqa
     else:
-        return str(obj)
+        if type(obj) in [bytes]:
+            return obj.decode(DEFAULT_ENCODING)
+        else:
+            return str(obj)
 
 
 def sstr(obj):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint.egg-info/PKG-INFO 
new/gitlint-0.11.0/gitlint.egg-info/PKG-INFO
--- old/gitlint-0.8.2/gitlint.egg-info/PKG-INFO 2017-04-25 13:26:39.000000000 
+0200
+++ new/gitlint-0.11.0/gitlint.egg-info/PKG-INFO        2019-03-13 
14:16:59.000000000 +0100
@@ -1,13 +1,13 @@
 Metadata-Version: 1.1
 Name: gitlint
-Version: 0.8.2
+Version: 0.11.0
 Summary: Git commit message linter written in python, checks your commit 
messages for style.
 Home-page: https://github.com/jorisroovers/gitlint
 Author: Joris Roovers
 Author-email: UNKNOWN
 License: MIT
 Description: 
-        Great for use as a commit-msg git hook or as part of your gating 
script in a CI/CD pipeline (e.g. jenkins).
+        Great for use as a commit-msg git hook or as part of your gating 
script in a CI pipeline (e.g. jenkins, gitlab).
         Many of the gitlint validations are based on `well-known`_ community_ 
`standards`_, others are based on checks that
         we've found useful throughout the years. Gitlint has sane defaults, 
but you can also easily customize it to your
         own liking.
@@ -29,12 +29,12 @@
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Environment :: Console
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/gitlint.egg-info/requires.txt 
new/gitlint-0.11.0/gitlint.egg-info/requires.txt
--- old/gitlint-0.8.2/gitlint.egg-info/requires.txt     2017-04-25 
13:26:39.000000000 +0200
+++ new/gitlint-0.11.0/gitlint.egg-info/requires.txt    2019-03-13 
14:16:59.000000000 +0100
@@ -1,9 +1,9 @@
-Click==6.6
+Click==6.7
 arrow==0.10.0
-ordereddict==1.1
 
-[:python_version == "2.6"]
+[:python_version < "2.7"]
 importlib==1.0.3
+ordereddict==1.1
 
 [:sys_platform != "win32"]
-sh==1.11
+sh==1.12.14
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/setup.cfg new/gitlint-0.11.0/setup.cfg
--- old/gitlint-0.8.2/setup.cfg 2017-04-25 13:26:40.000000000 +0200
+++ new/gitlint-0.11.0/setup.cfg        2019-03-13 14:16:59.000000000 +0100
@@ -4,5 +4,4 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gitlint-0.8.2/setup.py new/gitlint-0.11.0/setup.py
--- old/gitlint-0.8.2/setup.py  2017-03-14 10:22:45.000000000 +0100
+++ new/gitlint-0.11.0/setup.py 2019-03-13 13:26:51.000000000 +0100
@@ -1,7 +1,9 @@
 #!/usr/bin/env python
+from __future__ import print_function
 from setuptools import setup, find_packages
 import re
 import os
+import sys
 
 # There is an issue with building python packages in a shared vagrant 
directory because of how setuptools works
 # in python < 2.7.9. We solve this by deleting the filesystem hardlinking 
capability during build.
@@ -9,11 +11,11 @@
 try:
     del os.link
 except:
-    pass # Not all OSes (e.g. windows) support os.link
+    pass  # Not all OSes (e.g. windows) support os.link
 
 description = "Git commit message linter written in python, checks your commit 
messages for style."
 long_description = """
-Great for use as a commit-msg git hook or as part of your gating script in a 
CI/CD pipeline (e.g. jenkins).
+Great for use as a commit-msg git hook or as part of your gating script in a 
CI pipeline (e.g. jenkins, gitlab).
 Many of the gitlint validations are based on `well-known`_ community_ 
`standards`_, others are based on checks that
 we've found useful throughout the years. Gitlint has sane defaults, but you 
can also easily customize it to your
 own liking.
@@ -48,12 +50,12 @@
         "Development Status :: 5 - Production/Stable",
         "Operating System :: OS Independent",
         "Programming Language :: Python",
-        "Programming Language :: Python :: 2.6",
         "Programming Language :: Python :: 2.7",
         "Programming Language :: Python :: 3.3",
         "Programming Language :: Python :: 3.4",
         "Programming Language :: Python :: 3.5",
         "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: Implementation :: CPython",
         "Programming Language :: Python :: Implementation :: PyPy",
         "Environment :: Console",
@@ -63,16 +65,16 @@
         "License :: OSI Approved :: MIT License"
     ],
     install_requires=[
-        'Click==6.6',
-        'arrow==0.10.0',
-        'ordereddict==1.1',
+        'Click==6.7',
+        'arrow==0.10.0'
     ],
     extras_require={
-        ':python_version == "2.6"': [
+        ':python_version < "2.7"': [
             'importlib==1.0.3',
+            'ordereddict==1.1',
         ],
         ':sys_platform != "win32"': [
-            'sh==1.11',
+            'sh==1.12.14',
         ],
     },
     keywords='gitlint git lint',
@@ -89,3 +91,9 @@
         ],
     },
 )
+
+# Print a red deprecation warning for python 2.6 users
+if sys.version_info[0] == 2 and sys.version_info[1] <= 6:
+    msg = "\033[31mDEPRECATION: Python 2.6 or below are no longer supported by 
gitlint or the Python core team." + \
+          "Please upgrade your Python to a later version.\033[0m"
+    print(msg)

++++++ relax-requirements.patch ++++++
diff -u -r gitlint-0.11.0/gitlint.egg-info/requires.txt 
gitlint-0.11.0.patched/gitlint.egg-info/requires.txt
--- gitlint-0.11.0/gitlint.egg-info/requires.txt        2019-03-13 
14:16:59.000000000 +0100
+++ gitlint-0.11.0.patched/gitlint.egg-info/requires.txt        2019-07-04 
15:34:32.604844335 +0200
@@ -1,9 +1,9 @@
-Click==6.7
-arrow==0.10.0
+Click>=6.7
+arrow>=0.10.0
 
 [:python_version < "2.7"]
-importlib==1.0.3
-ordereddict==1.1
+importlib>=1.0.3
+ordereddict>=1.1
 
 [:sys_platform != "win32"]
-sh==1.12.14
+sh>=1.12.14
diff -u -r gitlint-0.11.0/setup.py gitlint-0.11.0.patched/setup.py
--- gitlint-0.11.0/setup.py     2019-03-13 13:26:51.000000000 +0100
+++ gitlint-0.11.0.patched/setup.py     2019-07-04 15:33:46.932567901 +0200
@@ -65,16 +65,16 @@
         "License :: OSI Approved :: MIT License"
     ],
     install_requires=[
-        'Click==6.7',
-        'arrow==0.10.0'
+        'Click>=6.7',
+        'arrow>=0.10.0'
     ],
     extras_require={
         ':python_version < "2.7"': [
-            'importlib==1.0.3',
-            'ordereddict==1.1',
+            'importlib>=1.0.3',
+            'ordereddict>=1.1',
         ],
         ':sys_platform != "win32"': [
-            'sh==1.12.14',
+            'sh>=1.12.14',
         ],
     },
     keywords='gitlint git lint',

Reply via email to