summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/user_defined_rules.md2
-rw-r--r--gitlint/git.py21
-rw-r--r--gitlint/tests/test_cli.py2
-rw-r--r--gitlint/tests/test_git.py18
-rw-r--r--qa/expected/debug_output12
-rw-r--r--requirements.txt1
-rw-r--r--setup.py1
7 files changed, 39 insertions, 8 deletions
diff --git a/docs/user_defined_rules.md b/docs/user_defined_rules.md
index 1630104..6a142e7 100644
--- a/docs/user_defined_rules.md
+++ b/docs/user_defined_rules.md
@@ -169,7 +169,7 @@ commit.message.title | string | Title/subject of the commit message:
commit.message.body | list of string | List of lines in the body of the commit message (i.e. starting from the second line)
commit.author_name | string | Name of the author, result of ```git log --pretty=%aN```
commit.author_email | string | Email of the author, result of ```git log --pretty=%aE```
-commit.date | string | TODO: parse to date obj
+commit.date | datetime | Python ```datetime``` object representing the time of commit
commit.context | object | Object pointing to the bigger git context that the commit is part of
commit.context.commits | list of commit | List of commits in the git context. Note that this might only be the subset of commits that gitlint is acting on, not all commits in the repo.
diff --git a/gitlint/git.py b/gitlint/git.py
index 923d6c3..a0de1b8 100644
--- a/gitlint/git.py
+++ b/gitlint/git.py
@@ -1,3 +1,4 @@
+import arrow
import sh
# import exceptions separately, this makes it a little easier to mock them out in the unit tests
from sh import CommandNotFound, ErrorReturnCode
@@ -37,6 +38,10 @@ class GitCommitMessage(object):
def __repr__(self):
return self.__str__() # pragma: no cover
+ def __eq__(self, other):
+ return self.original == other.original and self.full == other.full and \
+ self.title == other.title and self.body == other.body # noqa
+
class GitCommit(object):
""" Class representing a git commit.
@@ -72,6 +77,11 @@ class GitCommit(object):
def __repr__(self):
return self.__str__() # pragma: no cover
+ def __eq__(self, other):
+ # skip checking the context as context refers back to this obj, this will trigger a cyclic dependency
+ return self.message == other.message and self.author_name == other.author_name and \
+ self.author_email == other.autor_email and self.date == other.date # noqa
+
class GitContext(object):
""" Class representing the git context in which gitlint is operating: a data object storing information about
@@ -114,7 +124,8 @@ class GitContext(object):
commit_msg = sh.git.log("-1", "--pretty=%B", **sh_special_args)
commit_author_name = sh.git.log("-1", "--pretty=%aN", **sh_special_args)
commit_author_email = sh.git.log("-1", "--pretty=%aE", **sh_special_args)
- commit_date = sh.git.log("-1", "--pretty=%aD", **sh_special_args)
+ # %aI -> ISO 8601-like format, while %aI is strict ISO 8601, it seems to be less widely supporte
+ commit_date_str = sh.git.log("-1", "--pretty=%ai", **sh_special_args)
commit_parents = sh.git.log("-1", "--pretty=%P", **sh_special_args).split(" ")
commit_is_merge_commit = len(commit_parents) > 1
@@ -132,6 +143,11 @@ class GitContext(object):
error_msg = "An error occurred while executing '{0}': {1}".format(e.full_cmd, error_msg)
raise GitContextError(error_msg)
+ # "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(str(commit_date_str), "YYYY-MM-DD HH:mm:ss Z").datetime
+
# Create Git commit object with the retrieved info
changed_files = [changed_file for changed_file in changed_files_str.strip().split("\n")]
commit_msg_obj = GitCommitMessage.from_full_message(commit_msg)
@@ -143,3 +159,6 @@ class GitContext(object):
context.commits.append(commit)
return context
+
+ def __eq__(self, other):
+ return self.commits == other.commits
diff --git a/gitlint/tests/test_cli.py b/gitlint/tests/test_cli.py
index 20f15c4..bff7bf1 100644
--- a/gitlint/tests/test_cli.py
+++ b/gitlint/tests/test_cli.py
@@ -37,7 +37,7 @@ class CLITests(BaseTestCase):
def git_log_side_effect(*args, **_kwargs):
return_values = {'--pretty=%B': "commit-title\n\ncommit-body", '--pretty=%aN': "test author",
- '--pretty=%aE': "test-email@foo.com", '--pretty=%aD': "Mon Feb 29 22:19:39 2016 +0100",
+ '--pretty=%aE': "test-email@foo.com", '--pretty=%ai': "2016-12-03 15:28:15 01:00",
'--pretty=%P': "abc"}
return return_values[args[1]]
diff --git a/gitlint/tests/test_git.py b/gitlint/tests/test_git.py
index 91062ff..ab0a68d 100644
--- a/gitlint/tests/test_git.py
+++ b/gitlint/tests/test_git.py
@@ -1,3 +1,5 @@
+import datetime
+import dateutil
from mock import patch, call
from sh import ErrorReturnCode, CommandNotFound
@@ -10,7 +12,7 @@ class GitTests(BaseTestCase):
def test_get_latest_commit(self, sh):
def git_log_side_effect(*args, **_kwargs):
return_values = {'--pretty=%B': "commit-title\n\ncommit-body", '--pretty=%aN': "test author",
- '--pretty=%aE': "test-email@foo.com", '--pretty=%aD': "Mon Feb 29 22:19:39 2016 +0100",
+ '--pretty=%aE': "test-email@foo.com", '--pretty=%ai': "2016-12-03 15:28:15 01:00",
'--pretty=%P': "abc"}
return return_values[args[1]]
@@ -26,7 +28,7 @@ class GitTests(BaseTestCase):
expected_calls = [call('-1', '--pretty=%B', _cwd='fake/path', _tty_out=False),
call('-1', '--pretty=%aN', _cwd='fake/path', _tty_out=False),
call('-1', '--pretty=%aE', _cwd='fake/path', _tty_out=False),
- call('-1', '--pretty=%aD', _cwd='fake/path', _tty_out=False),
+ call('-1', '--pretty=%ai', _cwd='fake/path', _tty_out=False),
call('-1', '--pretty=%P', _cwd='fake/path', _tty_out=False)]
self.assertListEqual(sh.git.log.mock_calls, expected_calls)
@@ -36,6 +38,8 @@ class GitTests(BaseTestCase):
self.assertEqual(last_commit.message.body, ["", "commit-body"])
self.assertEqual(last_commit.author_name, "test author")
self.assertEqual(last_commit.author_email, "test-email@foo.com")
+ self.assertEqual(last_commit.date, datetime.datetime(2016, 12, 3, 15, 28, 15,
+ tzinfo=dateutil.tz.tzoffset("+0100", 3600)))
self.assertListEqual(last_commit.parents, ["abc"])
self.assertFalse(last_commit.is_merge_commit)
@@ -48,7 +52,7 @@ class GitTests(BaseTestCase):
def test_get_latest_commit_merge_commit(self, sh):
def git_log_side_effect(*args, **_kwargs):
return_values = {'--pretty=%B': "Merge \"foo bar commit\"", '--pretty=%aN': "test author",
- '--pretty=%aE': "test-email@foo.com", '--pretty=%aD': "Mon Feb 29 22:19:39 2016 +0100",
+ '--pretty=%aE': "test-email@foo.com", '--pretty=%ai': "2016-12-03 15:28:15 01:00",
'--pretty=%P': "abc def"}
return return_values[args[1]]
@@ -64,7 +68,7 @@ class GitTests(BaseTestCase):
expected_calls = [call('-1', '--pretty=%B', _cwd='fake/path', _tty_out=False),
call('-1', '--pretty=%aN', _cwd='fake/path', _tty_out=False),
call('-1', '--pretty=%aE', _cwd='fake/path', _tty_out=False),
- call('-1', '--pretty=%aD', _cwd='fake/path', _tty_out=False),
+ call('-1', '--pretty=%ai', _cwd='fake/path', _tty_out=False),
call('-1', '--pretty=%P', _cwd='fake/path', _tty_out=False)]
self.assertListEqual(sh.git.log.mock_calls, expected_calls)
@@ -74,6 +78,8 @@ class GitTests(BaseTestCase):
self.assertEqual(last_commit.message.body, [])
self.assertEqual(last_commit.author_name, "test author")
self.assertEqual(last_commit.author_email, "test-email@foo.com")
+ self.assertEqual(last_commit.date, datetime.datetime(2016, 12, 3, 15, 28, 15,
+ tzinfo=dateutil.tz.tzoffset("+0100", 3600)))
self.assertListEqual(last_commit.parents, ["abc", "def"])
self.assertTrue(last_commit.is_merge_commit)
@@ -134,6 +140,7 @@ class GitTests(BaseTestCase):
self.assertEqual(gitcontext.commits[-1].message.original, expected_original)
self.assertEqual(gitcontext.commits[-1].author_name, None)
self.assertEqual(gitcontext.commits[-1].author_email, None)
+ self.assertEqual(gitcontext.commits[-1].date, None)
self.assertListEqual(gitcontext.commits[-1].parents, [])
self.assertFalse(gitcontext.commits[-1].is_merge_commit)
self.assertEqual(len(gitcontext.commits), 1)
@@ -160,6 +167,7 @@ class GitTests(BaseTestCase):
self.assertEqual(gitcontext.commits[-1].message.original, "")
self.assertEqual(gitcontext.commits[-1].author_name, None)
self.assertEqual(gitcontext.commits[-1].author_email, None)
+ self.assertEqual(gitcontext.commits[-1].date, None)
self.assertListEqual(gitcontext.commits[-1].parents, [])
self.assertFalse(gitcontext.commits[-1].is_merge_commit)
self.assertEqual(len(gitcontext.commits), 1)
@@ -173,6 +181,7 @@ class GitTests(BaseTestCase):
self.assertEqual(gitcontext.commits[-1].message.original, "Title\n\nBody 1\n#Comment\nBody 2")
self.assertEqual(gitcontext.commits[-1].author_name, None)
self.assertEqual(gitcontext.commits[-1].author_email, None)
+ self.assertEqual(gitcontext.commits[-1].date, None)
self.assertListEqual(gitcontext.commits[-1].parents, [])
self.assertFalse(gitcontext.commits[-1].is_merge_commit)
self.assertEqual(len(gitcontext.commits), 1)
@@ -187,6 +196,7 @@ class GitTests(BaseTestCase):
self.assertEqual(gitcontext.commits[-1].message.original, commit_msg)
self.assertEqual(gitcontext.commits[-1].author_name, None)
self.assertEqual(gitcontext.commits[-1].author_email, None)
+ self.assertEqual(gitcontext.commits[-1].date, None)
self.assertListEqual(gitcontext.commits[-1].parents, [])
self.assertTrue(gitcontext.commits[-1].is_merge_commit)
self.assertEqual(len(gitcontext.commits), 1)
diff --git a/qa/expected/debug_output1 b/qa/expected/debug_output1
index e9ac180..1867b4e 100644
--- a/qa/expected/debug_output1
+++ b/qa/expected/debug_output1
@@ -1,5 +1,5 @@
[GENERAL]
-config path: /vagrant/qa/samples/config/gitlintconfig
+config path: {config_path}
extra path: None
ignore merge commits: True
verbosity: 2
diff --git a/requirements.txt b/requirements.txt
index 830b530..df05267 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,5 +2,6 @@ setuptools
wheel==0.24.0
Click==6.6
sh==1.11
+arrow==0.10.0
ordereddict==1.1
importlib==1.0.3; python_version < '2.7' \ No newline at end of file
diff --git a/setup.py b/setup.py
index 76c6b7a..1451d80 100644
--- a/setup.py
+++ b/setup.py
@@ -59,6 +59,7 @@ setup(
install_requires=[
'Click==6.6',
'sh==1.11',
+ 'arrow==0.10.0',
'ordereddict==1.1',
],
extras_require={