Merge ~cjwatson/turnip:log-by-date into turnip:master

Proposed by Colin Watson
Status: Needs review
Proposed branch: ~cjwatson/turnip:log-by-date
Merge into: turnip:master
Diff against target: 118 lines (+29/-3)
4 files modified
requirements.txt (+1/-0)
setup.py (+1/-0)
turnip/api/store.py (+16/-2)
turnip/api/views.py (+11/-1)
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+295544@code.launchpad.net

Commit message

Add start_time and end_time parameters to log API

This is useful for bounding the set of commits returned in cases where
we may not have a reliable stop commit.

Description of the change

When I was integrating git commits into Launchpad's merge proposal conversations, I initially thought about filtering by date on the turnip side, but ended up doing that on the Launchpad side instead since it was simpler. However, it can apparently happen that our idea of the stop commit isn't in the source repository, in which case we need a different way to bound the set of commits returned by turnip's log API.

I think the OOPSes I've seen are mainly a bug in Launchpad: we need to be requesting cross-repository diffs in a better way, and I'll work on that separately. Still, it doesn't hurt to attack this from multiple fronts.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)
Revision history for this message
William Grant (wgrant) :

Unmerged commits

ee4cd2f... by Colin Watson

Add start_time and end_time parameters to log API

This is useful for bounding the set of commits returned in cases where
we may not have a reliable stop commit.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/requirements.txt b/requirements.txt
2index eafd823..cc6dcf9 100644
3--- a/requirements.txt
4+++ b/requirements.txt
5@@ -27,6 +27,7 @@ python-mimeparse==0.1.4
6 # See lp:~deryck/python-openid/python-openid-fix1034376 which
7 # reapplied a patch from wgrant to get codehosting going again.
8 python-openid==2.2.5-fix1034376
9+pytz==2014.10
10 PyYAML==3.11
11 repoze.lru==0.6
12 simplejson==3.6.5
13diff --git a/setup.py b/setup.py
14index be53437..cbcfb1f 100755
15--- a/setup.py
16+++ b/setup.py
17@@ -25,6 +25,7 @@ requires = [
18 'pygit2>=0.22.1,<0.23.0',
19 'python-openid',
20 'PyYAML',
21+ 'pytz',
22 'Twisted',
23 'waitress',
24 'zope.interface',
25diff --git a/turnip/api/store.py b/turnip/api/store.py
26index 1291c13..0b08fa9 100644
27--- a/turnip/api/store.py
28+++ b/turnip/api/store.py
29@@ -6,6 +6,7 @@ from contextlib2 import (
30 contextmanager,
31 ExitStack,
32 )
33+from datetime import datetime
34 import itertools
35 import os
36 import re
37@@ -25,6 +26,7 @@ from pygit2 import (
38 Oid,
39 Repository,
40 )
41+import pytz
42
43 from turnip.pack.helpers import ensure_config
44
45@@ -397,12 +399,15 @@ def get_diff(repo_store, repo_name, sha1_from, sha1_to, context_lines=3):
46 return diff
47
48
49-def get_log(repo_store, repo_name, start=None, limit=None, stop=None):
50+def get_log(repo_store, repo_name, start=None, limit=None, stop=None,
51+ start_time=None, end_time=None):
52 """Return a commit collection from HEAD or optionally a start oid.
53
54 :param start: sha1 or branch to start listing commits from.
55 :param limit: limit number of commits to return.
56 :param stop: ignore a commit (and its ancestors).
57+ :param start_time: ignore commits before this time (and their ancestors).
58+ :param end_time: ignore commits after this time.
59 """
60 with open_repo(repo_store, repo_name) as repo:
61 if not start:
62@@ -412,7 +417,16 @@ def get_log(repo_store, repo_name, start=None, limit=None, stop=None):
63 walker.hide(stop) # filter stop sha1 and its ancestors
64 if limit > 0:
65 walker = itertools.islice(walker, limit)
66- return [format_commit(commit) for commit in walker]
67+ for commit in walker:
68+ if start_time is not None or end_time is not None:
69+ commit_time = datetime.fromtimestamp(
70+ commit.committer.time, tz=pytz.UTC)
71+ if start_time is not None and commit_time < start_time:
72+ walker.hide(commit)
73+ continue
74+ if end_time is not None and commit_time > end_time:
75+ continue
76+ yield format_commit(commit)
77
78
79 def get_commit(repo_store, repo_name, revision, repo=None):
80diff --git a/turnip/api/views.py b/turnip/api/views.py
81index abdfaca..6e6c413 100644
82--- a/turnip/api/views.py
83+++ b/turnip/api/views.py
84@@ -1,6 +1,7 @@
85 # Copyright 2015 Canonical Ltd. This software is licensed under the
86 # GNU Affero General Public License version 3 (see the file LICENSE).
87
88+from datetime import datetime
89 import os
90 import re
91 from subprocess import CalledProcessError
92@@ -9,6 +10,7 @@ from cornice.resource import resource
93 from cornice.util import extract_json_data
94 from pygit2 import GitError
95 import pyramid.httpexceptions as exc
96+import pytz
97
98 from turnip.config import TurnipConfig
99 from turnip.api import store
100@@ -285,9 +287,17 @@ class LogAPI(BaseAPI):
101 sha1 = self.request.matchdict['sha1']
102 limit = int(self.request.params.get('limit', -1))
103 stop = self.request.params.get('stop')
104+ start_time = self.request.params.get('start_time')
105+ if start_time is not None:
106+ start_time = datetime.fromtimestamp(start_time, tz=pytz.UTC)
107+ end_time = self.request.params.get('end_time')
108+ if end_time is not None:
109+ end_time = datetime.fromtimestamp(end_time, tz=pytz.UTC)
110
111 try:
112- log = store.get_log(repo_store, repo_name, sha1, limit, stop)
113+ log = list(store.get_log(
114+ repo_store, repo_name, start=sha1, limit=limit, stop=stop,
115+ start_time=start_time, end_time=end_time))
116 except GitError:
117 return exc.HTTPNotFound()
118 return log

Subscribers

People subscribed via source and target branches