Ticket #2028: trac-diff-for-0.9.3.patch
| File trac-diff-for-0.9.3.patch, 50.7 KB (added by jeremie.corbier@…, 6 years ago) |
|---|
-
htdocs/css/browser.css
Seulement dans trac-0.9.3-trac-diff: build diff -ru trac-0.9.3/htdocs/css/browser.css trac-0.9.3-trac-diff/htdocs/css/browser.css
old new 46 46 #dirlist td.rev { text-align: right } 47 47 #dirlist td.change { font-size: 85%; vertical-align: middle; white-space: nowrap } 48 48 49 /* Log */ 50 tr.diff input { 51 padding: 0 1em 0 1em; 52 margin: 0; 53 } 54 55 div.buttons { 56 clear: left; 57 } 58 59 #anydiff { 60 margin: 0 0 1em; 61 float: left; 62 } 63 #anydiff form, #anydiff div, #anydiff h2 { 64 display: inline; 65 } 66 #anydiff input { 67 vertical-align: baseline; 68 margin: 0 -0.5em 0 1em; 69 } 70 71 49 72 /* Styles for the revision log table 50 73 (extends the styles for "table.listing") */ 51 74 #chglist { margin-top: 0 } -
htdocs/css/changeset.css
diff -ru trac-0.9.3/htdocs/css/changeset.css trac-0.9.3-trac-diff/htdocs/css/changeset.css
old new 26 26 27 27 .diff ul.props { font-size: 90%; list-style: disc; margin: .5em 0 0; padding: 0 .5em 1em 2em } 28 28 .diff ul.props li { margin: 0; padding: 0 } 29 30 31 #title dl { 32 display: inline; 33 font-size: 110% 34 } 35 #title dt { 36 font-size: 110%; 37 font-weight: bold; 38 display: inline; 39 margin-left: 3em; 40 } 41 #title dd { 42 display: inline; 43 margin-left: 0.4em; 44 } -
templates/browser.cs
Seulement dans trac-0.9.3-trac-diff/templates: anydiff.cs diff -ru trac-0.9.3/templates/browser.cs trac-0.9.3-trac-diff/templates/browser.cs
old new 3 3 4 4 <div id="ctxtnav" class="nav"> 5 5 <ul> 6 <li class="last"><a href="<?cs var:browser.log_href ?>">Revision Log</a></li> 6 <li class="first"><a href="<?cs var:browser.restr_changeset_href ?>"> 7 Last Change</a></li> 8 <li class="last"><a href="<?cs var:browser.log_href ?>"> 9 Revision Log</a></li> 7 10 </ul> 8 11 </div> 9 12 13 10 14 <div id="content" class="browser"> 11 15 <h1><?cs call:browser_path_links(browser.path, browser) ?></h1> 12 16 13 17 <div id="jumprev"> 14 <form action="" method="get"><div> 15 <label for="rev">View revision:</label> 16 <input type="text" id="rev" name="rev" value="<?cs 17 var:browser.revision ?>" size="4" /> 18 </div></form> 18 <form action="" method="get"> 19 <div> 20 <label for="rev">View revision:</label> 21 <input type="text" id="rev" name="rev" value="<?cs 22 var:browser.revision ?>" size="4" /> 23 </div> 24 </form> 19 25 </div> 20 26 21 27 <?cs if:browser.is_dir ?> … … 114 120 ?>/TracBrowser">TracBrowser</a> for help on using the browser. 115 121 </div> 116 122 123 <div id="anydiff"><?cs 124 if len(browser.path) > #1 ?> 125 <form action="<?cs var:browser.anydiff_href ?>" method="get"> 126 <input type="hidden" name="new_path" value="<?cs var:browser.path ?>" /> 127 <input type="hidden" name="old_path" value="<?cs var:browser.path ?>" /> 128 <input type="hidden" name="new_rev" value="<?cs var:browser.revision ?>" /> 129 <input type="hidden" name="old_rev" value="<?cs var:browser.revision ?>" /> 130 <div class="buttons"> 131 <input type="submit" value="View changes..." title="Prepare an Arbitrary Diff" /> 132 </div> 133 </form><?cs 134 /if ?> 135 </div> 136 117 137 </div> 118 138 <?cs include:"footer.cs"?> -
templates/changeset.cs
diff -ru trac-0.9.3/templates/changeset.cs trac-0.9.3-trac-diff/templates/changeset.cs
old new 1 <?cs include "header.cs"?>2 <?cs include "macros.cs"?>3 4 <div id="ctxtnav" class="nav">5 <h2>Changeset Navigation</h2><?cs6 with:links = chrome.links ?>7 <ul><?cs8 if:len(links.prev) ?>9 <li class="first<?cs if:!len(links.next) ?> last<?cs /if ?>">10 ← <a class="prev" href="<?cs var:links.prev.0.href ?>" title="<?cs11 var:links.prev.0.title ?>">Previous Changeset</a>12 </li><?cs13 /if ?><?cs14 if:len(links.next) ?>15 <li class="<?cs if:len(links.prev) ?>first <?cs /if ?>last">16 <a class="next" href="<?cs var:links.next.0.href ?>" title="<?cs17 var:links.next.0.title ?>">Next Changeset</a> →18 </li><?cs19 /if ?>20 </ul><?cs21 /with ?>22 </div>23 24 <div id="content" class="changeset">25 <h1>Changeset <?cs var:changeset.revision ?></h1>26 27 <?cs each:change = changeset.changes ?><?cs28 if:len(change.diff) ?><?cs29 set:has_diffs = 1 ?><?cs30 /if ?><?cs31 /each ?><?cs if:has_diffs || diff.options.ignoreblanklines32 || diff.options.ignorecase || diff.options.ignorewhitespace ?>33 <form method="post" id="prefs" action="">34 <div>35 <label for="style">View differences</label>36 <select id="style" name="style">37 <option value="inline"<?cs38 if:diff.style == 'inline' ?> selected="selected"<?cs39 /if ?>>inline</option>40 <option value="sidebyside"<?cs41 if:diff.style == 'sidebyside' ?> selected="selected"<?cs42 /if ?>>side by side</option>43 </select>44 <div class="field">45 Show <input type="text" name="contextlines" id="contextlines" size="2"46 maxlength="3" value="<?cs var:diff.options.contextlines ?>" />47 <label for="contextlines">lines around each change</label>48 </div>49 <fieldset id="ignore">50 <legend>Ignore:</legend>51 <div class="field">52 <input type="checkbox" id="blanklines" name="ignoreblanklines"<?cs53 if:diff.options.ignoreblanklines ?> checked="checked"<?cs /if ?> />54 <label for="blanklines">Blank lines</label>55 </div>56 <div class="field">57 <input type="checkbox" id="case" name="ignorecase"<?cs58 if:diff.options.ignorecase ?> checked="checked"<?cs /if ?> />59 <label for="case">Case changes</label>60 </div>61 <div class="field">62 <input type="checkbox" id="whitespace" name="ignorewhitespace"<?cs63 if:diff.options.ignorewhitespace ?> checked="checked"<?cs /if ?> />64 <label for="whitespace">White space changes</label>65 </div>66 </fieldset>67 <div class="buttons">68 <input type="submit" name="update" value="Update" />69 </div>70 </div>71 </form><?cs /if ?>72 73 <?cs def:node_change(item,cl,kind) ?><?cs74 set:ndiffs = len(item.diff) ?><?cs75 set:nprops = len(item.props) ?>76 <div class="<?cs var:cl ?>"></div><?cs77 if:cl == "rem" ?>78 <a title="Show what was removed (rev. <?cs var:item.rev.old ?>)" href="<?cs79 var:item.browser_href.old ?>"><?cs var:item.path.old ?></a><?cs80 else ?>81 <a title="Show entry in browser" href="<?cs82 var:item.browser_href.new ?>"><?cs var:item.path.new ?></a><?cs83 /if ?>84 <span class="comment">(<?cs var:kind ?>)</span><?cs85 if:item.path.old && item.change == 'copy' || item.change == 'move' ?>86 <small><em>(<?cs var:kind ?> from <a href="<?cs87 var:item.browser_href.old ?>" title="Show original file (rev. <?cs88 var:item.rev.old ?>)"><?cs var:item.path.old ?></a>)</em></small><?cs89 /if ?><?cs90 if:$ndiffs + $nprops > #0 ?>91 (<a href="#file<?cs var:name(item) ?>" title="Show differences"><?cs92 if:$ndiffs > #0 ?><?cs var:ndiffs ?> diff<?cs if:$ndiffs > #1 ?>s<?cs /if ?><?cs93 /if ?><?cs94 if:$ndiffs && $nprops ?>, <?cs /if ?><?cs95 if:$nprops > #0 ?><?cs var:nprops ?> prop<?cs if:$nprops > #1 ?>s<?cs /if ?><?cs96 /if ?></a>)<?cs97 elif:cl == "mod" ?>98 (<a href="<?cs var:item.browser_href.old ?>"99 title="Show previous version in browser">previous</a>)<?cs100 /if ?>101 <?cs /def ?>102 103 <dl id="overview">104 <dt class="time">Timestamp:</dt>105 <dd class="time"><?cs var:changeset.time ?></dd>106 <dt class="author">Author:</dt>107 <dd class="author"><?cs var:changeset.author ?></dd>108 <dt class="message">Message:</dt>109 <dd class="message" id="searchable"><?cs110 alt:changeset.message ?> <?cs /alt ?></dd>111 <dt class="files">Files:</dt>112 <dd class="files">113 <ul><?cs each:item = changeset.changes ?>114 <li><?cs115 if:item.change == 'add' ?><?cs116 call:node_change(item, 'add', 'added') ?><?cs117 elif:item.change == 'delete' ?><?cs118 call:node_change(item, 'rem', 'deleted') ?><?cs119 elif:item.change == 'copy' ?><?cs120 call:node_change(item, 'cp', 'copied') ?><?cs121 elif:item.change == 'move' ?><?cs122 call:node_change(item, 'mv', 'moved') ?><?cs123 elif:item.change == 'edit' ?><?cs124 call:node_change(item, 'mod', 'modified') ?><?cs125 /if ?>126 </li>127 <?cs /each ?></ul>128 </dd>129 </dl>130 131 <div class="diff">132 <div id="legend">133 <h3>Legend:</h3>134 <dl>135 <dt class="unmod"></dt><dd>Unmodified</dd>136 <dt class="add"></dt><dd>Added</dd>137 <dt class="rem"></dt><dd>Removed</dd>138 <dt class="mod"></dt><dd>Modified</dd>139 <dt class="cp"></dt><dd>Copied</dd>140 <dt class="mv"></dt><dd>Moved</dd>141 </dl>142 </div>143 <ul class="entries"><?cs144 each:item = changeset.changes ?><?cs145 if:len(item.diff) || len(item.props) ?><li class="entry" id="file<?cs146 var:name(item) ?>"><h2><a href="<?cs147 var:item.browser_href.new ?>" title="Show new revision <?cs148 var:item.rev.new ?> of this file in browser"><?cs149 var:item.path.new ?></a></h2><?cs150 if:len(item.props) ?><ul class="props"><?cs151 each:prop = item.props ?><li>Property <strong><?cs152 var:name(prop) ?></strong> <?cs153 if:prop.old && prop.new ?>changed from <?cs154 elif:!prop.old ?>set<?cs155 else ?>deleted<?cs156 /if ?><?cs157 if:prop.old && prop.new ?><em><tt><?cs var:prop.old ?></tt></em><?cs /if ?><?cs158 if:prop.new ?> to <em><tt><?cs var:prop.new ?></tt></em><?cs /if ?></li><?cs159 /each ?></ul><?cs160 /if ?><?cs161 if:len(item.diff) ?><table class="<?cs162 var:diff.style ?>" summary="Differences" cellspacing="0"><?cs163 if:diff.style == 'sidebyside' ?>164 <colgroup class="l"><col class="lineno" /><col class="content" /></colgroup>165 <colgroup class="r"><col class="lineno" /><col class="content" /></colgroup>166 <thead><tr>167 <th colspan="2"><a href="<?cs168 var:item.browser_href.old ?>" title="Show old rev. <?cs169 var:item.rev.old ?> of <?cs var:item.path.old ?>">Revision <?cs170 var:item.rev.old ?></a></th>171 <th colspan="2"><a href="<?cs172 var:item.browser_href.new ?>" title="Show new rev. <?cs173 var:item.rev.new ?> of <?cs var:item.path.new ?>">Revision <?cs174 var:item.rev.new ?></a></th>175 </tr>176 </thead><?cs177 each:change = item.diff ?><tbody><?cs178 call:diff_display(change, diff.style) ?></tbody><?cs179 if:name(change) < len(item.diff) - 1 ?><tbody class="skipped"><tr>180 <th>…</th><td> </td><th>…</th><td> </td>181 </tr></tbody><?cs /if ?><?cs182 /each ?><?cs183 else ?>184 <colgroup><col class="lineno" /><col class="lineno" /><col class="content" /></colgroup>185 <thead><tr>186 <th title="Revision <?cs var:item.rev.old ?>"><a href="<?cs187 var:item.browser_href.old ?>" title="Show old version of <?cs188 var:item.path.old ?>">r<?cs var:item.rev.old ?></a></th>189 <th title="Revision <?cs var:item.rev.new ?>"><a href="<?cs190 var:item.browser_href.new ?>" title="Show new version of <?cs191 var:item.path.new ?>">r<?cs var:item.rev.new ?></a></th>192 <th> </th></tr>193 </thead><?cs194 each:change = item.diff ?><?cs195 call:diff_display(change, diff.style) ?><?cs196 if:name(change) < len(item.diff) - 1 ?><tbody class="skipped"><tr>197 <th>…</th><th>…</th><td> </td>198 </tr></tbody><?cs /if ?><?cs199 /each ?><?cs200 /if ?></table><?cs201 /if ?></li><?cs202 /if ?><?cs203 /each ?></ul>204 </div>205 206 </div>207 <?cs include "footer.cs"?> -
templates/log.cs
Seulement dans trac-0.9.3-trac-diff/templates: diff.cs diff -ru trac-0.9.3/templates/log.cs trac-0.9.3-trac-diff/templates/log.cs
old new 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 … … 61 62 title="Warning: by updating, you will clear the page history" /> 62 63 </div> 63 64 </form> 65 64 66 <div class="diff"> 65 67 <div id="legend"> 66 68 <h3>Legend:</h3> … … 74 76 </dl> 75 77 </div> 76 78 </div> 79 80 <form action="<?cs var:log.href ?>" method="post"> 81 <div class="buttons"><input type="submit" value="View changes" 82 title="Diff from Old Revision to New Revision (select them below)" /> 83 </div> 77 84 <table id="chglist" class="listing"> 78 85 <thead> 79 86 <tr> 87 <th>Old</th> 88 <th>New</th> 80 89 <th class="change"></th> 81 90 <th class="data">Date</th> 82 91 <th class="rev">Rev</th> … … 87 96 </thead> 88 97 <tbody><?cs 89 98 set:indent = #1 ?><?cs 99 set:idx = #0 ?><?cs 90 100 each:item = log.items ?><?cs 91 101 if:item.copyfrom_path ?> 92 102 <tr class="<?cs if:name(item) % #2 ?>even<?cs else ?>odd<?cs /if ?>"> 93 <td class="copyfrom_path" colspan=" 6" style="padding-left: <?cs var:indent ?>em">103 <td class="copyfrom_path" colspan="8" style="padding-left: <?cs var:indent ?>em"> 94 104 copied from <a href="<?cs var:item.browser_href ?>"?><?cs var:item.copyfrom_path ?></a>: 95 105 </td> 96 106 </tr><?cs … … 99 109 set:indent = #1 ?><?cs 100 110 /if ?> 101 111 <tr class="<?cs if:name(item) % #2 ?>even<?cs else ?>odd<?cs /if ?>"> 112 <td><input type="radio" name="old" 113 value="<?cs var:item.path ?>#<?cs var:item.rev ?>" <?cs 114 if:idx == #1 ?> checked="checked" <?cs /if ?> /></td> 115 <td><input type="radio" name="new" 116 value="<?cs var:item.path ?>#<?cs var:item.rev ?>" <?cs 117 if:idx == #0 ?> checked="checked" <?cs /if ?> /></td> 102 118 <td class="change" style="padding-left:<?cs var:indent ?>em"> 103 119 <a title="View log starting at this revision" href="<?cs var:item.log_href ?>"> 104 120 <span class="<?cs var:item.change ?>"></span> … … 117 133 <td class="author"><?cs var:log.changes[item.rev].author ?></td> 118 134 <td class="summary"><?cs var:log.changes[item.rev].message ?></td> 119 135 </tr><?cs 136 set:idx = idx + 1 ?><?cs 120 137 /each ?> 121 138 </tbody> 122 </table><?cs 139 </table> 140 <div class="buttons"><input type="submit" value="View changes" 141 title="Diff from Old Revision to New Revision (select them above)" /> 142 </div> 143 </form><?cs 123 144 if:len(links.prev) || len(links.next) ?><div id="paging" class="nav"><ul><?cs 124 145 if:len(links.prev) ?><li class="first<?cs 125 146 if:!len(links.next) ?> last<?cs /if ?>">← <a href="<?cs -
templates/wiki.cs
diff -ru trac-0.9.3/templates/wiki.cs trac-0.9.3-trac-diff/templates/wiki.cs
old new 154 154 var:wiki.page_name ?></a></h1> 155 155 <?cs if:len(wiki.history) ?><form method="get" action=""> 156 156 <input type="hidden" name="action" value="diff" /> 157 <div class="buttons"> 158 <input type="submit" value="View changes" /> 159 </div> 157 160 <table id="wikihist" class="listing" summary="Change history"> 158 161 <thead><tr> 159 162 <th class="diff"></th> -
trac/__init__.py
diff -ru trac-0.9.3/trac/__init__.py trac-0.9.3-trac-diff/trac/__init__.py
old new 10 10 """ 11 11 __docformat__ = 'epytext en' 12 12 13 __version__ = '0.9.3 '13 __version__ = '0.9.3-trac-diff' 14 14 __url__ = 'http://trac.edgewall.com/' 15 15 __copyright__ = '(C) 2003-2006 Edgewall Software' 16 16 __license__ = 'BSD' -
trac/siteconfig.py
Seulement dans trac-0.9.3-trac-diff/trac: __init__.pyc diff -ru trac-0.9.3/trac/siteconfig.py trac-0.9.3-trac-diff/trac/siteconfig.py
old new 1 1 2 2 # PLEASE DO NOT EDIT THIS FILE! 3 # This file was autogenerated when installing Trac 0.9. 2.3 # This file was autogenerated when installing Trac 0.9.3-trac-diff. 4 4 # 5 5 __default_conf_dir__ = '/usr/share/trac/conf' 6 6 __default_templates_dir__ = '/usr/share/trac/templates' -
trac/versioncontrol/api.py
diff -ru trac-0.9.3/trac/versioncontrol/api.py trac-0.9.3-trac-diff/trac/versioncontrol/api.py
old new 122 122 'None' is a valid revision value and represents the youngest revision. 123 123 """ 124 124 return NotImplementedError 125 125 126 def get_changes(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 127 """ 128 Generator that yields change tuples (old_node, new_node, kind, change) 129 for each node change between the two arbitrary (path,rev) pairs. 130 131 The old_node is assumed to be None when the change is an ADD, 132 the new_node is assumed to be None when the change is a DELETE. 133 """ 134 raise NotImplementedError 135 126 136 127 137 class Node(object): 128 138 """ … … 164 174 """ 165 175 raise NotImplementedError 166 176 177 def get_previous(self): 178 """ 179 Return the (path, rev, chg) tuple corresponding to the previous 180 revision for that node. 181 """ 182 skip = True 183 for p in self.get_history(2): 184 if skip: 185 skip = False 186 else: 187 return p 188 167 189 def get_properties(self): 168 190 """ 169 191 Returns a dictionary containing the properties (meta-data) of the node. -
trac/versioncontrol/cache.py
diff -ru trac-0.9.3/trac/versioncontrol/cache.py trac-0.9.3-trac-diff/trac/versioncontrol/cache.py
old new 129 129 def normalize_rev(self, rev): 130 130 return self.repos.normalize_rev(rev) 131 131 132 def get_changes(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 133 return self.repos.get_changes(old_path, old_rev, new_path, new_rev, ignore_ancestry) 134 132 135 133 136 class CachedChangeset(Changeset): 134 137 -
trac/versioncontrol/diff.py
diff -ru trac-0.9.3/trac/versioncontrol/diff.py trac-0.9.3-trac-diff/trac/versioncontrol/diff.py
old new 217 217 ignore_space_changes) 218 218 for group in _group_opcodes(opcodes, context): 219 219 i1, i2, j1, j2 = group[0][1], group[-1][2], group[0][3], group[-1][4] 220 if i1 == 0 and i2 == 0: 221 i1, i2 = -1, -1 # support for 'A'dd changes 220 222 yield '@@ -%d,%d +%d,%d @@' % (i1 + 1, i2 - i1, j1 + 1, j2 - j1) 221 223 for tag, i1, i2, j1, j2 in group: 222 224 if tag == 'equal': -
trac/versioncontrol/svn_fs.py
diff -ru trac-0.9.3/trac/versioncontrol/svn_fs.py trac-0.9.3-trac-diff/trac/versioncontrol/svn_fs.py
old new 346 346 expect_deletion = True 347 347 rev = self.previous_rev(rev) 348 348 349 def get_changes(self, old_path, old_rev, new_path, new_rev, 350 ignore_ancestry=0): 351 old_node = new_node = None 352 old_rev = self.normalize_rev(old_rev) 353 new_rev = self.normalize_rev(new_rev) 354 if self.has_node(old_path, old_rev): 355 old_node = self.get_node(old_path, old_rev) 356 else: 357 raise TracError, ('The Base for Diff is invalid: path %s' 358 ' doesn\'t exist in revision %s' \ 359 % (old_path, old_rev)) 360 if self.has_node(new_path, new_rev): 361 new_node = self.get_node(new_path, new_rev) 362 else: 363 raise TracError, ('The Target for Diff is invalid: path %s' 364 ' doesn\'t exist in revision %s' \ 365 % (new_path, new_rev)) 366 if new_node.kind != old_node.kind: 367 raise TracError, ('Diff mismatch: Base is a %s (%s in revision %s) ' 368 'and Target is a %s (%s in revision %s).' \ 369 % (old_node.kind, old_path, old_rev, 370 new_node.kind, new_path, new_rev)) 371 subpool = Pool(self.pool) 372 if new_node.isdir: 373 editor = DiffChangeEditor() 374 e_ptr, e_baton = delta.make_editor(editor, subpool()) 375 old_root = fs.revision_root(self.fs_ptr, old_rev, subpool()) 376 new_root = fs.revision_root(self.fs_ptr, new_rev, subpool()) 377 def authz_cb(root, path, pool): return 1 378 text_deltas = 0 # as this is anyway re-done in Diff.py... 379 entry_props = 0 # "... typically used only for working copy updates" 380 repos.svn_repos_dir_delta(old_root, 381 (self.scope + old_path).strip('/'), '', 382 new_root, 383 (self.scope + new_path).strip('/'), 384 e_ptr, e_baton, authz_cb, 385 text_deltas, 386 1, # directory 387 entry_props, 388 ignore_ancestry, 389 subpool()) 390 for path, kind, change in editor.deltas: 391 old_node = new_node = None 392 if change != Changeset.ADD: 393 old_node = self.get_node(posixpath.join(old_path, path), 394 old_rev) 395 if change != Changeset.DELETE: 396 new_node = self.get_node(posixpath.join(new_path, path), 397 new_rev) 398 else: 399 kind = _kindmap[fs.check_path(old_root, 400 self.scope + old_node.path, 401 subpool())] 402 yield (old_node, new_node, kind, change) 403 else: 404 old_root = fs.revision_root(self.fs_ptr, old_rev, subpool()) 405 new_root = fs.revision_root(self.fs_ptr, new_rev, subpool()) 406 if fs.contents_changed(old_root, self.scope + old_path, 407 new_root, self.scope + new_path, 408 subpool()): 409 yield (old_node, new_node, Node.FILE, Changeset.EDIT) 410 349 411 350 412 class SubversionNode(Node): 351 413 … … 368 430 self.pool()) 369 431 self.created_path = fs.node_created_path(self.root, self.scoped_path, 370 432 self.pool()) 371 # 'created_path' differs from 'path' if the last operation is a copy, 372 # and furthermore, 'path' might not exist at 'create_rev' 433 # Note: 'created_path' differs from 'path' if the last change was a copy, 434 # and furthermore, 'path' might not exist at 'create_rev'. 435 # The only guarantees are: 436 # * this node exists at (path,rev) 437 # * the node existed at (created_path,created_rev) 438 # TODO: check node id 373 439 self.rev = self.created_rev 374 440 375 441 Node.__init__(self, path, self.rev, _kindmap[node_type]) … … 414 480 if newer: 415 481 yield newer 416 482 483 # def get_previous(self): 484 # # FIXME: redo it with fs.node_history 485 417 486 def get_properties(self): 418 487 props = fs.node_proplist(self.root, self.scoped_path, self.pool()) 419 488 for name,value in props.items(): … … 513 582 514 583 def _get_prop(self, name): 515 584 return fs.revision_prop(self.fs_ptr, self.rev, name, self.pool()) 585 586 587 # 588 # Delta editor for diffs between arbitrary nodes 589 # 590 # Note 1: the 'copyfrom_path' and 'copyfrom_rev' information is not used 591 # because 'repos.svn_repos_dir_delta' *doesn't* provide it. 592 # 593 # Note 2: the 'dir_baton' is the path of the parent directory 594 # 595 596 class DiffChangeEditor(delta.Editor): 597 598 def __init__(self): 599 self.deltas = [] 600 601 # -- svn.delta.Editor callbacks 602 603 def open_root(self, base_revision, dir_pool): 604 return ('/', Changeset.EDIT) 605 606 def add_directory(self, path, dir_baton, copyfrom_path, copyfrom_rev, 607 dir_pool): 608 self.deltas.append((path, Node.DIRECTORY, Changeset.ADD)) 609 return (path, Changeset.ADD) 610 611 def open_directory(self, path, dir_baton, base_revision, dir_pool): 612 return (path, dir_baton[1]) 613 614 def change_dir_prop(self, dir_baton, name, value, pool): 615 path, change = dir_baton 616 if change != Changeset.ADD: 617 self.deltas.append((path, Node.DIRECTORY, change)) 618 619 def delete_entry(self, path, revision, dir_baton, pool): 620 self.deltas.append((path, None, Changeset.DELETE)) 621 622 def add_file(self, path, dir_baton, copyfrom_path, copyfrom_revision, 623 dir_pool): 624 self.deltas.append((path, Node.FILE, Changeset.ADD)) 625 626 def open_file(self, path, dir_baton, dummy_rev, file_pool): 627 self.deltas.append((path, Node.FILE, Changeset.EDIT)) 628 -
trac/versioncontrol/tests/svn_fs.py
diff -ru trac-0.9.3/trac/versioncontrol/tests/svn_fs.py trac-0.9.3-trac-diff/trac/versioncontrol/tests/svn_fs.py
old new 221 221 self.assertEqual(('tags/v1', 7, 'unknown'), history.next()) 222 222 self.assertRaises(StopIteration, history.next) 223 223 224 # Diffs 225 226 def _cmp_diff(self, expected, got): 227 if expected[0]: 228 old = self.repos.get_node(*expected[0]) 229 self.assertEqual((old.path, old.rev), (got[0].path, got[0].rev)) 230 if expected[1]: 231 new = self.repos.get_node(*expected[1]) 232 self.assertEqual((new.path, new.rev), (got[1].path, got[1].rev)) 233 self.assertEqual(expected[2], (got[2], got[3])) 234 235 def test_diff_file_different_revs(self): 236 diffs = self.repos.get_changes('trunk/README.txt', 2, 'trunk/README.txt', 3) 237 self._cmp_diff((('trunk/README.txt', 2), 238 ('trunk/README.txt', 3), 239 (Node.FILE, Changeset.EDIT)), diffs.next()) 240 self.assertRaises(StopIteration, diffs.next) 241 242 def test_diff_file_different_files(self): 243 diffs = self.repos.get_changes('branches/v1x/README.txt', 12, 244 'branches/v1x/README2.txt', 12) 245 self._cmp_diff((('branches/v1x/README.txt', 12), 246 ('branches/v1x/README2.txt', 12), 247 (Node.FILE, Changeset.EDIT)), diffs.next()) 248 self.assertRaises(StopIteration, diffs.next) 249 250 def test_diff_file_no_change(self): 251 diffs = self.repos.get_changes('trunk/README.txt', 7, 252 'tags/v1/README.txt', 7) 253 self.assertRaises(StopIteration, diffs.next) 254 255 def test_diff_dir_different_revs(self): 256 diffs = self.repos.get_changes('trunk', 4, 'trunk', 8) 257 self._cmp_diff((None, ('trunk/dir1/dir2', 8), 258 (Node.DIRECTORY, Changeset.ADD)), diffs.next()) 259 self._cmp_diff((None, ('trunk/dir1/dir3', 8), 260 (Node.DIRECTORY, Changeset.ADD)), diffs.next()) 261 self._cmp_diff((None, ('trunk/README2.txt', 6), 262 (Node.FILE, Changeset.ADD)), diffs.next()) 263 self._cmp_diff((('trunk/dir2', 4), None, 264 (Node.DIRECTORY, Changeset.DELETE)), diffs.next()) 265 self._cmp_diff((('trunk/dir3', 4), None, 266 (Node.DIRECTORY, Changeset.DELETE)), diffs.next()) 267 self.assertRaises(StopIteration, diffs.next) 268 269 def test_diff_dir_different_dirs(self): 270 diffs = self.repos.get_changes('trunk', 1, 'branches/v1x', 12) 271 self._cmp_diff((None, ('branches/v1x/dir1', 12), 272 (Node.DIRECTORY, Changeset.ADD)), diffs.next()) 273 self._cmp_diff((None, ('branches/v1x/dir1/dir2', 12), 274 (Node.DIRECTORY, Changeset.ADD)), diffs.next()) 275 self._cmp_diff((None, ('branches/v1x/dir1/dir3', 12), 276 (Node.DIRECTORY, Changeset.ADD)), diffs.next()) 277 self._cmp_diff((None, ('branches/v1x/README.txt', 12), 278 (Node.FILE, Changeset.ADD)), diffs.next()) 279 self._cmp_diff((None, ('branches/v1x/README2.txt', 12), 280 (Node.FILE, Changeset.ADD)), diffs.next()) 281 self.assertRaises(StopIteration, diffs.next) 282 283 def test_diff_dir_no_change(self): 284 diffs = self.repos.get_changes('trunk', 7, 285 'tags/v1', 7) 286 self.assertRaises(StopIteration, diffs.next) 287 288 # Changesets 289 224 290 def test_changeset_repos_creation(self): 225 291 chgset = self.repos.get_changeset(0) 226 292 self.assertEqual(0, chgset.rev) -
trac/versioncontrol/web_ui/browser.py
diff -ru trac-0.9.3/trac/versioncontrol/web_ui/browser.py trac-0.9.3-trac-diff/trac/versioncontrol/web_ui/browser.py
old new 91 91 92 92 repos = self.env.get_repository(req.authname) 93 93 node = get_existing_node(self.env, repos, path, rev) 94 rev = repos.normalize_rev(rev) 94 95 95 96 hidden_properties = [p.strip() for p 96 97 in self.config.get('browser', 'hide_properties', 97 98 'svk:merge').split(',')] 99 98 100 req.hdf['title'] = path 99 req.hdf['browser']= {101 browser_hdf = { 100 102 'path': path, 101 'revision': rev or repos.youngest_rev,103 'revision': rev, 102 104 'props': dict([(name, value) 103 105 for name, value in node.get_properties().items() 104 if not name in hidden_properties]), 105 'href': self.env.href.browser(path, rev=rev or 106 repos.youngest_rev), 107 'log_href': self.env.href.log(path, rev=rev or None) 108 } 106 if not name in hidden_properties]) 107 } 108 browser_hrefs = { 109 'href': self.env.href.browser(path, rev=rev), 110 'restr_changeset_href': self.env.href.changeset(node.rev, path), 111 'anydiff_href': self.env.href.anydiff(), 112 'log_href': self.env.href.log(path, rev=rev) 113 } 114 browser_hdf.update(dict([(key, util.escape(href)) for key, href in 115 browser_hrefs.items()])) 116 req.hdf['browser'] = browser_hdf 109 117 110 118 path_links = get_path_links(self.env.href, path, rev) 111 119 if len(path_links) > 1: … … 165 173 166 174 req.hdf['browser.items'] = info 167 175 req.hdf['browser.changes'] = changes 168 176 if node.path != '': 177 zip_href = self.env.href.diff(node.path, new=rev, old=rev, 178 old_path='/', # special case (#238) 179 format='zip') 180 add_link(req, 'alternate', zip_href, 'Zip Archive', 181 'application/zip', 'zip') 182 183 169 184 def _render_file(self, req, repos, node, rev=None): 170 185 req.perm.assert_permission('FILE_VIEW') 171 186 -
trac/versioncontrol/web_ui/changeset.py
diff -ru trac-0.9.3/trac/versioncontrol/web_ui/changeset.py trac-0.9.3-trac-diff/trac/versioncontrol/web_ui/changeset.py
old new 22 22 23 23 from trac import mimeview, util 24 24 from trac.core import * 25 from trac.perm import IPermissionRequestor26 25 from trac.Search import ISearchSource, query_to_sql, shorten_result 27 26 from trac.Timeline import ITimelineEventProvider 28 27 from trac.versioncontrol import Changeset, Node 29 28 from trac.versioncontrol.svn_authz import SubversionAuthorizer 30 from trac.versioncontrol.diff import get_diff_options, hdf_diff, unified_diff31 29 from trac.web import IRequestHandler 32 from trac.web.chrome import add_link, add_stylesheet,INavigationContributor30 from trac.web.chrome import INavigationContributor 33 31 from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider 32 from trac.versioncontrol.web_ui.diff import AbstractDiffModule 34 33 34 class ChangesetModule(AbstractDiffModule): 35 35 36 class ChangesetModule(Component): 37 38 implements(INavigationContributor, IPermissionRequestor, IRequestHandler, 36 implements(INavigationContributor, 39 37 ITimelineEventProvider, IWikiSyntaxProvider, ISearchSource) 40 38 41 39 # INavigationContributor methods … … 46 44 def get_navigation_items(self, req): 47 45 return [] 48 46 49 # IPermissionRequestor methods 50 51 def get_permission_actions(self): 52 return ['CHANGESET_VIEW'] 53 54 # IRequestHandler methods 47 # (reimplemented) IRequestHandler methods 55 48 56 49 def match_request(self, req): 57 match = re.match(r'/changeset/([0-9]+) $', req.path_info)50 match = re.match(r'/changeset/([0-9]+)(/.*)?$', req.path_info) 58 51 if match: 59 52 req.args['rev'] = match.group(1) 53 path = match.group(2) 54 if path: 55 req.args['path'] = path 60 56 return 1 61 57 62 def process_request(self, req):63 req.perm.assert_permission('CHANGESET_VIEW')64 65 rev = req.args.get('rev')66 repos = self.env.get_repository(req.authname)67 authzperm = SubversionAuthorizer(self.env, req.authname)68 authzperm.assert_permission_for_changeset(rev)69 70 diff_options = get_diff_options(req)71 if req.args.has_key('update'):72 req.redirect(self.env.href.changeset(rev))73 74 chgset = repos.get_changeset(rev)75 req.check_modified(chgset.date,76 diff_options[0] + ''.join(diff_options[1]))77 78 format = req.args.get('format')79 if format == 'diff':80 self._render_diff(req, repos, chgset, diff_options)81 return82 elif format == 'zip':83 self._render_zip(req, repos, chgset)84 return85 86 self._render_html(req, repos, chgset, diff_options)87 add_link(req, 'alternate', '?format=diff', 'Unified Diff',88 'text/plain', 'diff')89 add_link(req, 'alternate', '?format=zip', 'Zip Archive',90 'application/zip', 'zip')91 add_stylesheet(req, 'common/css/changeset.css')92 add_stylesheet(req, 'common/css/diff.css')93 add_stylesheet(req, 'common/css/code.css')94 return 'changeset.cs', None95 96 58 # ITimelineEventProvider methods 97 59 98 60 def get_timeline_filters(self, req): … … 145 107 util.Markup(message) 146 108 rev = repos.previous_rev(rev) 147 109 148 # Internal methods149 150 def _render_html(self, req, repos, chgset, diff_options):151 """HTML version"""152 req.hdf['title'] = '[%s]' % chgset.rev153 req.hdf['changeset'] = {154 'revision': chgset.rev,155 'time': util.format_datetime(chgset.date),156 'author': chgset.author or 'anonymous',157 'message': wiki_to_html(chgset.message or '--', self.env, req,158 escape_newlines=True)159 }160 161 oldest_rev = repos.oldest_rev162 if chgset.rev != oldest_rev:163 add_link(req, 'first', self.env.href.changeset(oldest_rev),164 'Changeset %s' % oldest_rev)165 previous_rev = repos.previous_rev(chgset.rev)166 add_link(req, 'prev', self.env.href.changeset(previous_rev),167 'Changeset %s' % previous_rev)168 youngest_rev = repos.youngest_rev169 if str(chgset.rev) != str(youngest_rev):170 next_rev = repos.next_rev(chgset.rev)171 add_link(req, 'next', self.env.href.changeset(next_rev),172 'Changeset %s' % next_rev)173 add_link(req, 'last', self.env.href.changeset(youngest_rev),174 'Changeset %s' % youngest_rev)175 176 edits = []177 idx = 0178 for path, kind, change, base_path, base_rev in chgset.get_changes():179 info = {'change': change}180 if base_path:181 info['path.old'] = base_path182 info['rev.old'] = base_rev183 info['browser_href.old'] = self.env.href.browser(base_path,184 rev=base_rev)185 if path:186 info['path.new'] = path187 info['rev.new'] = chgset.rev188 info['browser_href.new'] = self.env.href.browser(path,189 rev=chgset.rev)190 if change in (Changeset.COPY, Changeset.EDIT, Changeset.MOVE):191 edits.append((idx, path, kind, base_path, base_rev))192 req.hdf['changeset.changes.%d' % idx] = info193 idx += 1194 195 hidden_properties = [p.strip() for p196 in self.config.get('browser', 'hide_properties',197 'svk:merge').split(',')]198 199 for idx, path, kind, base_path, base_rev in edits:200 old_node = repos.get_node(base_path or path, base_rev)201 new_node = repos.get_node(path, chgset.rev)202 203 # Property changes204 old_props = old_node.get_properties()205 new_props = new_node.get_properties()206 changed_props = {}207 if old_props != new_props:208 for k,v in old_props.items():209 if not k in new_props:210 changed_props[k] = {'old': v}211 elif v != new_props[k]:212 changed_props[k] = {'old': v, 'new': new_props[k]}213 for k,v in new_props.items():214 if not k in old_props:215 changed_props[k] = {'new': v}216 for k in hidden_properties:217 if k in changed_props:218 del changed_props[k]219 req.hdf['changeset.changes.%d.props' % idx] = changed_props220 221 if kind == Node.DIRECTORY:222 continue223 224 # Content changes225 default_charset = self.config.get('trac', 'default_charset')226 old_content = old_node.get_content().read()227 if mimeview.is_binary(old_content):228 continue229 charset = mimeview.get_charset(old_node.content_type)230 if not charset:231 charset = mimeview.detect_unicode(old_content)232 old_content = util.to_utf8(old_content, charset or default_charset)233 234 new_content = new_node.get_content().read()235 if mimeview.is_binary(new_content):236 continue237 charset = mimeview.get_charset(new_node.content_type)238 if not charset:239 charset = mimeview.detect_unicode(new_content)240 new_content = util.to_utf8(new_content, charset or default_charset)241 242 if old_content != new_content:243 context = 3244 for option in diff_options[1]:245 if option.startswith('-U'):246 context = int(option[2:])247 break248 if context < 0:249 context = None250 tabwidth = int(self.config.get('diff', 'tab_width',251 self.config.get('mimeviewer',252 'tab_width')))253 changes = hdf_diff(old_content.splitlines(),254 new_content.splitlines(),255 context, tabwidth,256 ignore_blank_lines='-B' in diff_options[1],257 ignore_case='-i' in diff_options[1],258 ignore_space_changes='-b' in diff_options[1])259 req.hdf['changeset.changes.%d.diff' % idx] = changes260 261 def _render_diff(self, req, repos, chgset, diff_options):262 """Raw Unified Diff version"""263 req.send_response(200)264 req.send_header('Content-Type', 'text/plain;charset=utf-8')265 req.send_header('Content-Disposition', 'inline;'266 'filename=Changeset%s.diff' % chgset.rev)267 req.end_headers()268 269 for path, kind, change, base_path, base_rev in chgset.get_changes():270 if change == Changeset.ADD:271 old_node = None272 else:273 old_node = repos.get_node(base_path or path, base_rev)274 if change == Changeset.DELETE:275 new_node = None276 else:277 new_node = repos.get_node(path, chgset.rev)278 279 # TODO: Property changes280 281 # Content changes282 if kind == 'dir':283 continue284 285 default_charset = self.config.get('trac', 'default_charset')286 new_content = old_content = ''287 new_node_info = old_node_info = ('','')288 289 if old_node:290 charset = mimeview.get_charset(old_node.content_type) or \291 default_charset292 old_content = util.to_utf8(old_node.get_content().read(),293 charset)294 old_node_info = (old_node.path, old_node.rev)295 if mimeview.is_binary(old_content):296 continue297 298 if new_node:299 charset = mimeview.get_charset(new_node.content_type) or \300 default_charset301 new_content = util.to_utf8(new_node.get_content().read(),302 charset)303 new_node_info = (new_node.path, new_node.rev)304 if mimeview.is_binary(new_content):305 continue306 307 if old_content != new_content:308 context = 3309 for option in diff_options[1]:310 if option.startswith('-U'):311 context = int(option[2:])312 break313 req.write('Index: ' + path + util.CRLF)314 req.write('=' * 67 + util.CRLF)315 req.write('--- %s (revision %s)' % old_node_info +316 util.CRLF)317 req.write('+++ %s (revision %s)' % new_node_info +318 util.CRLF)319 for line in unified_diff(old_content.splitlines(),320 new_content.splitlines(), context,321 ignore_blank_lines='-B' in diff_options[1],322 ignore_case='-i' in diff_options[1],323 ignore_space_changes='-b' in diff_options[1]):324 req.write(line + util.CRLF)325 326 def _render_zip(self, req, repos, chgset):327 """ZIP archive with all the added and/or modified files."""328 req.send_response(200)329 req.send_header('Content-Type', 'application/zip')330 req.send_header('Content-Disposition', 'attachment;'331 'filename=Changeset%s.zip' % chgset.rev)332 req.end_headers()333 334 try:335 from cStringIO import StringIO336 except ImportError:337 from StringIO import StringIO338 from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED339 340 buf = StringIO()341 zipfile = ZipFile(buf, 'w', ZIP_DEFLATED)342 for path, kind, change, base_path, base_rev in chgset.get_changes():343 if kind == Node.FILE and change != Changeset.DELETE:344 node = repos.get_node(path, chgset.rev)345 zipinfo = ZipInfo()346 zipinfo.filename = node.path347 zipinfo.date_time = time.gmtime(node.last_modified)[:6]348 zipinfo.compress_type = ZIP_DEFLATED349 zipfile.writestr(zipinfo, node.get_content().read())350 zipfile.close()351 req.write(buf.getvalue())352 353 110 # IWikiSyntaxProvider methods 354 111 355 112 def get_wiki_syntax(self): 356 yield (r"!?\[\d+ \]|(?:\b|!)r\d+\b(?!:\d)",113 yield (r"!?\[\d+(?:/[^\]]*)?\]|(?:\b|!)r\d+\b(?!:\d)", 357 114 lambda x, y, z: self._format_link(x, 'changeset', 358 115 y[0] == 'r' and y[1:] 359 or y[1:-1], y ))116 or y[1:-1], y, z)) 360 117 361 118 def get_link_resolvers(self): 362 119 yield ('changeset', self._format_link) 363 120 364 def _format_link(self, formatter, ns, rev, label): 121 def _format_link(self, formatter, ns, chgset, label, fullmatch=None): 122 sep = chgset.find('/') 123 if sep > 0: 124 rev, path = chgset[:sep], chgset[sep:] 125 else: 126 rev, path = chgset, None 365 127 cursor = formatter.db.cursor() 366 128 cursor.execute('SELECT message FROM revision WHERE rev=%s', (rev,)) 367 129 row = cursor.fetchone() 368 130 if row: 369 131 return '<a class="changeset" title="%s" href="%s">%s</a>' \ 370 132 % (util.escape(util.shorten_line(row[0])), 371 formatter.href.changeset(rev ), label)133 formatter.href.changeset(rev, path), label) 372 134 else: 373 return '<a class="missing changeset" href="%s" rel="nofollow">%s</a>' \ 374 % (formatter.href.changeset(rev), label) 135 return '<a class="missing changeset" href="%s"' \ 136 ' rel="nofollow">%s</a>' \ 137 % (formatter.href.changeset(rev, path), label) 375 138 376 139 # ISearchProvider methods 377 140 -
trac/versioncontrol/web_ui/__init__.py
Seulement dans trac-0.9.3-trac-diff/trac/versioncontrol/web_ui: diff.py diff -ru trac-0.9.3/trac/versioncontrol/web_ui/__init__.py trac-0.9.3-trac-diff/trac/versioncontrol/web_ui/__init__.py
old new 1 1 from trac.versioncontrol.web_ui.browser import * 2 2 from trac.versioncontrol.web_ui.changeset import * 3 3 from trac.versioncontrol.web_ui.log import * 4 from trac.versioncontrol.web_ui.diff import * -
trac/versioncontrol/web_ui/log.py
diff -ru trac-0.9.3/trac/versioncontrol/web_ui/log.py trac-0.9.3-trac-diff/trac/versioncontrol/web_ui/log.py
old new 67 67 stop_rev = req.args.get('stop_rev') 68 68 verbose = req.args.get('verbose') 69 69 limit = LOG_LIMIT 70 old = req.args.get('old') 71 new = req.args.get('new') 72 73 repos = self.env.get_repository(req.authname) 74 normpath = repos.normalize_path(path) 75 rev = str(repos.normalize_rev(rev)) 76 77 if old and new: 78 osep = util.unescape(old).rindex('#') 79 nsep = util.unescape(new).rindex('#') 80 old_path, old_rev = old[:osep], old[osep+1:] 81 new_path, new_rev = new[:nsep], new[nsep+1:] 82 req.redirect(self.env.href.diff(new_path, new=new_rev, 83 old_path=old_path, old=old_rev)) 70 84 71 85 req.hdf['title'] = path + ' (log)' 72 86 req.hdf['log'] = { … … 84 98 if path_links: 85 99 add_link(req, 'up', path_links[-1]['href'], 'Parent directory') 86 100 87 repos = self.env.get_repository(req.authname)88 normpath = repos.normalize_path(path)89 rev = str(repos.normalize_rev(rev))90 101 91 102 # ''Node history'' uses `Node.history()`, 92 103 # ''Path history'' uses `Repository.get_path_history()` -
trac/wiki/tests/wiki-tests.txt
diff -ru trac-0.9.3/trac/wiki/tests/wiki-tests.txt trac-0.9.3-trac-diff/trac/wiki/tests/wiki-tests.txt
old new 88 88 ------------------------------ 89 89 [1:2], r1:2, [12:23], r12:23 90 90 ============================== 91 ticket:1, changeset:1, report:1, source:foo/bar 91 ticket:1, report:1, source:foo/bar 92 changeset:1, changeset:1/README.txt 92 93 93 94 Issue [ticket:1], CS[changeset:1], Listing [report:1], File [source:foo/bar] 94 95 ------------------------------ 95 96 <p> 96 <a class="missing ticket" href="/ticket/1" rel="nofollow">ticket:1</a>, <a class="missing changeset" href="/changeset/1" rel="nofollow">changeset:1</a>, <a class="report" href="/report/1">report:1</a>, <a class="source" href="/browser/foo/bar">source:foo/bar</a> 97 <a class="missing ticket" href="/ticket/1" rel="nofollow">ticket:1</a>, <a class="report" href="/report/1">report:1</a>, <a class="source" href="/browser/foo/bar">source:foo/bar</a> 98 <a class="missing changeset" href="/changeset/1" rel="nofollow">changeset:1</a>, <a class="missing changeset" href="/changeset/1/README.txt" rel="nofollow">changeset:1/README.txt</a> 97 99 </p> 98 100 <p> 99 101 Issue <a class="missing ticket" href="/ticket/1" rel="nofollow">1</a>, CS<a class="missing changeset" href="/changeset/1" rel="nofollow">1</a>, Listing <a class="report" href="/report/1">1</a>, File <a class="source" href="/browser/foo/bar">foo/bar</a> … … 118 120 </p> 119 121 ------------------------------ 120 122 ============================== 123 diff:trunk//branch 124 diff:trunk@12//branch@23 125 diff:trunk@12:23 126 diff:@12:23 127 ------------------------------ 128 <p> 129 <a class="changeset" title="Diff from trunk@latest to branch@latest" href="/diff/branch?old_path=trunk">diff:trunk//branch</a> 130 <a class="changeset" title="Diff from trunk@12 to branch@23" href="/diff/branch?new=23&old=12&old_path=trunk">diff:trunk@12//branch@23</a> 131 <a class="changeset" title="Diff r12:23 for trunk" href="/diff/trunk?new=23&old=12&old_path=trunk">diff:trunk@12:23</a> 132 <a class="changeset" title="Diff r12:23 for /" href="/diff/?new=23&old=12&old_path=">diff:@12:23</a> 133 </p> 134 ------------------------------ 135 ============================== 121 136 Add-on to changeset:123: 122 137 Some change. 123 138 ticket:1 -
wiki-default/WikiStart
diff -ru trac-0.9.3/wiki-default/WikiStart trac-0.9.3-trac-diff/wiki-default/WikiStart
old new 1 = Welcome to Trac 0.9.3 =1 = Welcome to Trac 0.9.3-trac-diff = 2 2 3 3 Trac is a '''minimalistic''' approach to '''web-based''' management of 4 4 '''software projects'''. Its goal is to simplify effective tracking and handling of software issues, enhancements and overall progress.
