Adding upstream version 0.14.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
d8f166e6bb
commit
a06c1515ef
109 changed files with 2822 additions and 912 deletions
19
qa/base.py
19
qa/base.py
|
@ -93,6 +93,19 @@ class BaseTestCase(TestCase):
|
|||
io.open(os.path.join(parent_dir, test_filename), 'a', encoding=DEFAULT_ENCODING).close()
|
||||
return test_filename
|
||||
|
||||
@staticmethod
|
||||
def create_environment(envvars=None):
|
||||
""" Creates a copy of the current os.environ and adds/overwrites a given set of variables to it """
|
||||
environment = os.environ.copy()
|
||||
if envvars:
|
||||
environment.update(envvars)
|
||||
return environment
|
||||
|
||||
def create_tmp_git_config(self, contents):
|
||||
""" Creates an environment with the GIT_CONFIG variable set to a file with the given contents. """
|
||||
tmp_config = self.create_tmpfile(contents)
|
||||
return self.create_environment({"GIT_CONFIG": tmp_config})
|
||||
|
||||
def create_simple_commit(self, message, out=None, ok_code=None, env=None, git_repo=None, tty_in=False):
|
||||
""" Creates a simple commit with an empty test file.
|
||||
:param message: Commit message for the commit. """
|
||||
|
@ -103,9 +116,7 @@ class BaseTestCase(TestCase):
|
|||
# variables can influence how git runs.
|
||||
# This was needed to fix https://github.com/jorisroovers/gitlint/issues/15 as we need to make sure to use
|
||||
# the PATH variable that contains the virtualenv's python binary.
|
||||
environment = os.environ
|
||||
if env:
|
||||
environment.update(env)
|
||||
environment = self.create_environment(env)
|
||||
|
||||
# Create file and add to git
|
||||
test_filename = self.create_file(git_repo)
|
||||
|
@ -164,7 +175,7 @@ class BaseTestCase(TestCase):
|
|||
expected_git_version = git("--version").replace("\n", "")
|
||||
return {'platform': platform.platform(), 'python_version': sys.version,
|
||||
'git_version': expected_git_version, 'gitlint_version': expected_gitlint_version,
|
||||
'GITLINT_USE_SH_LIB': BaseTestCase.GITLINT_USE_SH_LIB}
|
||||
'GITLINT_USE_SH_LIB': BaseTestCase.GITLINT_USE_SH_LIB, 'DEFAULT_ENCODING': DEFAULT_ENCODING}
|
||||
|
||||
def get_debug_vars_last_commit(self, git_repo=None):
|
||||
""" Returns a dict with items related to `gitlint --debug` output for the last commit. """
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
DEBUG: gitlint.cli To report issues, please visit https://github.com/jorisroovers/gitlint/issues
|
||||
DEBUG: gitlint.cli Platform: {platform}
|
||||
DEBUG: gitlint.cli Python version: {python_version}
|
||||
DEBUG: gitlint.git ('--version',)
|
||||
DEBUG: gitlint.cli Git version: {git_version}
|
||||
DEBUG: gitlint.cli Gitlint version: {gitlint_version}
|
||||
DEBUG: gitlint.cli GITLINT_USE_SH_LIB: {GITLINT_USE_SH_LIB}
|
||||
DEBUG: gitlint.cli DEFAULT_ENCODING: {DEFAULT_ENCODING}
|
||||
DEBUG: gitlint.cli Configuration
|
||||
config-path: None
|
||||
[GENERAL]
|
||||
|
@ -26,6 +28,8 @@ target: {target}
|
|||
I2: ignore-by-body
|
||||
ignore=all
|
||||
regex=None
|
||||
I3: ignore-body-lines
|
||||
regex=None
|
||||
T1: title-max-length
|
||||
line-length=72
|
||||
T2: title-trailing-whitespace
|
||||
|
@ -35,7 +39,9 @@ target: {target}
|
|||
T5: title-must-not-contain-word
|
||||
words=WIP
|
||||
T7: title-match-regex
|
||||
regex=.*
|
||||
regex=None
|
||||
T8: title-min-length
|
||||
min-length=5
|
||||
B1: body-max-line-length
|
||||
line-length=80
|
||||
B5: body-min-length
|
||||
|
@ -47,13 +53,20 @@ target: {target}
|
|||
B4: body-first-line-empty
|
||||
B7: body-changed-file-mention
|
||||
files=
|
||||
B8: body-match-regex
|
||||
regex=None
|
||||
M1: author-valid-email
|
||||
regex=[^@ ]+@[^@ ]+\.[^@ ]+
|
||||
|
||||
DEBUG: gitlint.cli Fetching additional meta-data from staged commit
|
||||
DEBUG: gitlint.cli Using --msg-filename.
|
||||
DEBUG: gitlint.git ('config', '--get', 'core.commentchar')
|
||||
DEBUG: gitlint.cli Linting 1 commit(s)
|
||||
DEBUG: gitlint.lint Linting commit [SHA UNKNOWN]
|
||||
DEBUG: gitlint.git ('config', '--get', 'user.name')
|
||||
DEBUG: gitlint.git ('config', '--get', 'user.email')
|
||||
DEBUG: gitlint.git ('rev-parse', '--abbrev-ref', 'HEAD')
|
||||
DEBUG: gitlint.git ('diff', '--staged', '--name-only', '-r')
|
||||
DEBUG: gitlint.lint Commit Object
|
||||
--- Commit Message ----
|
||||
WIP: from fïle test.
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
DEBUG: gitlint.cli To report issues, please visit https://github.com/jorisroovers/gitlint/issues
|
||||
DEBUG: gitlint.cli Platform: {platform}
|
||||
DEBUG: gitlint.cli Python version: {python_version}
|
||||
DEBUG: gitlint.git ('--version',)
|
||||
DEBUG: gitlint.cli Git version: {git_version}
|
||||
DEBUG: gitlint.cli Gitlint version: {gitlint_version}
|
||||
DEBUG: gitlint.cli GITLINT_USE_SH_LIB: {GITLINT_USE_SH_LIB}
|
||||
DEBUG: gitlint.cli DEFAULT_ENCODING: {DEFAULT_ENCODING}
|
||||
DEBUG: gitlint.cli Configuration
|
||||
config-path: None
|
||||
[GENERAL]
|
||||
|
@ -26,6 +28,8 @@ target: {target}
|
|||
I2: ignore-by-body
|
||||
ignore=all
|
||||
regex=None
|
||||
I3: ignore-body-lines
|
||||
regex=None
|
||||
T1: title-max-length
|
||||
line-length=72
|
||||
T2: title-trailing-whitespace
|
||||
|
@ -35,7 +39,9 @@ target: {target}
|
|||
T5: title-must-not-contain-word
|
||||
words=WIP
|
||||
T7: title-match-regex
|
||||
regex=.*
|
||||
regex=None
|
||||
T8: title-min-length
|
||||
min-length=5
|
||||
B1: body-max-line-length
|
||||
line-length=80
|
||||
B5: body-min-length
|
||||
|
@ -47,6 +53,8 @@ target: {target}
|
|||
B4: body-first-line-empty
|
||||
B7: body-changed-file-mention
|
||||
files=
|
||||
B8: body-match-regex
|
||||
regex=None
|
||||
M1: author-valid-email
|
||||
regex=[^@ ]+@[^@ ]+\.[^@ ]+
|
||||
|
||||
|
@ -54,8 +62,13 @@ DEBUG: gitlint.cli Fetching additional meta-data from staged commit
|
|||
DEBUG: gitlint.cli Stdin data: 'WIP: Pïpe test.
|
||||
'
|
||||
DEBUG: gitlint.cli Stdin detected and not ignored. Using as input.
|
||||
DEBUG: gitlint.git ('config', '--get', 'core.commentchar')
|
||||
DEBUG: gitlint.cli Linting 1 commit(s)
|
||||
DEBUG: gitlint.lint Linting commit [SHA UNKNOWN]
|
||||
DEBUG: gitlint.git ('config', '--get', 'user.name')
|
||||
DEBUG: gitlint.git ('config', '--get', 'user.email')
|
||||
DEBUG: gitlint.git ('rev-parse', '--abbrev-ref', 'HEAD')
|
||||
DEBUG: gitlint.git ('diff', '--staged', '--name-only', '-r')
|
||||
DEBUG: gitlint.lint Commit Object
|
||||
--- Commit Message ----
|
||||
WIP: Pïpe test.
|
||||
|
|
93
qa/expected/test_config/test_config_from_env_1
Normal file
93
qa/expected/test_config/test_config_from_env_1
Normal file
|
@ -0,0 +1,93 @@
|
|||
DEBUG: gitlint.cli To report issues, please visit https://github.com/jorisroovers/gitlint/issues
|
||||
DEBUG: gitlint.cli Platform: {platform}
|
||||
DEBUG: gitlint.cli Python version: {python_version}
|
||||
DEBUG: gitlint.git ('--version',)
|
||||
DEBUG: gitlint.cli Git version: {git_version}
|
||||
DEBUG: gitlint.cli Gitlint version: {gitlint_version}
|
||||
DEBUG: gitlint.cli GITLINT_USE_SH_LIB: {GITLINT_USE_SH_LIB}
|
||||
DEBUG: gitlint.cli DEFAULT_ENCODING: {DEFAULT_ENCODING}
|
||||
DEBUG: gitlint.cli Configuration
|
||||
config-path: None
|
||||
[GENERAL]
|
||||
extra-path: None
|
||||
contrib: ['CC1', 'CT1']
|
||||
ignore: T1,T2
|
||||
ignore-merge-commits: True
|
||||
ignore-fixup-commits: True
|
||||
ignore-squash-commits: True
|
||||
ignore-revert-commits: True
|
||||
ignore-stdin: True
|
||||
staged: False
|
||||
verbosity: 2
|
||||
debug: True
|
||||
target: {target}
|
||||
[RULES]
|
||||
I1: ignore-by-title
|
||||
ignore=all
|
||||
regex=None
|
||||
I2: ignore-by-body
|
||||
ignore=all
|
||||
regex=None
|
||||
I3: ignore-body-lines
|
||||
regex=None
|
||||
T1: title-max-length
|
||||
line-length=72
|
||||
T2: title-trailing-whitespace
|
||||
T6: title-leading-whitespace
|
||||
T3: title-trailing-punctuation
|
||||
T4: title-hard-tab
|
||||
T5: title-must-not-contain-word
|
||||
words=WIP
|
||||
T7: title-match-regex
|
||||
regex=None
|
||||
T8: title-min-length
|
||||
min-length=5
|
||||
B1: body-max-line-length
|
||||
line-length=80
|
||||
B5: body-min-length
|
||||
min-length=20
|
||||
B6: body-is-missing
|
||||
ignore-merge-commits=True
|
||||
B2: body-trailing-whitespace
|
||||
B3: body-hard-tab
|
||||
B4: body-first-line-empty
|
||||
B7: body-changed-file-mention
|
||||
files=
|
||||
B8: body-match-regex
|
||||
regex=None
|
||||
M1: author-valid-email
|
||||
regex=[^@ ]+@[^@ ]+\.[^@ ]+
|
||||
CC1: contrib-body-requires-signed-off-by
|
||||
CT1: contrib-title-conventional-commits
|
||||
types=fix,feat,chore,docs,style,refactor,perf,test,revert,ci,build
|
||||
|
||||
DEBUG: gitlint.cli No --msg-filename flag, no or empty data passed to stdin. Using the local repo.
|
||||
DEBUG: gitlint.git ('rev-list', '{commit_sha}')
|
||||
DEBUG: gitlint.cli Linting 1 commit(s)
|
||||
DEBUG: gitlint.git ('log', '{commit_sha}', '-1', '--pretty=%aN%x00%aE%x00%ai%x00%P%n%B')
|
||||
DEBUG: gitlint.git ('config', '--get', 'core.commentchar')
|
||||
DEBUG: gitlint.lint Linting commit {commit_sha}
|
||||
DEBUG: gitlint.git ('branch', '--contains', '{commit_sha}')
|
||||
DEBUG: gitlint.git ('diff-tree', '--no-commit-id', '--name-only', '-r', '--root', '{commit_sha}')
|
||||
DEBUG: gitlint.lint Commit Object
|
||||
--- Commit Message ----
|
||||
WIP: Thïs is a title thåt is a bit longer.
|
||||
Content on the second line
|
||||
This line of the body is here because we need it
|
||||
|
||||
--- Meta info ---------
|
||||
Author: gitlint-test-user <gitlint@test.com>
|
||||
Date: {commit_date}
|
||||
is-merge-commit: False
|
||||
is-fixup-commit: False
|
||||
is-squash-commit: False
|
||||
is-revert-commit: False
|
||||
Branches: ['master']
|
||||
Changed Files: {changed_files}
|
||||
-----------------------
|
||||
1: CC1 Body does not contain a 'Signed-Off-By' line
|
||||
1: CT1 Title does not start with one of fix, feat, chore, docs, style, refactor, perf, test, revert, ci, build
|
||||
1: T3 Title has trailing punctuation (.)
|
||||
1: T5 Title contains the word 'WIP' (case-insensitive)
|
||||
2: B4 Second line is not empty
|
||||
DEBUG: gitlint.cli Exit Code = 5
|
83
qa/expected/test_config/test_config_from_env_2
Normal file
83
qa/expected/test_config/test_config_from_env_2
Normal file
|
@ -0,0 +1,83 @@
|
|||
DEBUG: gitlint.cli To report issues, please visit https://github.com/jorisroovers/gitlint/issues
|
||||
DEBUG: gitlint.cli Platform: {platform}
|
||||
DEBUG: gitlint.cli Python version: {python_version}
|
||||
DEBUG: gitlint.git ('--version',)
|
||||
DEBUG: gitlint.cli Git version: {git_version}
|
||||
DEBUG: gitlint.cli Gitlint version: {gitlint_version}
|
||||
DEBUG: gitlint.cli GITLINT_USE_SH_LIB: {GITLINT_USE_SH_LIB}
|
||||
DEBUG: gitlint.cli DEFAULT_ENCODING: {DEFAULT_ENCODING}
|
||||
DEBUG: gitlint.cli Configuration
|
||||
config-path: None
|
||||
[GENERAL]
|
||||
extra-path: None
|
||||
contrib: []
|
||||
ignore:
|
||||
ignore-merge-commits: True
|
||||
ignore-fixup-commits: True
|
||||
ignore-squash-commits: True
|
||||
ignore-revert-commits: True
|
||||
ignore-stdin: False
|
||||
staged: True
|
||||
verbosity: 0
|
||||
debug: True
|
||||
target: {target}
|
||||
[RULES]
|
||||
I1: ignore-by-title
|
||||
ignore=all
|
||||
regex=None
|
||||
I2: ignore-by-body
|
||||
ignore=all
|
||||
regex=None
|
||||
I3: ignore-body-lines
|
||||
regex=None
|
||||
T1: title-max-length
|
||||
line-length=72
|
||||
T2: title-trailing-whitespace
|
||||
T6: title-leading-whitespace
|
||||
T3: title-trailing-punctuation
|
||||
T4: title-hard-tab
|
||||
T5: title-must-not-contain-word
|
||||
words=WIP
|
||||
T7: title-match-regex
|
||||
regex=None
|
||||
T8: title-min-length
|
||||
min-length=5
|
||||
B1: body-max-line-length
|
||||
line-length=80
|
||||
B5: body-min-length
|
||||
min-length=20
|
||||
B6: body-is-missing
|
||||
ignore-merge-commits=True
|
||||
B2: body-trailing-whitespace
|
||||
B3: body-hard-tab
|
||||
B4: body-first-line-empty
|
||||
B7: body-changed-file-mention
|
||||
files=
|
||||
B8: body-match-regex
|
||||
regex=None
|
||||
M1: author-valid-email
|
||||
regex=[^@ ]+@[^@ ]+\.[^@ ]+
|
||||
|
||||
DEBUG: gitlint.cli Fetching additional meta-data from staged commit
|
||||
DEBUG: gitlint.cli Using --msg-filename.
|
||||
DEBUG: gitlint.git ('config', '--get', 'core.commentchar')
|
||||
DEBUG: gitlint.cli Linting 1 commit(s)
|
||||
DEBUG: gitlint.lint Linting commit [SHA UNKNOWN]
|
||||
DEBUG: gitlint.git ('config', '--get', 'user.name')
|
||||
DEBUG: gitlint.git ('config', '--get', 'user.email')
|
||||
DEBUG: gitlint.git ('rev-parse', '--abbrev-ref', 'HEAD')
|
||||
DEBUG: gitlint.git ('diff', '--staged', '--name-only', '-r')
|
||||
DEBUG: gitlint.lint Commit Object
|
||||
--- Commit Message ----
|
||||
WIP: msg-fïlename test.
|
||||
--- Meta info ---------
|
||||
Author: gitlint-test-user <gitlint@test.com>
|
||||
Date: {date}
|
||||
is-merge-commit: False
|
||||
is-fixup-commit: False
|
||||
is-squash-commit: False
|
||||
is-revert-commit: False
|
||||
Branches: ['master']
|
||||
Changed Files: []
|
||||
-----------------------
|
||||
DEBUG: gitlint.cli Exit Code = 3
|
|
@ -1,9 +1,11 @@
|
|||
DEBUG: gitlint.cli To report issues, please visit https://github.com/jorisroovers/gitlint/issues
|
||||
DEBUG: gitlint.cli Platform: {platform}
|
||||
DEBUG: gitlint.cli Python version: {python_version}
|
||||
DEBUG: gitlint.git ('--version',)
|
||||
DEBUG: gitlint.cli Git version: {git_version}
|
||||
DEBUG: gitlint.cli Gitlint version: {gitlint_version}
|
||||
DEBUG: gitlint.cli GITLINT_USE_SH_LIB: {GITLINT_USE_SH_LIB}
|
||||
DEBUG: gitlint.cli DEFAULT_ENCODING: {DEFAULT_ENCODING}
|
||||
DEBUG: gitlint.cli Configuration
|
||||
config-path: {config_path}
|
||||
[GENERAL]
|
||||
|
@ -26,6 +28,8 @@ target: {target}
|
|||
I2: ignore-by-body
|
||||
ignore=all
|
||||
regex=None
|
||||
I3: ignore-body-lines
|
||||
regex=None
|
||||
T1: title-max-length
|
||||
line-length=20
|
||||
T2: title-trailing-whitespace
|
||||
|
@ -35,7 +39,9 @@ target: {target}
|
|||
T5: title-must-not-contain-word
|
||||
words=WIP,thåt
|
||||
T7: title-match-regex
|
||||
regex=.*
|
||||
regex=None
|
||||
T8: title-min-length
|
||||
min-length=5
|
||||
B1: body-max-line-length
|
||||
line-length=30
|
||||
B5: body-min-length
|
||||
|
@ -47,12 +53,19 @@ target: {target}
|
|||
B4: body-first-line-empty
|
||||
B7: body-changed-file-mention
|
||||
files=
|
||||
B8: body-match-regex
|
||||
regex=None
|
||||
M1: author-valid-email
|
||||
regex=[^@ ]+@[^@ ]+\.[^@ ]+
|
||||
|
||||
DEBUG: gitlint.cli No --msg-filename flag, no or empty data passed to stdin. Using the local repo.
|
||||
DEBUG: gitlint.git ('log', '-1', '--pretty=%H')
|
||||
DEBUG: gitlint.cli Linting 1 commit(s)
|
||||
DEBUG: gitlint.git ('log', '{commit_sha}', '-1', '--pretty=%aN%x00%aE%x00%ai%x00%P%n%B')
|
||||
DEBUG: gitlint.git ('config', '--get', 'core.commentchar')
|
||||
DEBUG: gitlint.lint Linting commit {commit_sha}
|
||||
DEBUG: gitlint.git ('branch', '--contains', '{commit_sha}')
|
||||
DEBUG: gitlint.git ('diff-tree', '--no-commit-id', '--name-only', '-r', '--root', '{commit_sha}')
|
||||
DEBUG: gitlint.lint Commit Object
|
||||
--- Commit Message ----
|
||||
WIP: Thïs is a title thåt is a bit longer.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
1: CC1 Body does not contain a 'Signed-Off-By' line
|
||||
1: CT1 Title does not start with one of fix, feat, chore, docs, style, refactor, perf, test, revert: "WIP Thi$ is å title"
|
||||
1: CT1 Title does not start with one of fix, feat, chore, docs, style, refactor, perf, test, revert, ci, build: "WIP Thi$ is å title"
|
||||
1: CT1 Title does not follow ConventionalCommits.org format 'type(optional-scope): description': "WIP Thi$ is å title"
|
||||
1: T5 Title contains the word 'WIP' (case-insensitive): "WIP Thi$ is å title"
|
||||
|
|
5
qa/expected/test_named_rules/test_named_rule_1
Normal file
5
qa/expected/test_named_rules/test_named_rule_1
Normal file
|
@ -0,0 +1,5 @@
|
|||
1: T5 Title contains the word 'WIP' (case-insensitive): "WIP: thåt dûr bår"
|
||||
1: T5 Title contains the word 'thåt' (case-insensitive): "WIP: thåt dûr bår"
|
||||
1: T5:even$more%wôrds Title contains the word 'bår' (case-insensitive): "WIP: thåt dûr bår"
|
||||
1: T5:extra-wôrds Title contains the word 'dûr' (case-insensitive): "WIP: thåt dûr bår"
|
||||
3: B5 Body message is too short (18<20): "Sïmple commit body"
|
9
qa/expected/test_named_rules/test_named_user_rule_1
Normal file
9
qa/expected/test_named_rules/test_named_user_rule_1
Normal file
|
@ -0,0 +1,9 @@
|
|||
1: UC4 int-öption: 2
|
||||
1: UC4 str-öption: föo
|
||||
1: UC4 list-öption: ['foo', 'bar']
|
||||
1: UC4:bår int-öption: 2
|
||||
1: UC4:bår str-öption: bår
|
||||
1: UC4:bår list-öption: ['bar', 'list']
|
||||
1: UC4:föo int-öption: 3
|
||||
1: UC4:föo str-öption: föo
|
||||
1: UC4:föo list-öption: ['foo', 'bar']
|
|
@ -0,0 +1,4 @@
|
|||
1: UC2 Body does not contain a 'Signed-Off-By' line
|
||||
1: UC3 Branch name 'master' does not start with one of ['feature/', 'hotfix/', 'release/']
|
||||
1: UL1 Title contains the special character '$'
|
||||
2: B4 Second line is not empty
|
|
@ -2,4 +2,8 @@
|
|||
1: UC1 GitContext.current_branch: master
|
||||
1: UC1 GitContext.commentchar: #
|
||||
1: UC2 GitCommit.branches: ['master']
|
||||
2: B4 Second line is not empty: "Content on the second line"
|
||||
1: UC2 GitCommit.custom_prop: foöbar
|
||||
1: UC4 int-öption: 2
|
||||
1: UC4 str-öption: föo
|
||||
1: UC4 list-öption: ['foo', 'bar']
|
||||
4: B2 Line has trailing whitespace: "{repo-path} "
|
||||
|
|
8
qa/samples/config/named-rules
Normal file
8
qa/samples/config/named-rules
Normal file
|
@ -0,0 +1,8 @@
|
|||
[title-must-not-contain-word]
|
||||
words=WIP,thåt
|
||||
|
||||
[title-must-not-contain-word:extra-wôrds]
|
||||
words=hûr,dûr
|
||||
|
||||
[title-must-not-contain-word: even$more%wôrds ]
|
||||
words=fôo,bår
|
15
qa/samples/config/named-user-rules
Normal file
15
qa/samples/config/named-user-rules
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Ignore other user-defined rules
|
||||
[general]
|
||||
ignore=UC1,UC2,UC3,configürable:ignöred
|
||||
|
||||
[UC4:föo]
|
||||
int-öption=3
|
||||
str-öption=föo
|
||||
|
||||
[configürable:bår]
|
||||
str-öption=bår
|
||||
list-öption=bar,list
|
||||
|
||||
# The following rule will be ignored
|
||||
[configürable:ignöred]
|
||||
str-öption=foöbar
|
|
@ -1,16 +1,19 @@
|
|||
from gitlint.rules import CommitRule, RuleViolation
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from gitlint.rules import CommitRule, RuleViolation, ConfigurationRule
|
||||
from gitlint.options import IntOption, StrOption, ListOption
|
||||
from gitlint.utils import sstr
|
||||
|
||||
|
||||
class GitContextRule(CommitRule):
|
||||
""" Rule that tests whether we can correctly access certain gitcontext properties """
|
||||
name = "gitcontext"
|
||||
name = u"gïtcontext"
|
||||
id = "UC1"
|
||||
|
||||
def validate(self, commit):
|
||||
violations = [
|
||||
RuleViolation(self.id, "GitContext.current_branch: {0}".format(commit.context.current_branch), line_nr=1),
|
||||
RuleViolation(self.id, "GitContext.commentchar: {0}".format(commit.context.commentchar), line_nr=1)
|
||||
RuleViolation(self.id, u"GitContext.current_branch: {0}".format(commit.context.current_branch), line_nr=1),
|
||||
RuleViolation(self.id, u"GitContext.commentchar: {0}".format(commit.context.commentchar), line_nr=1)
|
||||
]
|
||||
|
||||
return violations
|
||||
|
@ -18,12 +21,49 @@ class GitContextRule(CommitRule):
|
|||
|
||||
class GitCommitRule(CommitRule):
|
||||
""" Rule that tests whether we can correctly access certain commit properties """
|
||||
name = "gitcommit"
|
||||
name = u"gïtcommit"
|
||||
id = "UC2"
|
||||
|
||||
def validate(self, commit):
|
||||
violations = [
|
||||
RuleViolation(self.id, "GitCommit.branches: {0}".format(sstr(commit.branches)), line_nr=1),
|
||||
RuleViolation(self.id, u"GitCommit.branches: {0}".format(sstr(commit.branches)), line_nr=1),
|
||||
RuleViolation(self.id, u"GitCommit.custom_prop: {0}".format(commit.custom_prop), line_nr=1),
|
||||
]
|
||||
|
||||
return violations
|
||||
|
||||
|
||||
class GitlintConfigurationRule(ConfigurationRule):
|
||||
""" Rule that tests whether we can correctly access the config as well as modify the commit message """
|
||||
name = u"cönfigrule"
|
||||
id = "UC3"
|
||||
|
||||
def apply(self, config, commit):
|
||||
# We add a line to the commit message body that pulls a value from config, this proves we can modify the body
|
||||
# and read the config contents
|
||||
commit.message.body.append("{0} ".format(config.target)) # trailing whitespace deliberate to trigger violation
|
||||
|
||||
# We set a custom property that we access in CommitRule, to prove we can add extra properties to the commit
|
||||
commit.custom_prop = u"foöbar"
|
||||
|
||||
# We also ignore some extra rules, proving that we can modify the config
|
||||
config.ignore.append("B4")
|
||||
|
||||
|
||||
class ConfigurableCommitRule(CommitRule):
|
||||
""" Rule that tests that we can add configuration to user-defined rules """
|
||||
name = u"configürable"
|
||||
id = "UC4"
|
||||
|
||||
options_spec = [IntOption(u"int-öption", 2, u"int-öption description"),
|
||||
StrOption(u"str-öption", u"föo", u"int-öption description"),
|
||||
ListOption(u"list-öption", [u"foo", u"bar"], u"list-öption description")]
|
||||
|
||||
def validate(self, _):
|
||||
violations = [
|
||||
RuleViolation(self.id, u"int-öption: {0}".format(self.options[u'int-öption'].value), line_nr=1),
|
||||
RuleViolation(self.id, u"str-öption: {0}".format(self.options[u'str-öption'].value), line_nr=1),
|
||||
RuleViolation(self.id, u"list-öption: {0}".format(sstr(self.options[u'list-öption'].value)), line_nr=1),
|
||||
]
|
||||
|
||||
return violations
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# on gitlint internals for our integration testing framework.
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from qa.utils import ustr, USE_SH_LIB
|
||||
from qa.utils import ustr, USE_SH_LIB, IS_PY2
|
||||
|
||||
if USE_SH_LIB:
|
||||
from sh import git, echo, gitlint # pylint: disable=unused-import,no-name-in-module,import-error
|
||||
|
@ -59,7 +58,7 @@ else:
|
|||
return ustr(result)
|
||||
|
||||
def _exec(*args, **kwargs):
|
||||
if sys.version_info[0] == 2:
|
||||
if IS_PY2:
|
||||
no_command_error = OSError # noqa pylint: disable=undefined-variable,invalid-name
|
||||
else:
|
||||
no_command_error = FileNotFoundError # noqa pylint: disable=undefined-variable
|
||||
|
@ -68,6 +67,8 @@ else:
|
|||
popen_kwargs = {'stdout': pipe, 'stderr': pipe, 'shell': kwargs.get('_tty_out', False)}
|
||||
if '_cwd' in kwargs:
|
||||
popen_kwargs['cwd'] = kwargs['_cwd']
|
||||
if '_env' in kwargs:
|
||||
popen_kwargs['env'] = kwargs['_env']
|
||||
|
||||
try:
|
||||
p = subprocess.Popen(args, **popen_kwargs)
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=too-many-function-args,unexpected-keyword-arg
|
||||
|
||||
import re
|
||||
|
||||
from qa.shell import gitlint
|
||||
from qa.base import BaseTestCase
|
||||
from qa.utils import sstr
|
||||
from qa.utils import sstr, ustr
|
||||
|
||||
|
||||
class ConfigTests(BaseTestCase):
|
||||
|
@ -52,7 +55,7 @@ class ConfigTests(BaseTestCase):
|
|||
self.assertEqualStdout(output, self.get_expected("test_config/test_config_from_file_1"))
|
||||
|
||||
def test_config_from_file_debug(self):
|
||||
# Test bot on existing and new repo (we've had a bug in the past that was unique to empty repos)
|
||||
# Test both on existing and new repo (we've had a bug in the past that was unique to empty repos)
|
||||
repos = [self.tmp_git_repo, self.create_tmp_git_repo()]
|
||||
for target_repo in repos:
|
||||
commit_msg = u"WIP: Thïs is a title thåt is a bit longer.\nContent on the second line\n" + \
|
||||
|
@ -65,3 +68,39 @@ class ConfigTests(BaseTestCase):
|
|||
expected_kwargs.update({'config_path': config_path, 'changed_files': sstr([filename])})
|
||||
self.assertEqualStdout(output, self.get_expected("test_config/test_config_from_file_debug_1",
|
||||
expected_kwargs))
|
||||
|
||||
def test_config_from_env(self):
|
||||
""" Test for configuring gitlint from environment variables """
|
||||
|
||||
# We invoke gitlint, configuring it via env variables, we can check whether gitlint picks these up correctly
|
||||
# by comparing the debug output with what we'd expect
|
||||
target_repo = self.create_tmp_git_repo()
|
||||
commit_msg = u"WIP: Thïs is a title thåt is a bit longer.\nContent on the second line\n" + \
|
||||
"This line of the body is here because we need it"
|
||||
filename = self.create_simple_commit(commit_msg, git_repo=target_repo)
|
||||
env = self.create_environment({"GITLINT_DEBUG": "1", "GITLINT_VERBOSITY": "2",
|
||||
"GITLINT_IGNORE": "T1,T2", "GITLINT_CONTRIB": "CC1,CT1",
|
||||
"GITLINT_IGNORE_STDIN": "1", "GITLINT_TARGET": target_repo,
|
||||
"GITLINT_COMMITS": self.get_last_commit_hash(git_repo=target_repo)})
|
||||
output = gitlint(_env=env, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[5])
|
||||
expected_kwargs = self.get_debug_vars_last_commit(git_repo=target_repo)
|
||||
expected_kwargs.update({'changed_files': sstr([filename])})
|
||||
|
||||
self.assertEqualStdout(output, self.get_expected("test_config/test_config_from_env_1", expected_kwargs))
|
||||
|
||||
# For some env variables, we need a separate test ast they are mutually exclusive with the ones tested above
|
||||
tmp_commit_msg_file = self.create_tmpfile(u"WIP: msg-fïlename test.")
|
||||
env = self.create_environment({"GITLINT_DEBUG": "1", "GITLINT_TARGET": target_repo,
|
||||
"GITLINT_SILENT": "1", "GITLINT_STAGED": "1"})
|
||||
|
||||
output = gitlint("--msg-filename", tmp_commit_msg_file,
|
||||
_env=env, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[3])
|
||||
|
||||
# Extract date from actual output to insert it into the expected output
|
||||
# We have to do this since there's no way for us to deterministically know that date otherwise
|
||||
p = re.compile("Date: (.*)\n", re.UNICODE | re.MULTILINE)
|
||||
result = p.search(ustr(output.stdout))
|
||||
date = result.group(1).strip()
|
||||
expected_kwargs.update({"date": date})
|
||||
|
||||
self.assertEqualStdout(output, self.get_expected("test_config/test_config_from_env_2", expected_kwargs))
|
||||
|
|
|
@ -157,6 +157,28 @@ class IntegrationTests(BaseTestCase):
|
|||
|
||||
self.assertEqualStdout(output, self.get_expected("test_gitlint/test_msg_filename_no_tty_1"))
|
||||
|
||||
def test_no_git_name_set(self):
|
||||
""" Ensure we print out a helpful message if user.name is not set """
|
||||
tmp_commit_msg_file = self.create_tmpfile(u"WIP: msg-fïlename NO name test.")
|
||||
# Name is checked before email so this isn't strictly
|
||||
# necessary but seems good for consistency.
|
||||
env = self.create_tmp_git_config(u"[user]\n email = test-emåil@foo.com\n")
|
||||
output = gitlint("--staged", "--msg-filename", tmp_commit_msg_file,
|
||||
_ok_code=[self.GIT_CONTEXT_ERROR_CODE],
|
||||
_env=env)
|
||||
expected = u"Missing git configuration: please set user.name\n"
|
||||
self.assertEqualStdout(output, expected)
|
||||
|
||||
def test_no_git_email_set(self):
|
||||
""" Ensure we print out a helpful message if user.email is not set """
|
||||
tmp_commit_msg_file = self.create_tmpfile(u"WIP: msg-fïlename NO email test.")
|
||||
env = self.create_tmp_git_config(u"[user]\n name = test åuthor\n")
|
||||
output = gitlint("--staged", "--msg-filename", tmp_commit_msg_file,
|
||||
_ok_code=[self.GIT_CONTEXT_ERROR_CODE],
|
||||
_env=env)
|
||||
expected = u"Missing git configuration: please set user.email\n"
|
||||
self.assertEqualStdout(output, expected)
|
||||
|
||||
def test_git_errors(self):
|
||||
# Repo has no commits: caused by `git log`
|
||||
empty_git_repo = self.create_tmp_git_repo()
|
||||
|
|
|
@ -53,6 +53,18 @@ class HookTests(BaseTestCase):
|
|||
stdin.put("{0}\n".format(response))
|
||||
self.response_index = (self.response_index + 1) % len(self.responses)
|
||||
|
||||
def test_commit_hook_no_violations(self):
|
||||
test_filename = self.create_simple_commit(u"This ïs a title\n\nBody contënt that should work",
|
||||
out=self._interact, tty_in=True)
|
||||
|
||||
short_hash = self.get_last_commit_short_hash()
|
||||
expected_output = ["gitlint: checking commit message...\n",
|
||||
"gitlint: \x1b[32mOK\x1b[0m (no violations in commit message)\n",
|
||||
u"[master %s] This ïs a title\n" % short_hash,
|
||||
" 1 file changed, 0 insertions(+), 0 deletions(-)\n",
|
||||
u" create mode 100644 %s\n" % test_filename]
|
||||
self.assertListEqual(expected_output, self.githook_output)
|
||||
|
||||
def test_commit_hook_continue(self):
|
||||
self.responses = ["y"]
|
||||
test_filename = self.create_simple_commit(u"WIP: This ïs a title.\nContënt on the second line",
|
||||
|
|
23
qa/test_named_rules.py
Normal file
23
qa/test_named_rules.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from qa.shell import gitlint
|
||||
from qa.base import BaseTestCase
|
||||
|
||||
|
||||
class NamedRuleTests(BaseTestCase):
|
||||
""" Integration tests for named rules."""
|
||||
|
||||
def test_named_rule(self):
|
||||
commit_msg = u"WIP: thåt dûr bår\n\nSïmple commit body"
|
||||
self.create_simple_commit(commit_msg)
|
||||
config_path = self.get_sample_path("config/named-rules")
|
||||
output = gitlint("--config", config_path, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[5])
|
||||
self.assertEqualStdout(output, self.get_expected("test_named_rules/test_named_rule_1"))
|
||||
|
||||
def test_named_user_rule(self):
|
||||
commit_msg = u"Normal cömmit title\n\nSïmple commit message body"
|
||||
self.create_simple_commit(commit_msg)
|
||||
config_path = self.get_sample_path("config/named-user-rules")
|
||||
extra_path = self.get_sample_path("user_rules/extra")
|
||||
output = gitlint("--extra-path", extra_path, "--config", config_path, _cwd=self.tmp_git_repo, _tty_in=True,
|
||||
_ok_code=[9])
|
||||
self.assertEqualStdout(output, self.get_expected("test_named_rules/test_named_user_rule_1"))
|
|
@ -7,14 +7,24 @@ from qa.base import BaseTestCase
|
|||
class UserDefinedRuleTests(BaseTestCase):
|
||||
""" Integration tests for user-defined rules."""
|
||||
|
||||
def test_user_defined_rules_examples(self):
|
||||
def test_user_defined_rules_examples1(self):
|
||||
""" Test the user defined rules in the top-level `examples/` directory """
|
||||
extra_path = self.get_example_path()
|
||||
commit_msg = u"WIP: Thi$ is å title\nContent on the second line"
|
||||
self.create_simple_commit(commit_msg)
|
||||
output = gitlint("--extra-path", extra_path, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[5])
|
||||
self.assertEqualStdout(output, self.get_expected("test_user_defined/test_user_defined_rules_examples_1"))
|
||||
|
||||
def test_user_defined_rules_examples2(self):
|
||||
""" Test the user defined rules in the top-level `examples/` directory """
|
||||
extra_path = self.get_example_path()
|
||||
commit_msg = u"Release: Thi$ is å title\nContent on the second line\n$This line is ignored \nThis isn't\t\n"
|
||||
self.create_simple_commit(commit_msg)
|
||||
output = gitlint("--extra-path", extra_path, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[4])
|
||||
self.assertEqualStdout(output, self.get_expected("test_user_defined/test_user_defined_rules_examples_2"))
|
||||
|
||||
def test_user_defined_rules_examples_with_config(self):
|
||||
""" Test the user defined rules in the top-level `examples/` directory """
|
||||
extra_path = self.get_example_path()
|
||||
commit_msg = u"WIP: Thi$ is å title\nContent on the second line"
|
||||
self.create_simple_commit(commit_msg)
|
||||
|
@ -27,8 +37,9 @@ class UserDefinedRuleTests(BaseTestCase):
|
|||
extra_path = self.get_sample_path("user_rules/extra")
|
||||
commit_msg = u"WIP: Thi$ is å title\nContent on the second line"
|
||||
self.create_simple_commit(commit_msg)
|
||||
output = gitlint("--extra-path", extra_path, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[5])
|
||||
self.assertEqualStdout(output, self.get_expected("test_user_defined/test_user_defined_rules_extra_1"))
|
||||
output = gitlint("--extra-path", extra_path, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[9])
|
||||
self.assertEqualStdout(output, self.get_expected("test_user_defined/test_user_defined_rules_extra_1",
|
||||
{'repo-path': self.tmp_git_repo}))
|
||||
|
||||
def test_invalid_user_defined_rules(self):
|
||||
extra_path = self.get_sample_path("user_rules/incorrect_linerule")
|
||||
|
|
18
qa/utils.py
18
qa/utils.py
|
@ -15,6 +15,16 @@ def platform_is_windows():
|
|||
|
||||
PLATFORM_IS_WINDOWS = platform_is_windows()
|
||||
|
||||
########################################################################################################################
|
||||
# IS_PY2
|
||||
|
||||
|
||||
def is_py2():
|
||||
return sys.version_info[0] == 2
|
||||
|
||||
|
||||
IS_PY2 = is_py2()
|
||||
|
||||
########################################################################################################################
|
||||
# USE_SH_LIB
|
||||
# Determine whether to use the `sh` library
|
||||
|
@ -68,7 +78,7 @@ DEFAULT_ENCODING = getpreferredencoding()
|
|||
|
||||
def ustr(obj):
|
||||
""" Python 2 and 3 utility method that converts an obj to unicode in python 2 and to a str object in python 3"""
|
||||
if sys.version_info[0] == 2:
|
||||
if IS_PY2:
|
||||
# If we are getting a string, then do an explicit decode
|
||||
# else, just call the unicode method of the object
|
||||
if type(obj) in [str, basestring]: # pragma: no cover # noqa
|
||||
|
@ -86,11 +96,13 @@ def sstr(obj):
|
|||
""" Python 2 and 3 utility method that converts an obj to a DEFAULT_ENCODING encoded string in python 2
|
||||
and to unicode in python 3.
|
||||
Especially useful for implementing __str__ methods in python 2: http://stackoverflow.com/a/1307210/381010"""
|
||||
if sys.version_info[0] == 2:
|
||||
# For lists in python2, remove unicode string representation characters.
|
||||
if IS_PY2:
|
||||
# For lists and tuples in python2, remove unicode string representation characters.
|
||||
# i.e. ensure lists are printed as ['a', 'b'] and not [u'a', u'b']
|
||||
if type(obj) in [list]:
|
||||
return [sstr(item) for item in obj] # pragma: no cover # noqa
|
||||
elif type(obj) in [tuple]:
|
||||
return tuple(sstr(item) for item in obj) # pragma: no cover # noqa
|
||||
|
||||
return unicode(obj).encode(DEFAULT_ENCODING) # pragma: no cover # noqa
|
||||
else:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue