Package svnmailer :: Module browser
[hide private]

Source Code for Module svnmailer.browser

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # Copyright 2005-2006 André Malo or his licensors, as applicable 
  4  # 
  5  # Licensed under the Apache License, Version 2.0 (the "License"); 
  6  # you may not use this file except in compliance with the License. 
  7  # You may obtain a copy of the License at 
  8  # 
  9  #     http://www.apache.org/licenses/LICENSE-2.0 
 10  # 
 11  # Unless required by applicable law or agreed to in writing, software 
 12  # distributed under the License is distributed on an "AS IS" BASIS, 
 13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14  # See the License for the specific language governing permissions and 
 15  # limitations under the License. 
 16  """ 
 17  Respository Browser URL construction 
 18  """ 
 19  __author__    = "André Malo" 
 20  __docformat__ = "epytext en" 
 21  __all__       = ['getBrowserUrlGenerator'] 
 22   
 23   
 24  # Exceptions 
25 -class Error(Exception):
26 """ Base exception for this module """ 27 pass
28
29 -class InvalidBaseUrlError(Error):
30 """ Invalid URL was configured """ 31 pass
32 33
34 -def getBrowserUrlGenerator(config):
35 """ Returns an initialized repos browser generator 36 37 @param config: The group configuration 38 @type config: C{svnmailer.settings.GroupSettingsContainer} 39 40 @return: The generator object or C{None} 41 @rtype: C{object} 42 """ 43 if config.browser_base_url: 44 b_type, base_url = parseBrowserBase(config.browser_base_url) 45 46 if b_type == "viewcvs": 47 return ViewcvsGenerator(base_url) 48 elif b_type == "websvn": 49 return WebsvnGenerator(base_url) 50 51 elif config.viewcvs_base_url: 52 return ViewcvsGenerator(config.viewcvs_base_url) 53 54 return None
55 56
57 -def parseBrowserBase(base_config):
58 """ Parses the given option value into type and base url 59 60 @param base_config: The option value 61 @type base_config: C{str} 62 63 @return: The type and the base url 64 @rtype: C{tuple} 65 """ 66 if base_config: 67 tokens = base_config.split(None, 1) 68 if len(tokens) == 2: 69 return (tokens[0].lower(), tokens[1]) 70 71 return (None, None)
72 73
74 -class ParsedUrl(object):
75 """ Container for URL parsing and modification 76 77 @ivar scheme: The scheme 78 @type scheme: C{str} 79 80 @ivar netloc: The netloc 81 @type netloc: C{str} 82 83 @ivar path: The path 84 @type path: C{str} 85 86 @ivar param: The path param 87 @type param:C{str} 88 89 @ivar query: The query string 90 @type query: C{str} 91 92 @ivar fragment: The fragment 93 @type fragment: C{str} 94 """ 95
96 - def __init__(self, url):
97 """ Initialization """ 98 import urlparse 99 100 (self.scheme, self.netloc, self.path, self.param, self.query, 101 self.fragment) = urlparse.urlparse(url)
102 103
104 - def __str__(self):
105 """ Returns the URL as string 106 107 @return: The URL as string 108 @rtype: C{str} 109 """ 110 import urlparse 111 112 return urlparse.urlunparse(( 113 self.scheme, self.netloc, self.path, self.param, self.query, 114 self.fragment 115 ))
116 117
118 -class ViewcvsGenerator(object):
119 """ viewcvs generator 120 121 @ivar base: The base url 122 @type base: C{str} 123 """ 124
125 - def __init__(self, base):
126 """ Initialization 127 128 @param base: The base url 129 @type base: C{str} 130 """ 131 self.base = base
132 133
134 - def getRevisionUrl(self, revision):
135 """ Returns the revision summary URL 136 137 @param revision: The revision number 138 @type revision: C{int} 139 140 @return: The url 141 @rtype: C{str} 142 """ 143 import urllib 144 from svnmailer import util 145 146 url = ParsedUrl(self.base) 147 148 while url.path[-1:] == '/': 149 url.path = url.path[:-1] 150 151 url.query = util.modifyQuery(url.query, 152 rem = ['p1', 'p2', 'r1', 'r2'], 153 set = [ 154 ('view', 'rev'), 155 ('rev', urllib.quote(str(revision))), 156 ] 157 ) 158 159 return str(url)
160 161
162 - def getContentDiffUrl(self, change):
163 """ Returns the content diff url for a particular change 164 165 @param change: The change to process 166 @type change: C{svnmailer.subversion.VersionedPathDescriptor} 167 """ 168 import urllib, posixpath 169 from svnmailer import util 170 171 url = ParsedUrl(self.base) 172 173 url.path = posixpath.join(url.path, urllib.quote(( 174 change.wasDeleted() and [change.getBasePath()] or [change.path] 175 )[0])) 176 177 if change.isDirectory(): 178 url.path = "%s/" % url.path 179 180 if change.wasDeleted(): 181 url.query = util.modifyQuery(url.query, 182 rem = ['p1', 'p2', 'r1', 'r2'], 183 set = [ 184 ('view', 'auto'), 185 ('rev', urllib.quote(str(change.getBaseRevision()))), 186 ] 187 ) 188 189 elif change.wasCopied(): 190 if change.isDirectory(): 191 return None # no text changes 192 193 url.query = util.modifyQuery(url.query, set = [ 194 ('view', 'diff'), 195 ('rev', urllib.quote(str(change.revision))), 196 ('p1', urllib.quote(change.getBasePath())), 197 ('r1', urllib.quote(str(change.getBaseRevision()))), 198 ('p2', urllib.quote(change.path)), 199 ('r2', urllib.quote(str(change.revision))), 200 ]) 201 202 elif change.wasAdded(): 203 url.query = util.modifyQuery(url.query, 204 rem = ['p1', 'p2', 'r1', 'r2'], 205 set = [ 206 ('view', 'auto'), 207 ('rev', urllib.quote(str(change.revision))), 208 ] 209 ) 210 211 else: # modified 212 if change.isDirectory(): 213 return None # no text changes 214 215 url.query = util.modifyQuery(url.query, 216 rem = ['p1', 'p2'], 217 set = [ 218 ('view', 'diff'), 219 ('rev', urllib.quote(str(change.revision))), 220 ('r1', urllib.quote(str(change.getBaseRevision()))), 221 ('r2', urllib.quote(str(change.revision))), 222 ] 223 ) 224 225 return str(url)
226 227
228 -class WebsvnGenerator(object):
229 """ websvn generator 230 231 @ivar base: The base url 232 @type base: C{str} 233 """ 234
235 - def __init__(self, base):
236 """ Initialization 237 238 @param base: The base url 239 @type base: C{str} 240 """ 241 self.base = base
242 243
244 - def getRevisionUrl(self, revision):
245 """ Returns the revision summary URL 246 247 @param revision: The revision number 248 @type revision: C{int} 249 250 @return: The url 251 @rtype: C{str} 252 """ 253 import urllib, posixpath 254 from svnmailer import util 255 256 url = ParsedUrl(self.base) 257 parsed_query = util.parseQuery(url.query) 258 259 # no path info... 260 if parsed_query.has_key("repname"): 261 dirname, basename = posixpath.split(url.path) 262 if not basename: 263 raise InvalidBaseUrlError("Missing PHP file...?") 264 265 url.path = posixpath.join(dirname, 'listing.php') 266 267 # path info configured 268 else: 269 while url.path[-1:] == '/': 270 url.path = url.path[:-1] 271 url.path = "%s/" % url.path 272 273 url.query = util.modifyQuery(parsed_query, 274 rem = ['path'], 275 set = [ 276 ('sc', '1'), 277 ('rev', urllib.quote(str(revision))), 278 ] 279 ) 280 281 return str(url)
282 283
284 - def getContentDiffUrl(self, change):
285 """ Returns the content diff url for a particular change 286 287 @param change: The change to process 288 @type change: C{svnmailer.subversion.VersionedPathDescriptor} 289 """ 290 import urllib, posixpath 291 from svnmailer import util 292 293 if change.isDirectory() and not change.wasDeleted() and ( 294 not change.wasAdded() or change.wasCopied()): 295 # show only a directory URL on adding and deleting 296 return 297 298 url = ParsedUrl(self.base) 299 parsed_query = util.parseQuery(url.query) 300 cpath = urllib.quote("%s%s" % ( 301 (change.wasDeleted() and 302 [change.getBasePath()] or [change.path])[0], 303 ["", "/"][change.isDirectory()] 304 )) 305 306 toset = [("rev", urllib.quote(str((change.wasDeleted() and 307 [change.getBaseRevision()] or [change.revision] 308 )[0])))] 309 310 if parsed_query.has_key("repname"): 311 dirname, basename = posixpath.split(url.path) 312 if not basename: 313 raise InvalidBaseUrlError( 314 "Missing PHP file in '%s'?" % self.base 315 ) 316 317 url.query = util.modifyQuery(parsed_query, 318 set = [('path', "/%s" % cpath)] 319 ) 320 url.path = dirname 321 cpath = ["diff.php", ["filedetails.php", "listing.php"] 322 [change.isDirectory()]][ 323 change.wasDeleted() or ( 324 change.wasAdded() and not change.wasCopied()) 325 ] 326 327 else: 328 toset.append(("op", 329 ["diff", ["file", "dir"][change.isDirectory()]][ 330 change.wasDeleted() or ( 331 change.wasAdded() and not change.wasCopied()) 332 ] 333 )) 334 335 url.path = posixpath.join(url.path, cpath) 336 url.query = util.modifyQuery(url.query, rem = ["sc"], set = toset) 337 338 return str(url)
339