diff --git a/trac/versioncontrol/cache.py b/trac/versioncontrol/cache.py
|
a
|
b
|
|
| 40 | 40 | |
| 41 | 41 | has_linear_changesets = False |
| 42 | 42 | |
| | 43 | scope = property(lambda self: self.repos.scope) |
| | 44 | |
| 43 | 45 | def __init__(self, getdb, repos, authz, log): |
| 44 | 46 | Repository.__init__(self, repos.name, authz, log) |
| 45 | 47 | if callable(getdb): |
diff --git a/trac/versioncontrol/svn_prop.py b/trac/versioncontrol/svn_prop.py
|
a
|
b
|
|
| 22 | 22 | |
| 23 | 23 | from trac.core import * |
| 24 | 24 | from trac.versioncontrol import NoSuchNode |
| | 25 | from trac.versioncontrol.svn_fs import _path_within_scope |
| 25 | 26 | from trac.versioncontrol.web_ui.browser import IPropertyRenderer |
| 26 | 27 | from trac.versioncontrol.web_ui.changeset import IPropertyDiffRenderer |
| 27 | 28 | from trac.util import Ranges, to_ranges |
| … |
… |
|
| 131 | 132 | rows = [] |
| 132 | 133 | for line in props[name].splitlines(): |
| 133 | 134 | path, revs = line.split(':', 1) |
| 134 | | spath = path.strip('/') |
| | 135 | spath = _path_within_scope(repos.scope, path) |
| | 136 | if spath is None: |
| | 137 | continue |
| 135 | 138 | revs = revs.strip() |
| 136 | 139 | deleted = False |
| 137 | 140 | if 'LOG_VIEW' in context.perm('source', spath): |
| 138 | 141 | try: |
| 139 | 142 | node = repos.get_node(spath, target_rev) |
| 140 | | row = [self._get_source_link(path, context), |
| | 143 | row = [self._get_source_link(spath, context), |
| 141 | 144 | self._get_revs_link(revs_label, context, |
| 142 | 145 | spath, revs)] |
| 143 | 146 | if has_eligible: |
| … |
… |
|
| 157 | 160 | revs = revs.replace(',', u',\u200b') |
| 158 | 161 | rows.append((deleted, spath, |
| 159 | 162 | [tag.td(path), tag.td(revs, colspan=revs_cols)])) |
| | 163 | if not rows: |
| | 164 | return None |
| 160 | 165 | rows.sort() |
| 161 | 166 | has_deleted = rows and rows[-1][0] or None |
| 162 | 167 | return tag(has_deleted and tag.a(_('(toggle deleted branches)'), |
| … |
… |
|
| 164 | 169 | href='#'), |
| 165 | 170 | tag.table(tag.tbody( |
| 166 | 171 | [tag.tr(row, class_=deleted and 'trac-deleted' or None) |
| 167 | | for deleted, p, row in rows]), class_='props')) |
| | 172 | for deleted, spath, row in rows]), class_='props')) |
| 168 | 173 | |
| 169 | 174 | def _get_blocked_revs(self, props, name, path): |
| 170 | 175 | """Return the revisions blocked from merging for the given property |
| … |
… |
|
| 183 | 188 | pass |
| 184 | 189 | return "" |
| 185 | 190 | |
| 186 | | def _get_source_link(self, path, context): |
| | 191 | def _get_source_link(self, spath, context): |
| 187 | 192 | """Return a link to a merge source.""" |
| 188 | | return tag.a(path, title=_('View merge source'), |
| 189 | | href=context.href.browser(path, |
| | 193 | return tag.a('/' + spath, title=_('View merge source'), |
| | 194 | href=context.href.browser(spath, |
| 190 | 195 | rev=context.resource.version)) |
| 191 | 196 | |
| 192 | 197 | def _get_revs_link(self, label, context, spath, revs): |
| … |
… |
|
| 217 | 222 | # Build 3 columns table showing modifications on merge sources |
| 218 | 223 | # || source || added revs || removed revs || |
| 219 | 224 | # || source || removed || |
| | 225 | repos = self.env.get_repository() |
| 220 | 226 | def parse_sources(props): |
| 221 | 227 | sources = {} |
| 222 | 228 | for line in props[name].splitlines(): |
| 223 | 229 | path, revs = line.split(':', 1) |
| 224 | | spath = path.strip('/') |
| 225 | | sources[spath] = (path, set(Ranges(revs.strip()))) |
| | 230 | spath = _path_within_scope(repos.scope, path) |
| | 231 | if spath is not None: |
| | 232 | sources[spath] = set(Ranges(revs.strip())) |
| 226 | 233 | return sources |
| 227 | 234 | old_sources = parse_sources(old_props) |
| 228 | 235 | new_sources = parse_sources(new_props) |
| … |
… |
|
| 235 | 242 | revs = to_ranges(revs) |
| 236 | 243 | return self._get_revs_link(revs.replace(',', u',\u200b'), |
| 237 | 244 | context, spath, revs) |
| 238 | | repos = self.env.get_repository() |
| 239 | 245 | modified_sources = [] |
| 240 | | for spath, (path, new_revs) in new_sources.iteritems(): |
| | 246 | for spath, new_revs in new_sources.iteritems(): |
| 241 | 247 | if spath in old_sources: |
| 242 | | old_revs, status = old_sources.pop(spath)[1], None |
| | 248 | old_revs, status = old_sources.pop(spath), None |
| 243 | 249 | else: |
| 244 | 250 | old_revs, status = set(), _(' (added)') |
| 245 | 251 | added = new_revs - old_revs |
| … |
… |
|
| 254 | 260 | pass |
| 255 | 261 | if added or removed: |
| 256 | 262 | modified_sources.append(( |
| 257 | | path, [self._get_source_link(path, new_context), status], |
| | 263 | spath, [self._get_source_link(spath, new_context), status], |
| 258 | 264 | added and tag(added_label, revs_link(added, new_context)), |
| 259 | 265 | removed and tag(removed_label, |
| 260 | 266 | revs_link(removed, old_context)))) |
| 261 | 267 | # Go through remaining old sources, those were deleted |
| 262 | 268 | removed_sources = [] |
| 263 | 269 | for spath, (path, old_revs) in old_sources.iteritems(): |
| 264 | | removed_sources.append((path, |
| 265 | | self._get_source_link(path, old_context))) |
| | 270 | removed_sources.append((spath, |
| | 271 | self._get_source_link(spath, old_context))) |
| 266 | 272 | if modified_sources or removed_sources: |
| 267 | 273 | modified_sources.sort() |
| 268 | 274 | removed_sources.sort() |
| 269 | 275 | changes = tag.table(tag.tbody( |
| 270 | 276 | [tag.tr(tag.td(src), tag.td(added), tag.td(removed)) |
| 271 | | for p, src, added, removed in modified_sources], |
| | 277 | for spath, src, added, removed in modified_sources], |
| 272 | 278 | [tag.tr(tag.td(src), tag.td(_('removed'), colspan=2)) |
| 273 | | for p, src in removed_sources]), class_='props') |
| | 279 | for spath, src in removed_sources]), class_='props') |
| 274 | 280 | else: |
| 275 | 281 | changes = tag.em(_(' (with no actual effect on merging)')) |
| 276 | 282 | return tag.li(tag('Property ', tag.strong(name), ' changed'), |