17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
from StringIO import StringIO
23
from bzrlib import errors
25
23
from paste.httpexceptions import HTTPServerError
27
25
from loggerhead import util
28
26
from loggerhead.controllers import TemplatedBranchView
29
from loggerhead.history import rich_filename
27
from loggerhead.controllers.filediff_ui import diff_chunks_for_file
32
30
DEFAULT_LINE_COUNT_LIMIT = 3000
33
return urllib.quote(urllib.quote(p, safe=''))
35
36
class RevisionUI(TemplatedBranchView):
37
38
template_path = 'loggerhead.templates.revision'
39
def _process_diff(self, diff):
40
# doesn't really need to be a method; could be static.
43
for line in diff.splitlines():
46
if line.startswith('+++ ') or line.startswith('--- '):
48
if line.startswith('@@ '):
52
chunk = util.Container()
54
split_lines = line.split(' ')[1:3]
55
lines = [int(x.split(',')[0][1:]) for x in split_lines]
58
elif line.startswith(' '):
59
chunk.diff.append(util.Container(old_lineno=old_lineno,
60
new_lineno=new_lineno,
65
elif line.startswith('+'):
66
chunk.diff.append(util.Container(old_lineno=None,
67
new_lineno=new_lineno,
68
type='insert', line=line[1:]))
70
elif line.startswith('-'):
71
chunk.diff.append(util.Container(old_lineno=old_lineno,
73
type='delete', line=line[1:]))
76
chunk.diff.append(util.Container(old_lineno=None,
84
def _parse_diffs(self, old_tree, new_tree, delta, specific_path):
86
Return a list of processed diffs, in the format::
95
type: str('context', 'delete', or 'insert'),
104
def include_specific_path(path):
105
return specific_path == path
106
def include_all_paths(path):
109
include_path = include_specific_path
111
include_path = include_all_paths
113
for old_path, new_path, fid, \
114
kind, text_modified, meta_modified in delta.renamed:
115
if text_modified and include_path(new_path):
116
process.append((old_path, new_path, fid, kind))
117
for path, fid, kind, text_modified, meta_modified in delta.modified:
118
if include_path(path):
119
process.append((path, path, fid, kind))
120
for path, fid, kind in delta.added:
121
if file == 'kind' and include_path(path):
122
process.append((path, path, fid, kind))
123
for path, fid, kind in delta.removed:
124
if file == 'kind' and include_path(path):
125
process.append((path, path, fid, kind))
127
process.sort(key=lambda x:x[1])
129
for old_path, new_path, fid, kind in process:
131
old_lines = old_tree.get_file_lines(fid)
132
except errors.NoSuchId:
135
new_lines = new_tree.get_file_lines(fid)
136
except errors.NoSuchId:
139
if old_lines != new_lines:
141
bzrlib.diff.internal_diff(old_path, old_lines,
142
new_path, new_lines, buffer)
143
except bzrlib.errors.BinaryFile:
146
diff = buffer.getvalue()
149
out.append(util.Container(
150
filename=rich_filename(new_path, kind), file_id=fid,
151
chunks=self._process_diff(diff)))
155
def get_changes_with_diff(self, change, compare_revid, specific_path):
157
if compare_revid is None:
159
compare_revid = change.parents[0].revid
161
compare_revid = 'null:'
163
rev_tree1 = h._branch.repository.revision_tree(compare_revid)
164
rev_tree2 = h._branch.repository.revision_tree(change.revid)
165
delta = rev_tree2.changes_from(rev_tree1)
167
changes = h.parse_delta(delta)
169
return changes, self._parse_diffs(
170
rev_tree1, rev_tree2, delta, specific_path)
172
40
def get_values(self, path, kwargs, headers):
174
42
revid = self.get_revid()
197
65
util.fill_in_navigation(navigation)
199
67
change = h.get_changes([revid])[0]
69
if compare_revid is None:
70
file_changes = h.get_file_changes(change)
72
file_changes = h.file_changes_for_revision_ids(
73
compare_revid, change.revid)
200
75
if path in ('', '/'):
202
change.changes, diffs = self.get_changes_with_diff(change, compare_revid, path)
203
# add parent & merge-point branch-nick info, in case it's useful
204
h.get_branch_nicks([change])
81
item = [x for x in file_changes.text_changes if x.filename == path][0]
82
diff_chunks = diff_chunks_for_file(
83
self._history._branch.repository, item.file_id,
84
item.old_revision, item.new_revision)
87
for i, item in enumerate(file_changes.text_changes):
89
link_data['diff-' + str(i)] = '%s/%s/%s' % (
90
dq(item.new_revision), dq(item.old_revision), dq(item.file_id))
91
path_to_id[item.filename] = 'diff-' + str(i)
93
h.add_branch_nicks(change)
95
if '.' in change.revno:
96
# Walk "up" though the merge-sorted graph until we find a
97
# revision with merge depth 0: this is the revision that merged
98
# this one to mainline.
99
ri = self._history._rev_info
100
i = self._history._rev_indices[change.revid]
101
while ri[i][0][2] > 0:
103
merged_in = ri[i][0][3]
206
107
# Directory Breadcrumbs
207
108
directory_breadcrumbs = (