Ticket #199: diff_module_alpha3.diff
| File diff_module_alpha3.diff, 34.6 KB (added by cboos, 7 years ago) |
|---|
-
htdocs/css/browser.css
45 45 #dirlist td.name a, #dirlist td.rev a { border-bottom: none; display: block } 46 46 #dirlist td.change * { font-size: 9px } 47 47 48 /* Log */ 49 tr.diff input { 50 padding: 0 1em 0 1em; 51 margin: 0; 52 } 53 54 #anydiff { 55 background: #f7f7f0; 56 border: 1px outset #998; 57 margin: 0 1em 1em; 58 padding: .8em; 59 float: right; 60 } 61 #anydiff em { 62 background: #fbfbfb; 63 } 64 #anydiff form, #anydiff div { 65 vertical-align: top; 66 display: inline; 67 margin-right: 0; 68 margin-left: 0; 69 } 70 #anydiff input { 71 vertical-align: baseline; 72 } 73 48 74 /* Styles for the revision log table 49 75 (extends the styles for "table.listing") */ 50 76 #chglist { margin-top: 0 } -
trac/db_default.py
458 458 459 459 default_components = ('trac.About', 'trac.attachment', 'trac.Browser', 460 460 'trac.Changeset', 'trac.Search', 'trac.Settings', 461 'trac.Diff', 461 462 'trac.ticket.query', 'trac.ticket.report', 462 463 'trac.Roadmap', 463 464 'trac.ticket.web_ui', 'trac.Timeline', 'trac.wiki.web_ui', -
trac/versioncontrol/svn_fs.py
27 27 import os.path 28 28 import time 29 29 import weakref 30 import posixpath 30 31 31 32 from svn import fs, repos, core, delta 32 33 … … 175 176 def __del__(self): 176 177 self.close() 177 178 179 def has_node(self, path, rev): 180 rev_root = fs.revision_root(self.fs_ptr, rev, self.pool) 181 node_type = fs.check_path(rev_root, path, self.pool) 182 return node_type in _kindmap 183 178 184 def normalize_path(self, path): 179 return path == '/' and path or path .strip('/')185 return path == '/' and path or path and path.strip('/') or '' 180 186 181 187 def normalize_rev(self, rev): 182 188 try: … … 267 273 rev = self.normalize_rev(rev) 268 274 expect_deletion = False 269 275 while rev: 270 rev_root = fs.revision_root(self.fs_ptr, rev, self.pool) 271 node_type = fs.check_path(rev_root, path, self.pool) 272 if node_type in _kindmap: # then path exists at that rev 276 if self.has_node(path, rev): 273 277 if expect_deletion: 274 278 # it was missing, now it's there again: rev+1 must be a delete 275 279 yield path, rev+1, Changeset.DELETE … … 294 298 expect_deletion = True 295 299 rev = self.previous_rev(rev) 296 300 301 def get_diffs(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 302 old_node = new_node = None 303 old_rev = self.normalize_rev(old_rev) 304 new_rev = self.normalize_rev(new_rev) 305 if self.has_node(old_path, old_rev): 306 old_node = self.get_node(old_path, old_rev) 307 old_path = old_node.created_path 308 old_rev = old_node.created_rev 309 if self.has_node(new_path, new_rev): 310 new_node = self.get_node(new_path, new_rev) 311 new_path = new_node.created_path 312 new_rev = new_node.created_rev 313 if not old_node and not new_node: 314 raise TracError, ('None of the diff arguments are valid: ' 315 'neither %s in revision %s nor %s in revision %s exist ' 316 'in the repository' % (old_path, old_rev, 317 new_path, new_rev)) 318 elif old_node and new_node: 319 if new_node.kind != old_node.kind: 320 raise TracError, ('Diff mismatch: Trying to diff a %s (%s at %s) ' 321 'with a %s (%s at %s).' \ 322 % (old_node.kind, old_path, old_rev, 323 new_node.kind, new_path, new_rev)) 324 if new_node: 325 isdir = new_node.isdir 326 else: 327 isdir = old_node.isdir 328 if isdir: 329 old_base = old_path 330 new_base = new_path 331 else: 332 old_base = posixpath.split(old_path)[0] 333 new_base = posixpath.split(new_path)[0] 297 334 335 editor = DiffChangeEditor() 336 e_ptr, e_baton = delta.make_editor(editor, self.pool) 337 old_root = fs.revision_root(self.fs_ptr, old_rev, self.pool) 338 new_root = fs.revision_root(self.fs_ptr, new_rev, self.pool) 339 if isdir: 340 old_dir, old_entry = old_path, '' 341 else: 342 old_dir, old_entry = posixpath.split(old_path) 343 def authz_cb(root, path, pool): return 1 344 text_deltas = 0 # as this is currently re-done in Diff.py... 345 entry_props = 0 # ("... typically used only for working copy updates") 346 repos.svn_repos_dir_delta(old_root, 347 old_dir, old_entry, 348 new_root, new_path, 349 e_ptr, e_baton, authz_cb, 350 text_deltas, 351 isdir and 1 or 0, 352 entry_props, 353 ignore_ancestry, 354 self.pool) 355 for d in editor.deltas: 356 yield (posixpath.join(old_base,d[0]), posixpath.join(new_base,d[0]), 357 d[1], d[2]) 358 359 298 360 class SubversionNode(Node): 299 361 300 362 pool = property(fget=lambda self: self._pool(), … … 450 512 451 513 def _get_prop(self, name): 452 514 return fs.revision_prop(self.fs_ptr, self.rev, name, self.pool) 515 516 517 # 518 # Delta editor for diffs between arbitrary nodes (recycling my old code for #295 :) ) 519 # 520 # Note 1: the 'copyfrom_path' and 'copyfrom_rev' information is not used 521 # because 'repos.svn_repos_dir_delta' *doesn't* provide it. 522 # 523 # Note 2: the 'dir_baton' is the path of the parent directory 524 # 525 526 class DiffChangeEditor(delta.Editor): 527 528 def __init__(self): 529 self.deltas = [] 530 self.skip_dir_prop_change = 0 531 532 def _norm(self, path): 533 """Path are normalized to __not__ have a leading slash""" 534 return path == '/' and path or path and path.strip('/') or '' 535 536 # -- svn.delta.Editor callbacks 537 538 def open_root(self, base_revision, dir_pool): 539 return '/' 540 541 def add_directory(self, path, dir_baton, copyfrom_path, copyfrom_rev, dir_pool): 542 self.deltas.append((path, Node.DIRECTORY, Changeset.ADD)) 543 # don't create an additional 'Changeset.EDIT' entry for this directory 544 # in case there's also a dir property change: 545 self.skip_dir_prop_change = 1 546 return path 547 548 def open_directory(self, path, dir_baton, base_revision, dir_pool): 549 self.deltas.append((path, Node.DIRECTORY, Changeset.EDIT)) 550 self.skip_dir_prop_change = 0 551 return path 552 553 def change_dir_prop(self, dir_baton, name, value, pool): 554 if self.skip_dir_prop_change: 555 return 556 self.deltas.append((dir_baton, Node.DIRECTORY, Changeset.EDIT)) 557 self.skip_dir_prop_change = 1 558 559 def close_directory(self, dir_baton): 560 self.skip_dir_prop_change = 0 561 562 def delete_entry(self, path, revision, dir_baton, pool): 563 self.deltas.append((path, Node.FILE, Changeset.DELETE)) # should be Node.UNKNOWN 564 565 def add_file(self, path, dir_baton, copyfrom_path, copyfrom_revision, dir_pool): 566 self.deltas.append((self._norm(path), Node.FILE, Changeset.ADD)) 567 568 def open_file(self, path, dir_baton, dummy_rev, file_pool): 569 self.deltas.append((self._norm(path), Node.FILE, Changeset.EDIT)) 570 -
trac/versioncontrol/cache.py
88 88 def get_node(self, path, rev=None): 89 89 return self.repos.get_node(path, rev) 90 90 91 def has_node(self, path, rev): 92 return self.repos.has_node(path, rev) 93 91 94 def get_oldest_rev(self): 92 95 return self.repos.oldest_rev 93 96 … … 112 115 def normalize_rev(self, rev): 113 116 return self.repos.normalize_rev(rev) 114 117 118 def get_diffs(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 119 return self.repos.get_diffs(old_path, old_rev, new_path, new_rev, ignore_ancestry) 115 120 121 116 122 class CachedChangeset(Changeset): 117 123 118 124 def __init__(self, rev, db, authz): -
trac/versioncontrol/main.py
42 42 """ 43 43 raise NotImplementedError 44 44 45 def has_node(self, path, rev): 46 """ 47 Tell if there's a node at the specified (path,rev) combination. 48 """ 49 raise NotImplementedError 50 45 51 def get_node(self, path, rev=None): 46 52 """ 47 53 Retrieve a Node (directory or file) from the repository at the … … 114 120 'None' is a valid revision value and represents the youngest revision. 115 121 """ 116 122 return NotImplementedError 117 118 123 124 def get_diffs(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 125 """ 126 Generator that yields (old_path, new_path, kind, change) tuples 127 for each node change between the two arbitrary (path,rev) pairs. 128 """ 129 raise NotImplementedError 130 131 119 132 class Node(object): 120 133 """ 121 134 Represents a directory or file in the repository. -
trac/Diff.py
24 24 from __future__ import generators 25 25 import time 26 26 import re 27 import posixpath 27 28 28 29 from trac import mimeview, perm, util 29 30 from trac.core import * 30 from trac.Timeline import ITimelineEventProvider31 31 from trac.versioncontrol import Changeset, Node 32 32 from trac.versioncontrol.diff import get_diff_options, hdf_diff, unified_diff 33 33 from trac.web.chrome import add_link, add_stylesheet … … 35 35 from trac.wiki import wiki_to_html, wiki_to_oneliner 36 36 37 37 38 class ChangesetModule(Component): 38 class Diff(dict): 39 def __getattr__(self,str): 40 return self[str] 41 39 42 40 implements(IRequestHandler, ITimelineEventProvider) 43 class DiffModule(Component): 41 44 45 implements(IRequestHandler) 46 42 47 # IRequestHandler methods 43 48 44 49 def match_request(self, req): 45 match = re.match(r'/ changeset/([0-9]+)$', req.path_info)50 match = re.match(r'/diff(?:(/.*)|$)', req.path_info) 46 51 if match: 47 req.args[' rev'] = match.group(1)52 req.args['path'] = match.group(1) 48 53 return 1 49 54 50 55 def process_request(self, req): 51 56 req.perm.assert_permission(perm.CHANGESET_VIEW) 52 57 53 rev = req.args.get('rev')58 path = req.args.get('path') 54 59 repos = self.env.get_repository(req.authname) 60 path = repos.normalize_path(path) 61 rev = req.args.get('rev', repos.youngest_rev) # 'path history' mode 62 old = req.args.get('old') # 'arbitrary diff' mode 63 new = req.args.get('new') 64 old_path = req.args.get('old_path', path) 65 if old_path == path and old == new: # force 'path history' mode 66 rev = old 67 old_path = old = new = None 55 68 56 69 diff_options = get_diff_options(req) 57 70 if req.args.has_key('update'): 58 req.redirect(self.env.href.changeset(rev)) 71 if old or new: 72 req.redirect(self.env.href.diff(path, new=new, old_path=old_path, old=old)) 73 else: 74 req.redirect(self.env.href.diff(path, rev=rev)) 59 75 60 chgset = repos.get_changeset(rev) 61 req.check_modified(chgset.date, 62 diff_options[0] + ''.join(diff_options[1])) 76 if old or new: 77 chgset = None 78 if not new: 79 new = repos.next_rev(old) # FIXME: must lookup the next entry in node history 80 elif not old: 81 old = repos.previous_rev(new) 82 if not old_path: 83 old_path = path 84 diff = Diff(old_path=old_path, old_rev=old, 85 new_path=path, new_rev=new) 86 else: 87 chgset = repos.get_changeset(rev) 88 diff = Diff(old_path=path, old_rev=repos.previous_rev(rev), 89 new_path=path, new_rev=rev) 90 91 # TODO: 92 # req.check_modified(chgset.date, 93 # diff_options[0] + ''.join(diff_options[1])) 63 94 64 95 format = req.args.get('format') 65 96 if format == 'diff': 66 self._render_diff(req, repos, chgset, diff_options)97 self._render_diff(req, repos, diff, chgset, diff_options) 67 98 return 68 99 elif format == 'zip': 69 self._render_zip(req, repos, chgset)100 self._render_zip(req, repos, diff, chgset) 70 101 return 71 102 72 self._render_html(req, repos, chgset, diff_options)103 self._render_html(req, repos, diff, chgset, diff_options) 73 104 add_link(req, 'alternate', '?format=diff', 'Unified Diff', 74 105 'text/plain', 'diff') 75 106 add_link(req, 'alternate', '?format=zip', 'Zip Archive', 76 107 'application/zip', 'zip') 77 108 add_stylesheet(req, 'changeset.css') 78 109 add_stylesheet(req, 'diff.css') 79 return ' changeset.cs', None110 return 'diff.cs', None 80 111 81 # ITimelineEventProvider methods82 112 83 def get_timeline_filters(self, req):84 if req.perm.has_permission(perm.CHANGESET_VIEW):85 yield ('changeset', 'Repository checkins')86 87 def get_timeline_events(self, req, start, stop, filters):88 if 'changeset' in filters:89 absurls = req.args.get('format') == 'rss' # Kludge90 show_files = int(self.config.get('timeline',91 'changeset_show_files'))92 db = self.env.get_db_cnx()93 repos = self.env.get_repository()94 rev = repos.youngest_rev95 while rev:96 chgset = repos.get_changeset(rev)97 if chgset.date < start:98 return99 if chgset.date < stop:100 if absurls:101 href = self.env.abs_href.changeset(chgset.rev)102 else:103 href = self.env.href.changeset(chgset.rev)104 title = 'Changeset <em>[%s]</em> by %s' % (105 util.escape(chgset.rev), util.escape(chgset.author))106 message = wiki_to_oneliner(util.shorten_line(chgset.message or '--'),107 self.env, db, absurls=absurls)108 if show_files:109 files = []110 for chg in chgset.get_changes():111 if show_files > 0 and len(files) >= show_files:112 files.append('...')113 break114 files.append('<span class="%s">%s</span>'115 % (chg[2], util.escape(chg[0])))116 message = '<span class="changes">' + ', '.join(files) +\117 '</span>: ' + message118 yield 'changeset', href, title, chgset.date, chgset.author,\119 message120 rev = repos.previous_rev(rev)121 122 113 # Internal methods 123 114 124 def _render_html(self, req, repos, chgset, diff_options):115 def _render_html(self, req, repos, diff, chgset, diff_options): 125 116 """HTML version""" 126 req.hdf['title'] = '[%s]' % chgset.rev 127 req.hdf['changeset'] = { 128 'revision': chgset.rev, 129 'time': time.strftime('%c', time.localtime(chgset.date)), 130 'author': util.escape(chgset.author or 'anonymous'), 131 'message': wiki_to_html(chgset.message or '--', self.env, req, 132 escape_newlines=True) 133 } 117 req.hdf['diff'] = diff 118 req.hdf['diff.href'] = { 119 'new_rev': self.env.href.changeset(diff.new_rev), 120 'old_rev': self.env.href.changeset(diff.old_rev), 121 'new_path': self.env.href.browser(diff.new_path, rev=diff.new_rev), 122 'old_path': self.env.href.changeset(diff.old_path, rev=diff.old_rev) 123 } 124 if chgset: # 'path history' mode 125 req.hdf['title'] = 'Changes for %s at Revision %s' % (diff.new_path, chgset.rev) 126 req.hdf['changeset'] = { 127 'revision': chgset.rev, 128 'time': time.strftime('%c', time.localtime(chgset.date)), 129 'author': util.escape(chgset.author or 'anonymous'), 130 'message': wiki_to_html(chgset.message or '--', self.env, req, 131 escape_newlines=True) 132 } 134 133 135 oldest_rev = repos.oldest_rev 136 if chgset.rev != oldest_rev: 137 add_link(req, 'first', self.env.href.changeset(oldest_rev), 138 'Changeset %s' % oldest_rev) 139 previous_rev = repos.previous_rev(chgset.rev) 140 add_link(req, 'prev', self.env.href.changeset(previous_rev), 141 'Changeset %s' % previous_rev) 142 youngest_rev = repos.youngest_rev 143 if str(chgset.rev) != str(youngest_rev): 144 next_rev = repos.next_rev(chgset.rev) 145 add_link(req, 'next', self.env.href.changeset(next_rev), 146 'Changeset %s' % next_rev) 147 add_link(req, 'last', self.env.href.changeset(youngest_rev), 148 'Changeset %s' % youngest_rev) 134 oldest_rev = repos.oldest_rev 135 if chgset.rev != oldest_rev: 136 add_link(req, 'first', self.env.href.diff(diff.old_path, rev=oldest_rev), 137 'Changeset %s' % oldest_rev) # FIXME (use the history) 138 previous_rev = repos.previous_rev(chgset.rev) 139 add_link(req, 'prev', self.env.href.diff(diff.old_path, rev=previous_rev), 140 'Changeset %s' % previous_rev) 141 youngest_rev = repos.youngest_rev 142 if str(chgset.rev) != str(youngest_rev): 143 next_rev = repos.next_rev(chgset.rev) 144 add_link(req, 'next', self.env.href.diff(diff.new_path, rev=next_rev), 145 'Changeset %s' % next_rev) 146 add_link(req, 'last', self.env.href.diff(diff.new_path, rev=youngest_rev), 147 'Changeset %s' % youngest_rev) 148 elif diff.new_path == diff.old_path: # 'diff between 2 revisions' mode 149 req.hdf['title'] = 'Diff for %s between Revisions %s and %s' \ 150 % (diff.new_path, diff.old_rev, diff.new_rev) 151 else: # 'arbitrary diff' mode 152 req.hdf['title'] = 'Diff between %s at Revision %s and %s at Revision %s' \ 153 % (diff.old_path, diff.old_rev, 154 diff.new_path, diff.new_rev) 149 155 150 156 edits = [] 151 157 idx = 0 152 for path, kind, change, base_path, base_rev in chgset.get_changes(): 158 old_rev = diff.old_rev 159 new_rev = diff.new_rev 160 for old_path, new_path, kind, change in repos.get_diffs(**diff): 161 print 'delta %d: %s %s delta from %s@%s to %s@%s' \ 162 % (idx, change, kind, old_path, old_rev, new_path, new_rev) 153 163 info = {'change': change} 154 if base_path:155 info['path.old'] = base_path156 info['rev.old'] = base_rev157 info['browser_href.old'] = self.env.href.browser( base_path,158 rev= base_rev)159 if path:160 info['path.new'] = path161 info['rev.new'] = chgset.rev162 info['browser_href.new'] = self.env.href.browser( path,163 rev= chgset.rev)164 if old_path: 165 info['path.old'] = old_path 166 info['rev.old'] = old_rev 167 info['browser_href.old'] = self.env.href.browser(old_path, 168 rev=old_rev) 169 if new_path: 170 info['path.new'] = new_path 171 info['rev.new'] = new_rev 172 info['browser_href.new'] = self.env.href.browser(new_path, 173 rev=new_rev) 164 174 if change in (Changeset.COPY, Changeset.EDIT, Changeset.MOVE): 165 edits.append((idx, path, kind, base_path, base_rev))166 req.hdf[' changeset.changes.%d' % idx] = info175 edits.append((idx, old_path, new_path, kind)) 176 req.hdf['diff.changes.%d' % idx] = info 167 177 idx += 1 168 169 for idx, path, kind, base_path, base_revin edits:170 old_node = repos.get_node( base_path or path, base_rev)171 new_node = repos.get_node( path, chgset.rev)172 178 179 for idx, old_path, new_path, kind in edits: 180 old_node = repos.get_node(old_path, old_rev) 181 new_node = repos.get_node(new_path, new_rev) 182 173 183 # Property changes 174 184 old_props = old_node.get_properties() 175 185 new_props = new_node.get_properties() … … 183 193 for k,v in new_props.items(): 184 194 if not k in old_props: 185 195 changed_props[k] = {'new': v} 186 req.hdf[' changeset.changes.%d.props' % idx] = changed_props196 req.hdf['diff.changes.%d.props' % idx] = changed_props 187 197 188 198 if kind == Node.DIRECTORY: 189 199 continue 190 200 191 201 # Content changes 192 202 default_charset = self.config.get('trac', 'default_charset') 193 old_content = old_node.get_content().read() 203 old_content = old_node.get_content().read() 194 204 if mimeview.is_binary(old_content): 195 205 continue 196 206 charset = mimeview.get_charset(old_node.content_type) or \ … … 217 227 ignore_blank_lines='-B' in diff_options[1], 218 228 ignore_case='-i' in diff_options[1], 219 229 ignore_space_changes='-b' in diff_options[1]) 220 req.hdf[' changeset.changes.%d.diff' % idx] = changes230 req.hdf['diff.changes.%d.diff' % idx] = changes 221 231 222 def _render_diff(self, req, repos, chgset, diff_options): 232 233 def _render_diff(self, req, repos, chgset, diff_options): # TODO 223 234 """Raw Unified Diff version""" 224 235 req.send_response(200) 225 236 req.send_header('Content-Type', 'text/plain;charset=utf-8') … … 284 295 ignore_space_changes='-b' in diff_options[1]): 285 296 req.write(line + util.CRLF) 286 297 287 def _render_zip(self, req, repos, chgset): 298 def _render_zip(self, req, repos, chgset): # TODO 288 299 """ZIP archive with all the added and/or modified files.""" 289 300 req.send_response(200) 290 301 req.send_header('Content-Type', 'application/zip') -
trac/Browser.py
113 113 114 114 req.hdf['title'] = path 115 115 req.hdf['browser'] = { 116 'path': path,117 'revision': rev or repos.youngest_rev,116 'path': node.path, 117 'revision': node.rev, 118 118 'props': dict([(util.escape(name), util.escape(value)) 119 119 for name, value in node.get_properties().items()]), 120 'href': self.env.href.browser(path,rev=rev or repos.youngest_rev), 121 'log_href': self.env.href.log(path) 120 'href': self.env.href.browser(node.path,rev=node.rev), 121 'diff_href': self.env.href.diff(node.path,rev=node.rev), 122 'log_href': self.env.href.log(node.path) 122 123 } 123 124 124 125 path_links = _get_path_links(self.env.href, path, rev) … … 268 269 stop_rev = req.args.get('stop_rev') 269 270 verbose = req.args.get('verbose') 270 271 limit = int(req.args.get('limit') or 100) 272 old = req.args.get('old') 273 new = req.args.get('new') 274 select_for_diff = req.args.get('diff') 271 275 276 repos = self.env.get_repository(req.authname) 277 normpath = repos.normalize_path(path) 278 rev = str(repos.normalize_rev(rev)) 279 old = old or str(repos.previous_rev(rev)) 280 new = new or rev 281 272 282 req.hdf['title'] = path + ' (log)' 273 283 req.hdf['log'] = { 274 284 'path': path, … … 276 286 'verbose': verbose, 277 287 'stop_rev': stop_rev, 278 288 'browser_href': self.env.href.browser(path, rev=rev), 279 'log_href': self.env.href.log(path, rev=rev) 289 'log_href': self.env.href.log(path, rev=rev), 290 'diff_href': self.env.href.diff(path, old=old, new=new), 291 'old': old, 292 'new': new 280 293 } 281 294 295 if select_for_diff == "1": 296 req.session['diff_base_path'] = path 297 req.session['diff_base_rev'] = rev 298 299 if req.session.has_key('diff_base_path'): 300 if select_for_diff == "0": 301 del req.session['diff_base_path'] 302 del req.session['diff_base_rev'] 303 anydiff_href = self.env.href.diff(path,new=rev, 304 old_path=req.session['diff_base_path'], 305 old=req.session['diff_base_rev']) 306 req.hdf['log.anydiff_href'] = anydiff_href 307 req.hdf['session'] = { 308 'diff_base_path': req.session['diff_base_path'], 309 'diff_base_rev': req.session['diff_base_rev'] 310 } 311 282 312 path_links = _get_path_links(self.env.href, path, rev) 283 313 req.hdf['log.path'] = path_links 284 314 if path_links: 285 315 add_link(req, 'up', path_links[-1]['href'], 'Parent directory') 286 316 287 repos = self.env.get_repository(req.authname)288 normpath = repos.normalize_path(path)289 rev = str(repos.normalize_rev(rev))290 291 317 # 'node' or 'path' history: use get_node()/get_history() or get_path_history() 292 318 if mode != 'path_history': 293 319 try: -
templates/log.cs
3 3 4 4 <div id="ctxtnav" class="nav"> 5 5 <ul> 6 <li class="last"><a href="<?cs 7 var:log.browser_href ?>">View Latest Revision</a></li><?cs 6 <li class="last"> 7 <a href="<?cs var:log.browser_href ?>">View Latest Revision</a> 8 </li><?cs 8 9 if:len(chrome.links.prev) ?> 9 10 <li class="first<?cs if:!len(chrome.links.next) ?> last<?cs /if ?>"> 10 11 ← <a href="<?cs var:chrome.links.prev.0.href ?>" title="<?cs … … 74 75 </dl> 75 76 </div> 76 77 </div> 78 79 <div id="anydiff"><?cs 80 if:session.diff_base_path == log.path && session.diff_base_rev == log.rev ?> 81 <em>This Path/Revision is the Base for Diff</em><?cs 82 else ?><?cs 83 if:session.diff_base_path ?> 84 <form action="<?cs var:log.diff_href ?>" method="get"> 85 <input type="hidden" name="old_path" value="<?cs var:session.diff_base_path ?>" /> 86 <input type="hidden" name="old" value="<?cs var:session.diff_base_rev ?>" /> 87 <input type="hidden" name="new" value="<?cs var:log.rev ?>" /> 88 <div class="buttons"> 89 <input type="submit" value="Diff" 90 title="Diff the current Path/Revision against the selected Base" /> 91 </div> 92 </form> 93 against: <em><?cs var:session.diff_base_path ?></em> 94 in revision <em><?cs var:session.diff_base_rev ?></em> 95 <form action="<?cs var:log.log_href ?>" method="get"> 96 <input type="hidden" name="diff" value="0" /> 97 <div class="buttons"> 98 <input type="submit" value="Clear" 99 title="Clear the Base for Diff" /> 100 </div> 101 </form><?cs 102 /if ?> 103 <form action="<?cs var:log.log_href ?>" method="get"> 104 <input type="hidden" name="diff" value="1" /> 105 <div class="buttons"> 106 <input type="submit" 107 value="Set<?cs if:!session.diff_base_path ?> Base for Diff<?cs /if ?>" 108 title="Select the current Path/Revision as the new Base for Diff" /> 109 </div> 110 </form><?cs 111 /if ?> 112 </div> 113 77 114 <table id="chglist" class="listing"> 115 <form action="<?cs var:log.diff_href ?>" method="get"> 78 116 <thead> 117 <tr class="diff"> 118 <th colspan="2"> 119 <div class="buttons"><input type="submit" value="Diff" 120 title="Diff from Old Revision to New Revision (select them below)" /></div> 121 </th> 122 </tr> 79 123 <tr> 124 <th>Old</th> 125 <th>New</th> 80 126 <th class="change"></th> 81 127 <th class="data">Date</th> 82 128 <th class="rev">Rev</th> … … 87 133 </thead> 88 134 <tbody><?cs 89 135 set:indent = #1 ?><?cs 136 set:idx = #0 ?><?cs 90 137 each:item = log.items ?><?cs 91 138 if:item.copyfrom_path ?> 92 139 <tr class="<?cs if:name(item) % #2 ?>even<?cs else ?>odd<?cs /if ?>"> … … 99 146 set:indent = #1 ?><?cs 100 147 /if ?> 101 148 <tr class="<?cs if:name(item) % #2 ?>even<?cs else ?>odd<?cs /if ?>"> 149 <td><input type="radio" name="old" value="<?cs var:item.rev ?>" <?cs 150 if:idx == #1 ?> checked="checked" <?cs /if ?> /></td> 151 <td><input type="radio" name="new" value="<?cs var:item.rev ?>" <?cs 152 if:idx == #0 ?> checked="checked" <?cs /if ?> /></td> 102 153 <td class="change" style="padding-left:<?cs var:indent ?>em"> 103 154 <a title="View log starting at this revision" href="<?cs var:item.log_href ?>"> 104 155 <div class="<?cs var:item.change ?>"></div> … … 115 166 <td class="author"><?cs var:log.changes[item.rev].author ?></td> 116 167 <td class="summary"><?cs var:log.changes[item.rev].message ?></td> 117 168 </tr><?cs 169 set:idx = idx + 1 ?><?cs 118 170 /each ?> 119 171 </tbody> 172 </form> 120 173 </table><?cs 121 174 if:len(links.prev) || len(links.next) ?><div id="paging" class="nav"><ul><?cs 122 175 if:len(links.prev) ?><li class="first<?cs -
templates/browser.cs
3 3 4 4 <div id="ctxtnav" class="nav"> 5 5 <ul> 6 <li class="first"><a href="<?cs var:browser.diff_href ?>">Diff to previous</a></li> 6 7 <li class="last"><a href="<?cs var:browser.log_href ?>">Revision Log</a></li> 7 8 </ul> 8 9 </div> -
templates/diff.cs
2 2 <?cs include "macros.cs"?> 3 3 4 4 <div id="ctxtnav" class="nav"> 5 <h2> ChangesetNavigation</h2><?cs5 <h2>Diff Navigation</h2><?cs 6 6 with:links = chrome.links ?> 7 7 <ul><?cs 8 8 if:len(links.prev) ?> 9 9 <li class="first<?cs if:!len(links.next) ?> last<?cs /if ?>"> 10 10 <a class="prev" href="<?cs var:links.prev.0.href ?>" title="<?cs 11 var:links.prev.0.title ?>">Previous Changeset</a>11 var:links.prev.0.title ?>">Previous Diff</a> 12 12 </li><?cs 13 13 /if ?><?cs 14 14 if:len(links.next) ?> 15 15 <li class="<?cs if:len(links.prev) ?>first <?cs /if ?>last"> 16 16 <a class="next" href="<?cs var:links.next.0.href ?>" title="<?cs 17 var:links.next.0.title ?>">Next Changeset</a>17 var:links.next.0.title ?>">Next Diff</a> 18 18 </li><?cs 19 19 /if ?> 20 20 </ul><?cs … … 22 22 </div> 23 23 24 24 <div id="content" class="changeset"> 25 <h1>Changeset <?cs var:changeset.revision ?></h1> 25 <h1><?cs 26 if:len(changeset) > #0 ?> 27 Changes for <a title="Show entry in browser" href="<?cs var:diff.href.new_path ?>"> 28 <?cs var:diff.new_path ?></a> 29 in Revision <a title="Show full changeset" href="<?cs var:diff.href.new_rev ?>"> 30 <?cs var:diff.new_rev ?></a><?cs 31 elif:diff.new_path == diff.old_path ?> 32 Differences for <a title="Show entry in browser" href="<?cs var:diff.href.new_path ?>"> 33 <?cs var:diff.new_path ?></a> 34 between Revisions <a title="Show full changeset" href="<?cs var:diff.href.old_rev ?>"> 35 <?cs var:diff.old_rev ?></a> 36 and <a title="Show full changeset" href="<?cs var:diff.href.new_rev ?>"> 37 <?cs var:diff.new_rev ?></a><?cs 38 else ?> 39 Differences between <a title="Show entry in browser" href="<?cs var:diff.href.old_path ?>"> 40 <?cs var:diff.old_path ?></a> 41 at Revision <a title="Show full changeset" href="<?cs var:diff.href.old_rev ?>"> 42 <?cs var:diff.old_rev ?></a> 43 and <a title="Show entry in browser" href="<?cs var:diff.href.new_path ?>"> 44 <?cs var:diff.new_path ?></a> 45 at Revision <a title="Show full changeset" href="<?cs var:diff.href.new_rev ?>"> 46 <?cs var:diff.new_rev ?></a><?cs 47 /if ?> 48 </h1> 26 49 27 <?cs each:change = changeset.changes ?><?cs50 <?cs each:change = diff.changes ?><?cs 28 51 if:len(change.diff) ?><?cs 29 52 set:has_diffs = 1 ?><?cs 30 53 /if ?><?cs … … 32 55 || diff.options.ignorecase || diff.options.ignorewhitespace ?> 33 56 <form method="post" id="prefs" action=""> 34 57 <div> 58 <input type="hidden" name="old_path" value="<?cs var:diff.old_path ?>" /> 59 <input type="hidden" name="old" value="<?cs var:diff.old_rev ?>" /> 60 <input type="hidden" name="new" value="<?cs var:diff.new_rev ?>" /> 35 61 <label for="style">View differences</label> 36 62 <select id="style" name="style"> 37 63 <option value="inline"<?cs … … 100 126 /if ?> 101 127 <?cs /def ?> 102 128 103 <dl id="overview"> 129 <dl id="overview"><?cs 130 if:len(changeset) > #0 ?> 104 131 <dt class="time">Timestamp:</dt> 105 132 <dd class="time"><?cs var:changeset.time ?></dd> 106 133 <dt class="author">Author:</dt> 107 134 <dd class="author"><?cs var:changeset.author ?></dd> 108 135 <dt class="message">Message:</dt> 109 <dd class="message" id="searchable"><?cs var:changeset.message ?></dd> 136 <dd class="message" id="searchable"><?cs var:changeset.message ?></dd><?cs 137 /if ?> 110 138 <dt class="files">Files:</dt> 111 139 <dd class="files"> 112 <ul><?cs each:item = changeset.changes ?>140 <ul><?cs each:item = diff.changes ?> 113 141 <li><?cs 114 142 if:item.change == 'add' ?><?cs 115 143 call:node_change(item, 'add', 'added') ?><?cs … … 140 168 </dl> 141 169 </div> 142 170 <ul class="entries"><?cs 143 each:item = changeset.changes ?><?cs171 each:item = diff.changes ?><?cs 144 172 if:len(item.diff) || len(item.props) ?><li class="entry" id="file<?cs 145 173 var:name(item) ?>"><h2><a href="<?cs 146 174 var:item.browser_href.new ?>" title="Show new revision <?cs
