Merge lp:~pauljnixon/loggerhead/more_columns into lp:loggerhead

Proposed by Paul Nixon
Status: Merged
Approved by: Steve Kowalik
Approved revision: 478
Merged at revision: 494
Proposed branch: lp:~pauljnixon/loggerhead/more_columns
Merge into: lp:loggerhead
Diff against target: 386 lines (+97/-50)
9 files modified
loggerhead/apps/branch.py (+15/-0)
loggerhead/controllers/directory_ui.py (+6/-6)
loggerhead/controllers/inventory_ui.py (+22/-9)
loggerhead/history.py (+1/-0)
loggerhead/static/css/global.css (+2/-2)
loggerhead/static/css/view.css (+1/-2)
loggerhead/templates/directory.pt (+12/-13)
loggerhead/templates/inventory.pt (+25/-12)
loggerhead/util.py (+13/-6)
To merge this branch: bzr merge lp:~pauljnixon/loggerhead/more_columns
Reviewer Review Type Date Requested Status
Colin Watson (community) Needs Information
Paul Nixon (community) Abstain
Steve Kowalik (community) code Approve
Review via email: mp+118188@code.launchpad.net

This proposal supersedes a proposal from 2012-07-24.

Description of the change

Added "committer" and "comment" columns to Files and Inventory views.

Before: http://i.imgur.com/hQtr7.jpg
After: http://i.imgur.com/HishN.jpg

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote : Posted in a previous version of this proposal

Broadly, this looks good, but I have a few concerns. Firstly, comments should be formatted with a space after the hash, and secondly must be complete sentences. You have added some unneeded whitespace on line 29-30 of the diff. And lastly, since this branch does make some UI changes, I'd like to see at least one screenshot of the before and after view.

review: Needs Fixing (code)
Revision history for this message
Paul Nixon (pauljnixon) wrote : Posted in a previous version of this proposal
Revision history for this message
Paul Nixon (pauljnixon) wrote : Posted in a previous version of this proposal

Does this need anything else?

Revision history for this message
Steve Kowalik (stevenk) wrote :

90 + # determine the last time something in the folder was changed

You missed one. :-)

Thanks for addressing my comments and posting screenshots -- this looks excellent, and I look forward to it landing.

review: Approve (code)
Revision history for this message
Paul Nixon (pauljnixon) wrote :

Abstaining from a review of my own code, which is already approved anyway. I invited myself to review accidentally.

review: Abstain
Revision history for this message
Colin Watson (cjwatson) wrote :

Sorry this has taken so long to land; I'm going through some old loggerhead merge proposals now. I was about to merge this since it's approved, but I thought the change to the _approximatedate function seemed odd, and possibly unintentional. Was there a reason you removed support for dates in the future from this? I think they can occur if the committer's clock is wrong, and in any case it shouldn't hurt to retain support for them.

review: Needs Information
Revision history for this message
Paul Nixon (pauljnixon) wrote :

Hello Colin:

Good point, I think I hadn't considered the possibility of incorrect
clocks. I'd like to keep the addition of months and years, though.

Thank you,
---Paul
Review: Needs Information

Sorry this has taken so long to land; I'm going through some old loggerhead
merge proposals now. I was about to merge this since it's approved, but I
thought the change to the _approximatedate function seemed odd, and
possibly unintentional. Was there a reason you removed support for dates
in the future from this? I think they can occur if the committer's clock
is wrong, and in any case it shouldn't hurt to retain support for them.
--
https://code.launchpad.net/~pauljnixon/loggerhead/more_columns/+merge/118188
You are the owner of lp:~pauljnixon/loggerhead/more_columns.

Revision history for this message
Colin Watson (cjwatson) wrote :

Sure, adding months and years makes sense in this context, I think. Can you push an adjustment, then, and I can get this merged for you?

479. By Paul Nixon

Re-added support for future dates in _approximatedate.

Revision history for this message
Paul Nixon (pauljnixon) wrote :

Hello Colin:

I've added support for future dates and pushed to
lp:~pauljnixon/loggerhead/more_columns . I'm sorry this took so long:
I no longer have access to the test environment that I originally
developed this on, so I had a bit of setup to do before I could start
working on this again.

Should I create a new merge request for the modifications, or resubmit
the old one somehow?

Thank you,
---Paul

On Tue, Mar 17, 2015 at 11:42 AM, Colin Watson <email address hidden> wrote:
> Sure, adding months and years makes sense in this context, I think. Can you push an adjustment, then, and I can get this merged for you?
> --
> https://code.launchpad.net/~pauljnixon/loggerhead/more_columns/+merge/118188
> You are the owner of lp:~pauljnixon/loggerhead/more_columns.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'loggerhead/apps/branch.py'
2--- loggerhead/apps/branch.py 2012-02-08 01:50:02 +0000
3+++ loggerhead/apps/branch.py 2015-05-31 16:20:47 +0000
4@@ -93,6 +93,20 @@
5 return History(
6 self.branch, self.graph_cache,
7 revinfo_disk_cache=revinfo_disk_cache, cache_key=self.friendly_name)
8+
9+ # Before the addition of this method, clicking to sort by date from
10+ # within a branch caused a jump up to the top of that branch.
11+ def sort_url(self, *args, **kw):
12+ if isinstance(args[0], list):
13+ args = args[0]
14+ qs = []
15+ for k, v in kw.iteritems():
16+ if v is not None:
17+ qs.append('%s=%s' % (k, urllib.quote(v)))
18+ qs = '&'.join(qs)
19+ path_info = self._path_info.strip('/').split('?')[0]
20+ path_info += '?' + qs
21+ return self._url_base + '/' + path_info
22
23 def url(self, *args, **kw):
24 if isinstance(args[0], list):
25@@ -155,6 +169,7 @@
26 if self.branch.get_config().get_user_option('http_serve') == 'False':
27 raise httpexceptions.HTTPNotFound()
28 self._url_base = environ['SCRIPT_NAME']
29+ self._path_info = environ['PATH_INFO']
30 self._static_url_base = environ.get('loggerhead.static.url')
31 if self._static_url_base is None:
32 self._static_url_base = self._url_base
33
34=== modified file 'loggerhead/controllers/directory_ui.py'
35--- loggerhead/controllers/directory_ui.py 2012-02-08 01:50:02 +0000
36+++ loggerhead/controllers/directory_ui.py 2015-05-31 16:20:47 +0000
37@@ -19,6 +19,7 @@
38 import datetime
39 import logging
40 import stat
41+import urllib
42
43 from bzrlib import branch, errors
44
45@@ -29,18 +30,17 @@
46 class DirEntry(object):
47
48 def __init__(self, dirname, parity, branch):
49- self.dirname = dirname
50+ self.dirname = urllib.unquote(dirname)
51 self.parity = parity
52 self.branch = branch
53 if branch is not None:
54 # If a branch is empty, bzr raises an exception when trying this
55 try:
56- self.last_change = datetime.datetime.utcfromtimestamp(
57- branch.repository.get_revision(
58- branch.last_revision()).timestamp)
59+ self.last_revision = branch.repository.get_revision(branch.last_revision())
60+ self.last_change_time = datetime.datetime.utcfromtimestamp(self.last_revision.timestamp)
61 except:
62- self.last_change = None
63-
64+ self.last_revision = None
65+ self.last_change_time = None
66
67 class DirectoryUI(TemplatedBranchView):
68 """
69
70=== modified file 'loggerhead/controllers/inventory_ui.py'
71--- loggerhead/controllers/inventory_ui.py 2013-03-27 05:29:14 +0000
72+++ loggerhead/controllers/inventory_ui.py 2015-05-31 16:20:47 +0000
73@@ -70,15 +70,27 @@
74 change_dict[change.revid] = change
75
76 for filename, entry in dir_ie.children.iteritems():
77+ revid = entry.revision
78+ file_timestamp = change_dict[revid].timestamp
79 pathname = filename
80- if entry.kind == 'directory':
81- pathname += '/'
82+ contents_changed_rev = None
83 if path == '':
84 absolutepath = pathname
85 else:
86 absolutepath = path + '/' + pathname
87- revid = entry.revision
88-
89+ if entry.kind == 'directory':
90+ # determine the last time something in the folder was changed
91+ pathname += '/'
92+ sub_dir_id = inv.path2id(absolutepath)
93+ sub_dir_ie = inv[sub_dir_id]
94+ sub_revid_set = set()
95+ for sub_filename, sub_entry in sub_dir_ie.children.iteritems():
96+ sub_revid_set.add(sub_entry.revision)
97+ for change in self._history.get_changes(list(sub_revid_set)):
98+ change_dict[change.revid] = change
99+ if(change.timestamp > file_timestamp):
100+ revid = change.revid
101+ file_timestamp = change.timestamp
102 # TODO: For the JSON rendering, this inlines the "change" aka
103 # revision information attached to each file. Consider either
104 # pulling this out as a separate changes dict, or possibly just
105@@ -88,7 +100,7 @@
106 filename=filename, executable=entry.executable,
107 kind=entry.kind, absolutepath=absolutepath,
108 file_id=entry.file_id, size=entry.text_size, revid=revid,
109- change=change_dict[revid])
110+ change=change_dict[revid], contents_changed=contents_changed_rev)
111 file_list.append(file)
112
113 if sort_type == 'filename':
114@@ -96,10 +108,11 @@
115 elif sort_type == 'size':
116 file_list.sort(key=lambda x: x.size)
117 elif sort_type == 'date':
118- file_list.sort(key=lambda x: x.change.date)
119-
120- # Always sort directories first.
121- file_list.sort(key=lambda x: x.kind != 'directory')
122+ file_list.sort(key=lambda x: x.change.date, reverse=True)
123+
124+ if sort_type != 'date':
125+ # Don't always sort directories first.
126+ file_list.sort(key=lambda x: x.kind != 'directory')
127
128 return file_list
129
130
131=== modified file 'loggerhead/history.py'
132--- loggerhead/history.py 2012-02-08 01:50:02 +0000
133+++ loggerhead/history.py 2015-05-31 16:20:47 +0000
134@@ -722,6 +722,7 @@
135 'revid': revision.revision_id,
136 'date': datetime.datetime.fromtimestamp(revision.timestamp),
137 'utc_date': datetime.datetime.utcfromtimestamp(revision.timestamp),
138+ 'timestamp': revision.timestamp,
139 'committer': revision.committer,
140 'authors': revision.get_apparent_authors(),
141 'branch_nick': revision.properties.get('branch-nick', None),
142
143=== modified file 'loggerhead/static/css/global.css'
144--- loggerhead/static/css/global.css 2015-03-17 11:38:32 +0000
145+++ loggerhead/static/css/global.css 2015-05-31 16:20:47 +0000
146@@ -230,11 +230,11 @@
147 }
148 th.datecell,
149 td.date {
150- width: 180px;
151+ width: 100px;
152 }
153 th.timedate,
154 td.timedate2 {
155- width: 80px;
156+ width: 60px;
157 }
158 th.downloadcell,
159 td.downr {
160
161=== modified file 'loggerhead/static/css/view.css'
162--- loggerhead/static/css/view.css 2012-03-19 04:37:07 +0000
163+++ loggerhead/static/css/view.css 2015-05-31 16:20:47 +0000
164@@ -5,8 +5,7 @@
165 }
166 .viewRev {
167 border-right: none;
168- white-space: nowrap;
169- width: 1px;
170+ width: 20%;
171 padding: .3em .6em;
172 }
173 .viewComm,
174
175=== modified file 'loggerhead/templates/directory.pt'
176--- loggerhead/templates/directory.pt 2011-02-17 19:51:25 +0000
177+++ loggerhead/templates/directory.pt 2015-05-31 16:20:47 +0000
178@@ -17,16 +17,16 @@
179 <div >
180 <table id="logentries">
181 <tr class="logheader">
182- <th class="summarycell" colspan="2">Filename</th>
183- <th class="datecell">Latest Rev</th>
184+ <th class="datecell">Filename</th>
185+ <th class="timedate">Latest Rev</th>
186 <th class="datecell">Last Changed</th>
187+ <th class="datecell">Committer</th>
188+ <th class="summarycell">Comment</th>
189 </tr>
190
191 <tr class="blueRow0" tal:condition="python:name != '/'">
192- <td class="icocell">
193+ <td class="summcell" colspan="5">
194 <a href="../"><img tal:attributes="src python:static_url('/static/images/ico_folder_up.gif')" /></a>
195- </td>
196- <td class="summcell" colspan="3">
197 <a href="../">..</a>
198 </td>
199 </tr>
200@@ -34,32 +34,31 @@
201
202 <tal:branch-row tal:condition="dir/branch">
203 <tr tal:attributes="class string:blueRow${dir/parity}">
204- <td class="icocell">
205+ <td class="date">
206 <a tal:attributes="href string:${dir/dirname}/files">
207 <img tal:attributes="src python:static_url('/static/images/ico_branch.gif')" alt="Branch" />
208 </a>
209- </td>
210- <td class="autcell">
211 <a tal:attributes="href string:${dir/dirname}/files" tal:content="dir/dirname" /></td>
212 <td class="date">
213 <a tal:attributes="href string:${dir/dirname}/revision/${dir/branch/revno};
214 title string:Show revision ${dir/branch/revno}"
215 tal:content="dir/branch/revno"></a>
216 </td>
217- <td class="date" tal:content="python:util.date_time(dir.last_change)"></td>
218+ <td class="date" tal:content="python:util._approximatedate(dir.last_change_time)"></td>
219+ <td class="date" tal:content="python:util.hide_email(dir.last_revision.committer) if dir.last_revision is not None else 'Nobody'"></td>
220+ <td class="autcell" tal:content="python:dir.last_revision.message[:50] if dir.last_revision is not None else ''"></td>
221 </tr>
222+
223 </tal:branch-row>
224 <tal:non-branch-row tal:condition="not:dir/branch">
225 <tr tal:attributes="class string:blueRow${dir/parity}">
226- <td class="icocell">
227+ <td class="date">
228 <a tal:attributes="href string:${dir/dirname}/">
229 <img tal:attributes="src python:static_url('/static/images/ico_folder.gif')" alt="Folder" />
230 </a>
231- </td>
232- <td class="autcell">
233 <a tal:attributes="href string:${dir/dirname}/" tal:content="dir/dirname" /></td>
234 <td class="date"></td>
235- <td class="date" tal:content="dir/last_change"></td>
236+ <td class="date" colspan="4" tal:content="dir/last_change"></td>
237 </tr>
238 </tal:non-branch-row>
239 </tal:block>
240
241=== modified file 'loggerhead/templates/inventory.pt'
242--- loggerhead/templates/inventory.pt 2012-02-02 07:42:24 +0000
243+++ loggerhead/templates/inventory.pt 2015-05-31 16:20:47 +0000
244@@ -30,7 +30,7 @@
245 <tal:no-link condition="not: branch/branch_link">
246 <span metal:use-macro="breadcrumbs/directory"></span>
247 </tal:no-link>
248- <span>: <span metal:use-macro="breadcrumbs/branch" /> (revision <tal:revno content="change/revno"></tal:revno>)</span>
249+ <span>: <span metal:use-macro="breadcrumbs/branch" /> (Revision <tal:revno content="change/revno"></tal:revno>)</span>
250 </div>
251 </tal:block>
252
253@@ -54,10 +54,12 @@
254
255 <table id="logentries">
256 <tr class="logheader">
257- <th class="summarycell"><a tal:attributes="href python:url(['/files', revid], sort='filename')">Filename</a></th>
258- <th class="datecell">Latest Rev</th>
259- <th class="datecell"><a tal:attributes="href python:url(['/files', revid], sort='date')">Last Changed</a></th>
260- <th class="timedate"><a tal:attributes="href python:url(['/files', revid], sort='size')">Size</a></th>
261+ <th class="datecell"><a tal:attributes="href python:branch.sort_url(['/files', revid], sort='filename')">Filename</a></th>
262+ <th class="timedate">Latest Rev</th>
263+ <th class="datecell"><a tal:attributes="href python:branch.sort_url(['/files', revid], sort='date')">Last Changed</a></th>
264+ <th class="datecell">Committer</th>
265+ <th class="summarycell">Comment</th>
266+ <th class="timedate"><a tal:attributes="href python:branch.sort_url(['/files', revid], sort='size')">Size</a></th>
267 <th class="expandcell"></th>
268 <th class="expandcell"></th>
269 </tr>
270@@ -68,11 +70,15 @@
271 <img tal:attributes="src python:branch.static_url('/static/images/ico_folder_up.gif')" />..</a>
272 </td>
273 </tr>
274+ <tr class="blueRow0" tal:condition="python:updir is None and name != '/'">
275+ <td class="summcell" colspan="6">
276+ <a tal:attributes="href python:'/'.join(branch.friendly_name.split('/')[:-1])"><img tal:attributes="src python:static_url('/static/images/ico_folder_up.gif')" />..</a></td>
277+ </tr>
278
279 <!-- Show this if it's a directory -->
280 <tal:block repeat="file filelist">
281 <tr tal:attributes="class string:blueRow${repeat/file/even}" tal:condition="python:file.kind=='directory'">
282- <td class="autcell"><a tal:attributes="href python:url(['/files', revno_url, file.absolutepath])">
283+ <td class="date"><a tal:attributes="href python:url(['/files', revno_url, file.absolutepath])">
284 <img tal:attributes="src python:branch.static_url('/static/images/ico_folder.gif');
285 title string:Go to ${file/filename}" />
286 </a>
287@@ -84,8 +90,10 @@
288 title string:Show revision ${file/change/revno}"
289 tal:content="file/change/revno"></a>
290 </td>
291- <td class="date" tal:content="python:util.date_time(file.change.utc_date)"></td>
292- <td class="timedate2"></td>
293+ <td class="date" tal:content="python:util._approximatedate(file.change.utc_date)"></td>
294+ <td class="date" tal:content="python:util.hide_email(file.change.committer)"></td>
295+ <td class="autcell" tal:content="python:file.change.comment[:50]"></td>
296+ <td class="timedate2"></td><!-- not showing sizes of folders -->
297 <td class="expcell"><a tal:attributes="href python:url(['/changes'], start_revid=start_revid, filter_file_id=file.file_id);
298 title string:Show revision ${file/change/revno}">
299 <img tal:attributes="src python:branch.static_url('/static/images/ico_planilla.gif')" alt="Diff" />
300@@ -96,7 +104,7 @@
301
302 <!-- Show this if it's a symlink -->
303 <tr tal:attributes="class string:blueRow${repeat/file/even}" tal:condition="python:file.kind=='symlink'">
304- <td class="autcell"><a tal:attributes="href python:url(['/view', change.revno, file.absolutepath])">
305+ <td class="date"><a tal:attributes="href python:url(['/view', change.revno, file.absolutepath])">
306 <img tal:attributes="src python:branch.static_url('/static/images/ico_file_flecha.gif')" alt="Symlink" />
307 </a>
308
309@@ -107,7 +115,9 @@
310 title string:Show revision ${file/change/revno}"
311 tal:content="file/change/revno"></a>
312 </td>
313- <td class="date" tal:content="python:util.date_time(file.change.utc_date)"></td>
314+ <td class="date" tal:content="python:util._approximatedate(file.change.utc_date)"></td>
315+ <td class="date" tal:content="python:util.hide_email(file.change.committer)"></td>
316+ <td class="autcell" tal:content="python:file.change.comment[:50]"></td>
317 <td class="timedate2">.</td>
318 <td class="expcell"><a tal:attributes="href python:url(['/changes'], start_revid=start_revid, filter_file_id=file.file_id);
319 title string:Show revision ${file/change/revno}">
320@@ -120,7 +130,7 @@
321
322 <!-- Show this if it's a regular file -->
323 <tr tal:attributes="class string:blueRow${repeat/file/even}" tal:condition="python:file.kind=='file'">
324- <td class="autcell"><a tal:attributes="href python:url(['/view', revno_url, file.absolutepath])">
325+ <td class="date"><a tal:attributes="href python:url(['/view', revno_url, file.absolutepath])">
326 <img tal:attributes="src python:branch.static_url('/static/images/ico_file.gif');
327 title string:View ${file/filename}"
328 tal:condition="python:file.executable is False" />
329@@ -136,7 +146,10 @@
330 title string:Show revision ${file/change/revno}"
331 tal:content="file/change/revno"></a>
332 </td>
333- <td class="date" tal:content="python:util.date_time(file.change.utc_date)"></td>
334+ <td class="date" tal:content="python:util._approximatedate(file.change.utc_date)"></td>
335+ <td class="date" tal:content="python:util.hide_email(file.change.committer)"></td>
336+ <td class="autcell" tal:content="python:file.change.comment[:50]"></td>
337+
338 <td class="timedate2" tal:content="python:util.human_size(file.size)"></td>
339 <td class="expcell"><a tal:attributes="href python:url(['/view', revno_url, file.absolutepath]);
340 title string:View ${file/filename}">
341
342=== modified file 'loggerhead/util.py'
343--- loggerhead/util.py 2012-04-28 00:57:06 +0000
344+++ loggerhead/util.py 2015-05-31 16:20:47 +0000
345@@ -73,12 +73,13 @@
346
347
348 def _approximatedate(date):
349- delta = datetime.datetime.now() - date
350- if abs(delta) > datetime.timedelta(1, 0, 0):
351- # far in the past or future, display the date
352- return date_day(date)
353+ if date is None:
354+ return 'Never'
355+ delta = datetime.datetime.utcnow() - date
356 future = delta < datetime.timedelta(0, 0, 0)
357 delta = abs(delta)
358+ years = delta.days / 365
359+ months = delta.days / 30 # This is approximate.
360 days = delta.days
361 hours = delta.seconds / 3600
362 minutes = (delta.seconds - (3600*hours)) / 60
363@@ -86,7 +87,13 @@
364 result = ''
365 if future:
366 result += 'in '
367- if days != 0:
368+ if years != 0:
369+ amount = years
370+ unit = 'year'
371+ elif months != 0:
372+ amount = months
373+ unit = 'month'
374+ elif days != 0:
375 amount = days
376 unit = 'day'
377 elif hours != 0:
378@@ -103,7 +110,7 @@
379 result += '%s %s' % (amount, unit)
380 if not future:
381 result += ' ago'
382- return result
383+ return result
384
385
386 def _wrap_with_date_time_title(date, formatted_date):

Subscribers

People subscribed via source and target branches