Edgewall Software

source: trunk/svntrac/Changeset.py@ 1

Last change on this file since 1 was 1, checked in by Jonas Borgström, 20 years ago

Initial import

File size: 7.4 KB
Line 
1# svntrac
2#
3# Copyright (C) 2003 Jonas Borgström <jonas@xyche.com>
4#
5# svntrac is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License as
7# published by the Free Software Foundation; either version 2 of the
8# License, or (at your option) any later version.
9#
10# svntrac is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18#
19# Author: Jonas Borgström <jonas@xyche.com>
20
21from util import *
22from Module import Module
23import db
24import perm
25from xml.sax.saxutils import escape
26
27import re
28import string
29import StringIO
30from svn import fs, util, delta, repos
31
32line_re = re.compile('@@ [+-]([0-9]+),([0-9]+) [+-]([0-9]+),([0-9]+) @@')
33space_re = re.compile(' ')
34
35class DiffColorizer:
36 def __init__(self):
37 self.count = 0
38 self.block = []
39 self.type = None
40 self.p_block = []
41 self.p_type = None
42
43 print '<table class="diff-table" cellspacing="0">'
44
45 def writeadd (self, text):
46 print ('<tr><td class="diff-add-left"></td>'
47 '<td class="diff-add-right">'
48 '%s</td></tr>' % text)
49
50 def writeremove (self, text):
51 print ('<tr><td class="diff-remove-left">%s</td>'
52 '<td class="diff-remove-right"></td></tr>' % text)
53
54 def writeunchanged (self, text):
55 print ('<tr><td class="diff-unchanged">%s</td>'
56 '<td class="diff-unchanged">%s</td></tr>' %
57 (text, text))
58
59 def writechanged (self, old, new):
60 print ('<tr><td class="diff-changed">%s</td>'
61 '<td class="diff-changed">%s</td></tr>' %
62 (old, new))
63
64 def print_block (self):
65 if self.p_type == '-' and self.type == '+':
66 self.writechanged(string.join(self.p_block, '<br>'),
67 string.join(self.block, '<br>'))
68 elif self.type == '+':
69 self.writeadd(string.join(self.block, '<br>'))
70 elif self.type == '-':
71 self.writeremove(string.join(self.block, '<br>'))
72 elif self.type == ' ':
73 self.writeunchanged(string.join(self.block, '<br>'))
74 self.block = self.p_block = []
75
76 def writeline(self, text):
77 self.count = self.count + 1
78 if self.count < 3:
79 return
80 match = line_re.search(text)
81 if match:
82 self.print_block()
83 print ('<tr><td class="diff-line">line %s</td>'
84 '<td class="diff-line">line %s</td></tr>' %
85 (match.group(1), match.group(3)))
86 return
87 type = text[0]
88 text = text[1:]
89 text = space_re.sub ('&nbsp; ', text.expandtabs(8))
90 if type == self.type:
91 self.block.append(text)
92 else:
93 if type == '+' and self.type == '-':
94 self.p_block = self.block
95 self.p_type = self.type
96 else:
97 self.print_block()
98 self.block = [text]
99 self.type = type
100
101
102 def close(self):
103 self.print_block()
104 print '</table>'
105
106
107class DiffEditor (delta.Editor):
108 """
109 generates a unified diff of the changes for a given changeset.
110 the output is written to stdout.
111 """
112 def __init__(self, old_root, new_root):
113 self.old_root = old_root
114 self.new_root = new_root
115
116 def print_diff (self, old_path, new_path, pool):
117 old_root = new_root = None
118 if old_path:
119 old_root = self.old_root
120 name = old_path
121 if new_path:
122 new_root = self.new_root
123 name = new_path
124 differ = fs.FileDiff(old_root, old_path,
125 new_root, new_path, pool, ['-u'])
126 differ.get_files()
127 pobj = differ.get_pipe()
128 print '<h3>%s</h3>' % name
129 filter = DiffColorizer()
130 while 1:
131 line = pobj.readline()
132 if not line:
133 break
134 filter.writeline(escape(line))
135 filter.close()
136
137
138 def add_file(self, path, parent_baton,
139 copyfrom_path, copyfrom_revision, file_pool):
140 self.print_diff (None, path, file_pool)
141 return [None, path, file_pool]
142
143 def open_file(self, path, parent_baton, base_revision, file_pool):
144 return [path, path, file_pool]
145
146 def apply_textdelta(self, file_baton, base_checksum):
147 self.print_diff (*file_baton)
148
149def render_diffs(fs_ptr, rev, pool):
150 """
151 generates a unified diff of the changes for a given changeset.
152 the output is written to stdout.
153 """
154 old_root = fs.revision_root(fs_ptr, rev - 1, pool)
155 new_root = fs.revision_root(fs_ptr, rev, pool)
156
157 editor = DiffEditor(old_root, new_root)
158 e_ptr, e_baton = delta.make_editor(editor, pool)
159
160 repos.svn_repos_dir_delta(old_root, '', None,
161 new_root, '', e_ptr, e_baton,
162 0, 1, 0, 1, pool)
163
164class Changeset (Module):
165 template_key = 'changeset_template'
166
167 def get_changeset_info (self, rev):
168 cnx = db.get_connection()
169 cursor = cnx.cursor ()
170
171 cursor.execute ('SELECT time, author, message FROM revision ' +
172 'WHERE rev=%d' % rev)
173 return cursor.fetchone()
174
175 def get_change_info (self, rev):
176 cnx = db.get_connection()
177 cursor = cnx.cursor ()
178
179 cursor.execute ('SELECT name, change FROM node_change ' +
180 'WHERE rev=%d' % rev)
181 return cursor.fetchall()
182
183 def print_item (self, out, item):
184 action = {
185 'A': 'added',
186 'D': 'deleted',
187 'M': 'modified'
188 }
189 out.write ('<tr>\n')
190 if item['change'] in ['A', 'M']:
191 out.write ('<td><a href="%s">%s</a></td><td>%s</td>'
192 % (log_href (item['name']),
193 item['name'],
194 action[item['change']]))
195 else:
196 out.write ('<td>%s</td><td>%s</td>' % (item['name'],
197 action[item['change']]))
198 out.write ('</tr>')
199
200 def render (self):
201 perm.assert_permission (perm.CHANGESET_VIEW)
202
203 if self.args.has_key('rev'):
204 self.rev = int(self.args['rev'])
205 else:
206 self.rev = fs.youngest_rev(self.fs_ptr, self.pool)
207
208 out = StringIO.StringIO()
209 change_info = self.get_change_info (self.rev)
210
211 for item in change_info:
212 self.print_item (out, item)
213
214 changeset_info = self.get_changeset_info (self.rev)
215
216 self.namespace['time'] = time_to_string (int(changeset_info['time']))
217 self.namespace['author'] = changeset_info['author']
218 self.namespace['message'] = changeset_info['message']
219 self.namespace['revision'] = self.rev
220 self.namespace['changeset_info'] = out.getvalue()
221
222 def apply_template (self):
223 Module.apply_template(self)
224 print '<h3>diffs</h3>'
225 render_diffs(self.fs_ptr, int(self.rev), self.pool)
226 print self.namespace['footer']
Note: See TracBrowser for help on using the repository browser.