17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
from cherrypy import HTTPError
25
import bzrlib.textfile
27
from paste.httpexceptions import HTTPBadRequest, HTTPServerError
29
from loggerhead.controllers import TemplatedBranchView
31
from loggerhead.highlight import highlight
28
34
from loggerhead import util
31
log = logging.getLogger("loggerhead.controllers")
34
while path.endswith('/'):
36
path = posixpath.dirname(path)
40
class AnnotateUI (object):
42
def __init__(self, branch):
47
@util.strip_whitespace
48
@turbogears.expose(html='loggerhead.templates.annotate')
49
def default(self, *args, **kw):
37
class AnnotateUI(TemplatedBranchView):
39
template_path = 'loggerhead.templates.annotate'
41
def annotate_file(self, file_id, revid):
51
h = self._branch.get_history()
46
file_revid = self._history.get_inventory(revid)[file_id].revision
47
tree = self._history._branch.repository.revision_tree(file_revid)
49
file_name = os.path.basename(self._history.get_path(revid, file_id))
57
revid = h.fix_revid(args[0])
52
file_lines = tree.get_file_lines(file_id)
53
bzrlib.textfile.check_text_lines(file_lines)
54
except bzrlib.errors.BinaryFile:
55
# bail out; this isn't displayable text
56
yield util.Container(parity=0, lineno=1, status='same',
57
text='(This is a binary file.)',
58
change=util.Container())
60
if highlight is not None:
61
hl_lines = highlight(file_name, ''.join(file_lines))
62
hl_lines.extend([u''] * (len(file_lines) - len(hl_lines)))
63
path = '/'.join(args[1:])
64
if not path.startswith('/'):
67
file_id = kw.get('file_id', None)
68
if (file_id is None) and (path is None):
69
raise HTTPError(400, 'No file_id or filename provided to annotate')
72
file_id = h.get_file_id(revid, path)
74
# no navbar for revisions
75
navigation = util.Container()
78
path = h.get_path(revid, file_id)
79
filename = os.path.basename(path)
82
'branch': self._branch,
89
'navigation': navigation,
90
'change': h.get_changes([ revid ])[0],
91
'contents': list(h.annotate_file(file_id, revid)),
94
self.log.info('/annotate: %r secs' % (time.time() - z,))
64
hl_lines = map(cgi.escape, file_lines)
68
last_line_revid = None
69
for line_revid, text in tree.annotate_iter(file_id):
70
if line_revid == last_line_revid:
71
# remember which lines have a new revno and which don't
76
last_line_revid = line_revid
77
if line_revid in change_cache:
78
change = change_cache[line_revid]
80
change = self._history.get_changes([line_revid])[0]
81
change_cache[line_revid] = change
84
parity=parity, lineno=lineno, status=status,
85
change=change, text=hl_lines[lineno - 1])
88
self.log.debug('annotate: %r secs' % (time.time() - z,))
90
def get_values(self, path, kwargs, headers):
91
history = self._history
92
branch = history._branch
93
revid = self.get_revid()
94
revid = history.fix_revid(revid)
95
file_id = kwargs.get('file_id', None)
96
if (file_id is None) and (path is None):
97
raise HTTPBadRequest('No file_id or filename '
98
'provided to annotate')
101
file_id = history.get_file_id(revid, path)
103
# no navbar for revisions
104
navigation = util.Container()
107
path = history.get_path(revid, file_id)
108
filename = os.path.basename(path)
110
change = history.get_changes([ revid ])[0]
111
# If we're looking at the tip, use head: in the URL instead
112
if revid == branch.last_revision():
115
revno_url = history.get_revno(revid)
117
# Directory Breadcrumbs
118
directory_breadcrumbs = (
119
util.directory_breadcrumbs(
120
self._branch.friendly_name,
121
self._branch.is_root,
124
# Create breadcrumb trail for the path within the branch
126
inv = history.get_inventory(revid)
128
self.log.exception('Exception fetching changes')
129
raise HTTPServerError('Could not fetch changes')
130
branch_breadcrumbs = util.branch_breadcrumbs(path, inv, 'files')
133
'revno_url': revno_url,
136
'filename': filename,
137
'navigation': navigation,
139
'contents': list(self.annotate_file(file_id, revid)),
140
'fileview_active': True,
141
'directory_breadcrumbs': directory_breadcrumbs,
142
'branch_breadcrumbs': branch_breadcrumbs,