summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoris Roovers <jroovers@cisco.com>2016-12-03 17:48:26 +0100
committerJoris Roovers <jroovers@cisco.com>2016-12-03 17:48:26 +0100
commit2d323a9efcc9abda70316282545d5e505a83c1ac (patch)
tree3f0667d00e8f918faa61cb95a1af47b7dcc1e1dd
parentdc24b5f2d10928fec5d87c8c2b3cd7daf6bcca57 (diff)
Commit dates are now proper datetime objects
Previously, commit date objects were just represented by the string returned by git. Now, commit.date is an actual python datetime object. This did require us to include the arrow package as a dependency as there are some issue with timezone-aware date parsing in python. Also added __eq__ methods for GitCommit and GitCommitMessage as that allows for easy comparison.
-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={