~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/controllers/annotate_ui.py

  • Committer: Matt Nordhoff
  • Date: 2009-05-13 14:03:48 UTC
  • mto: (389.2.2 pep8-2009-10)
  • mto: This revision was merged to the branch mainline in revision 392.
  • Revision ID: mnordhoff@mattnordhoff.com-20090513140348-yn43gztulksm62e9
Always use a tuple in string formatting

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
#
19
19
 
20
 
import logging
 
20
import cgi
21
21
import os
22
 
import posixpath
23
22
import time
24
23
 
25
 
import turbogears
26
 
from cherrypy import HTTPError
27
 
 
 
24
import bzrlib.errors
 
25
import bzrlib.textfile
 
26
 
 
27
from paste.httpexceptions import HTTPBadRequest, HTTPServerError
 
28
 
 
29
from loggerhead.controllers import TemplatedBranchView
 
30
try:
 
31
    from loggerhead.highlight import highlight
 
32
except ImportError:
 
33
    highlight = None
28
34
from loggerhead import util
29
35
 
30
36
 
31
 
log = logging.getLogger("loggerhead.controllers")
32
 
 
33
 
def dirname(path):
34
 
    while path.endswith('/'):
35
 
        path = path[:-1]
36
 
    path = posixpath.dirname(path)
37
 
    return path
38
 
 
39
 
        
40
 
class AnnotateUI (object):
41
 
 
42
 
    def __init__(self, branch):
43
 
        # BranchView object
44
 
        self._branch = branch
45
 
        self.log = branch.log
46
 
 
47
 
    @util.strip_whitespace
48
 
    @turbogears.expose(html='loggerhead.templates.annotate')
49
 
    def default(self, *args, **kw):
 
37
class AnnotateUI(TemplatedBranchView):
 
38
 
 
39
    template_path = 'loggerhead.templates.annotate'
 
40
 
 
41
    def annotate_file(self, file_id, revid):
50
42
        z = time.time()
51
 
        h = self._branch.get_history()
52
 
        util.set_context(kw)
53
 
 
54
 
        h._branch.lock_read()
 
43
        lineno = 1
 
44
        parity = 0
 
45
 
 
46
        file_revid = self._history.get_inventory(revid)[file_id].revision
 
47
        tree = self._history._branch.repository.revision_tree(file_revid)
 
48
 
 
49
        file_name = os.path.basename(self._history.get_path(revid, file_id))
 
50
 
55
51
        try:
56
 
            if len(args) > 0:
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())
 
59
        else:
 
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)))
58
63
            else:
59
 
                revid = h.last_revid
60
 
 
61
 
            path = None
62
 
            if len(args) > 1:
63
 
                path = '/'.join(args[1:])
64
 
                if not path.startswith('/'):
65
 
                    path = '/' + path
66
 
 
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')
70
 
 
71
 
            if file_id is None:
72
 
                file_id = h.get_file_id(revid, path)
73
 
 
74
 
            # no navbar for revisions
75
 
            navigation = util.Container()
76
 
 
77
 
            if path is None:
78
 
                path = h.get_path(revid, file_id)
79
 
            filename = os.path.basename(path)
80
 
 
81
 
            vals = {
82
 
                'branch': self._branch,
83
 
                'util': util,
84
 
                'revid': revid,
85
 
                'file_id': file_id,
86
 
                'path': path,
87
 
                'filename': filename,
88
 
                'history': h,
89
 
                'navigation': navigation,
90
 
                'change': h.get_changes([ revid ])[0],
91
 
                'contents': list(h.annotate_file(file_id, revid)),
92
 
            }
93
 
            h.flush_cache()
94
 
            self.log.info('/annotate: %r secs' % (time.time() - z,))
95
 
            return vals
96
 
        finally:
97
 
            h._branch.unlock()
 
64
                hl_lines = map(cgi.escape, file_lines)
 
65
 
 
66
            change_cache = {}
 
67
 
 
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
 
72
                    status = 'same'
 
73
                else:
 
74
                    status = 'changed'
 
75
                    parity ^= 1
 
76
                    last_line_revid = line_revid
 
77
                    if line_revid in change_cache:
 
78
                        change = change_cache[line_revid]
 
79
                    else:
 
80
                        change = self._history.get_changes([line_revid])[0]
 
81
                        change_cache[line_revid] = change
 
82
 
 
83
                yield util.Container(
 
84
                    parity=parity, lineno=lineno, status=status,
 
85
                    change=change, text=hl_lines[lineno - 1])
 
86
                lineno += 1
 
87
 
 
88
        self.log.debug('annotate: %r secs' % (time.time() - z,))
 
89
 
 
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')
 
99
 
 
100
        if file_id is None:
 
101
            file_id = history.get_file_id(revid, path)
 
102
 
 
103
        # no navbar for revisions
 
104
        navigation = util.Container()
 
105
 
 
106
        if path is None:
 
107
            path = history.get_path(revid, file_id)
 
108
        filename = os.path.basename(path)
 
109
 
 
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():
 
113
            revno_url = 'head:'
 
114
        else:
 
115
            revno_url = history.get_revno(revid)
 
116
 
 
117
        # Directory Breadcrumbs
 
118
        directory_breadcrumbs = (
 
119
            util.directory_breadcrumbs(
 
120
                self._branch.friendly_name,
 
121
                self._branch.is_root,
 
122
                'files'))
 
123
 
 
124
        # Create breadcrumb trail for the path within the branch
 
125
        try:
 
126
            inv = history.get_inventory(revid)
 
127
        except:
 
128
            self.log.exception('Exception fetching changes')
 
129
            raise HTTPServerError('Could not fetch changes')
 
130
        branch_breadcrumbs = util.branch_breadcrumbs(path, inv, 'files')
 
131
 
 
132
        return {
 
133
            'revno_url': revno_url,
 
134
            'file_id': file_id,
 
135
            'path': path,
 
136
            'filename': filename,
 
137
            'navigation': navigation,
 
138
            'change': change,
 
139
            'contents': list(self.annotate_file(file_id, revid)),
 
140
            'fileview_active': True,
 
141
            'directory_breadcrumbs': directory_breadcrumbs,
 
142
            'branch_breadcrumbs': branch_breadcrumbs,
 
143
        }