17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
from paste.httpexceptions import HTTPBadRequest
25
import bzrlib.textfile
28
from paste.httpexceptions import HTTPBadRequest, HTTPServerError
25
30
from loggerhead.controllers import TemplatedBranchView
32
from loggerhead.highlight import highlight
26
35
from loggerhead import util
30
while path.endswith('/'):
32
path = posixpath.dirname(path)
35
class AnnotateUI (TemplatedBranchView):
38
class AnnotateUI(TemplatedBranchView):
37
40
template_path = 'loggerhead.templates.annotate'
39
def get_values(self, h, args, kw, headers):
41
revid = h.fix_revid(args[0])
42
def annotate_file(self, file_id, revid):
47
file_revid = self._history.get_inventory(revid)[file_id].revision
48
tree = self._history._branch.repository.revision_tree(file_revid)
50
file_name = os.path.basename(self._history.get_path(revid, file_id))
52
file_text = tree.get_file_text(file_id)
55
file_text = file_text.decode(encoding)
56
except UnicodeDecodeError:
57
encoding = 'iso-8859-15'
58
file_text = file_text.decode(encoding)
60
file_lines = bzrlib.osutils.split_lines(file_text)
63
bzrlib.textfile.check_text_lines(file_lines)
64
except bzrlib.errors.BinaryFile:
65
# bail out; this isn't displayable text
66
yield util.Container(parity=0, lineno=1, status='same',
67
text='(This is a binary file.)',
68
change=util.Container())
47
path = '/'.join(args[1:])
48
if not path.startswith('/'):
51
file_id = kw.get('file_id', None)
70
if highlight is not None:
71
hl_lines = highlight(file_name, file_text, encoding)
72
hl_lines.extend([u''] * (len(file_lines) - len(hl_lines)))
74
hl_lines = map(cgi.escape, file_lines)
78
last_line_revid = None
79
for line_revid, text in tree.annotate_iter(file_id):
80
if line_revid == last_line_revid:
81
# remember which lines have a new revno and which don't
86
last_line_revid = line_revid
87
if line_revid in change_cache:
88
change = change_cache[line_revid]
90
change = self._history.get_changes([line_revid])[0]
91
change_cache[line_revid] = change
94
parity=parity, lineno=lineno, status=status,
95
change=change, text=hl_lines[lineno - 1])
98
self.log.debug('annotate: %r secs' % (time.time() - z,))
100
def get_values(self, path, kwargs, headers):
101
history = self._history
102
branch = history._branch
103
revid = self.get_revid()
104
revid = history.fix_revid(revid)
105
file_id = kwargs.get('file_id', None)
52
106
if (file_id is None) and (path is None):
53
raise HTTPBadRequest('No file_id or filename provided to annotate')
107
raise HTTPBadRequest('No file_id or filename '
108
'provided to annotate')
55
110
if file_id is None:
56
file_id = h.get_file_id(revid, path)
111
file_id = history.get_file_id(revid, path)
58
113
# no navbar for revisions
59
114
navigation = util.Container()
62
path = h.get_path(revid, file_id)
117
path = history.get_path(revid, file_id)
63
118
filename = os.path.basename(path)
120
change = history.get_changes([ revid ])[0]
121
# If we're looking at the tip, use head: in the URL instead
122
if revid == branch.last_revision():
125
revno_url = history.get_revno(revid)
65
127
# Directory Breadcrumbs
66
128
directory_breadcrumbs = (
67
129
util.directory_breadcrumbs(
72
134
# Create breadcrumb trail for the path within the branch
74
inv = h.get_inventory(revid)
136
inv = history.get_inventory(revid)
76
138
self.log.exception('Exception fetching changes')
77
139
raise HTTPServerError('Could not fetch changes')
78
140
branch_breadcrumbs = util.branch_breadcrumbs(path, inv, 'files')
143
'revno_url': revno_url,
82
144
'file_id': file_id,
84
146
'filename': filename,
85
147
'navigation': navigation,
86
'change': h.get_changes([ revid ])[0],
87
'contents': list(h.annotate_file(file_id, revid)),
149
'contents': list(self.annotate_file(file_id, revid)),
88
150
'fileview_active': True,
89
151
'directory_breadcrumbs': directory_breadcrumbs,
90
152
'branch_breadcrumbs': branch_breadcrumbs,