Add support for calling an external program to generate README markup
Annotate for file /darcsweb.cgi
2005-07-01 albertogli 1 #!/usr/bin/env python
02:55:14 ' 2
' 3 """
' 4 darcsweb - A web interface for darcs
2008-10-28 albertito 5 Alberto Bertogli (albertito@blitiri.com.ar)
2005-07-01 albertogli 6
02:55:14 ' 7 Inspired on gitweb (as of 28/Jun/2005), which is written by Kay Sievers
' 8 <kay.sievers@vrfy.org> and Christian Gierke <ch@gierke.de>
' 9 """
' 10
2006-02-20 albertogli 11 import time
03:23:19 ' 12 time_begin = time.time()
2005-07-01 albertogli 13 import sys
02:55:14 ' 14 import os
' 15 import string
' 16 import stat
' 17 import cgi
' 18 import cgitb; cgitb.enable()
2005-07-03 albertogli 19 import urllib
2005-07-01 albertogli 20 import xml.sax
2005-11-09 albertogli 21 from xml.sax.saxutils import escape as xml_escape
2006-02-20 albertogli 22 time_imports = time.time() - time_begin
2005-07-01 albertogli 23
2005-12-01 stephane 24 iso_datetime = '%Y-%m-%dT%H:%M:%SZ'
2005-07-01 albertogli 25
2010-03-28 simon 26 PATCHES_PER_PAGE = 50
16:40:18 ' 27
2006-02-23 albertogli 28 # In order to be able to store the config file in /etc/darcsweb, it has to be
17:21:30 ' 29 # added to sys.path. It's mainly used by distributions, which place the
2007-10-14 albertito 30 # default configuration there. Add it second place, so it goes after '.' but
15:42:34 ' 31 # before the normal path. This allows per-directory config files (desirable
' 32 # for multiple darcsweb installations on the same machin), and avoids name
' 33 # clashing if there's a config.py in the standard path.
' 34 sys.path.insert(1, '/etc/darcsweb')
2008-03-24 vmiklos 35
17:31:17 ' 36 # Similarly, when hosting multiple darcsweb instrances on the same
' 37 # server, you can just 'SetEnv DARCSWEB_CONFPATH' in the httpd config,
' 38 # and this will have a bigger priority than the system-wide
' 39 # configuration file.
' 40 if 'DARCSWEB_CONFPATH' in os.environ:
' 41 sys.path.insert(1, os.environ['DARCSWEB_CONFPATH'])
2006-02-23 albertogli 42
2005-07-01 albertogli 43 # empty configuration class, we will fill it in later depending on the repo
02:55:14 ' 44 class config:
' 45 pass
' 46
2006-02-20 albertogli 47 # list of run_darcs() invocations, for performance measures
03:23:19 ' 48 darcs_runs = []
' 49
2006-01-09 albertogli 50 # exception handling
05:58:01 ' 51 def exc_handle(t, v, tb):
' 52 try:
' 53 cache.cancel()
' 54 except:
' 55 pass
' 56 cgitb.handler((t, v, tb))
' 57 sys.excepthook = exc_handle
2005-07-01 albertogli 58
02:55:14 ' 59 #
' 60 # utility functions
' 61 #
' 62
' 63 def filter_num(s):
' 64 l = [c for c in s if c in string.digits]
2006-11-30 kirr 65 return ''.join(l)
2005-07-01 albertogli 66
02:55:14 ' 67
2005-08-23 albertogli 68 allowed_in_action = string.ascii_letters + string.digits + '_'
22:20:18 ' 69 def filter_act(s):
' 70 l = [c for c in s if c in allowed_in_action]
2006-11-30 kirr 71 return ''.join(l)
2005-07-01 albertogli 72
02:55:14 ' 73
' 74 allowed_in_hash = string.ascii_letters + string.digits + '-.'
' 75 def filter_hash(s):
' 76 l = [c for c in s if c in allowed_in_hash]
2006-11-30 kirr 77 return ''.join(l)
2005-07-01 albertogli 78
02:55:14 ' 79
' 80 def filter_file(s):
2006-02-23 albertogli 81 if '..' in s or '"' in s:
2010-06-25 albertito 82 raise Exception, 'FilterFile FAILED'
2005-07-01 albertogli 83 if s == '/':
02:55:14 ' 84 return s
' 85
' 86 # remove extra "/"s
' 87 r = s[0]
' 88 last = s[0]
' 89 for c in s[1:]:
' 90 if c == last and c == '/':
' 91 continue
' 92 r += c
' 93 last = c
' 94 return r
' 95
' 96
' 97 def printd(*params):
2006-11-30 kirr 98 print ' '.join(params), '<br/>'
2005-07-01 albertogli 99
02:55:14 ' 100
' 101 # I _hate_ this.
' 102 def fixu8(s):
2006-02-24 albertogli 103 """Calls _fixu8(), which does the real work, line by line. Otherwise
00:31:28 ' 104 we choose the wrong encoding for big buffers and end up messing
' 105 output."""
' 106 n = []
' 107 for i in s.split('\n'):
' 108 n.append(_fixu8(i))
2006-11-30 kirr 109 return '\n'.join(n)
2005-07-01 albertogli 110
2006-02-24 albertogli 111 def _fixu8(s):
00:31:28 ' 112 if type(s) == unicode:
' 113 return s.encode('utf8', 'replace')
' 114 for e in config.repoencoding:
' 115 try:
' 116 return s.decode(e).encode('utf8', 'replace')
' 117 except UnicodeDecodeError:
' 118 pass
2010-06-25 albertito 119 raise UnicodeDecodeError, config.repoencoding
2005-07-01 albertogli 120
02:55:14 ' 121
2005-11-09 albertogli 122 def escape(s):
00:43:55 ' 123 s = xml_escape(s)
' 124 s = s.replace('"', '&quot;')
' 125 return s
2005-07-01 albertogli 126
02:55:14 ' 127 def how_old(epoch):
2005-11-17 albertogli 128 if config.cachedir:
14:41:33 ' 129 # when we have a cache, the how_old() becomes a problem since
' 130 # the cached entries will have old data; so in this case just
' 131 # return a nice string
' 132 t = time.localtime(epoch)
2009-03-26 gaetan.lehma 133 currentYear = time.localtime()[0]
19:58:42 ' 134 if t[0] == currentYear:
' 135 s = time.strftime("%d %b %H:%M", t)
' 136 else:
' 137 s = time.strftime("%d %b %Y %H:%M", t)
2005-11-17 albertogli 138 return s
2005-07-01 albertogli 139 age = int(time.time()) - int(epoch)
02:55:14 ' 140 if age > 60*60*24*365*2:
' 141 s = str(age/60/60/24/365)
' 142 s += " years ago"
' 143 elif age > 60*60*24*(365/12)*2:
' 144 s = str(age/60/60/24/(365/12))
2005-07-28 remko.tronco 145 s += " months ago"
2005-07-01 albertogli 146 elif age > 60*60*24*7*2:
02:55:14 ' 147 s = str(age/60/60/24/7)
' 148 s += " weeks ago"
' 149 elif age > 60*60*24*2:
' 150 s = str(age/60/60/24)
' 151 s += " days ago"
' 152 elif age > 60*60*2:
' 153 s = str(age/60/60)
' 154 s += " hours ago"
' 155 elif age > 60*2:
' 156 s = str(age/60)
' 157 s += " minutes ago"
' 158 elif age > 2:
' 159 s = str(age)
' 160 s += " seconds ago"
' 161 else:
' 162 s = "right now"
' 163 return s
' 164
' 165 def shorten_str(s, max = 60):
' 166 if len(s) > max:
' 167 s = s[:max - 4] + ' ...'
' 168 return s
' 169
2005-09-20 albertogli 170 def replace_tabs(s):
07:01:50 ' 171 pos = s.find("\t")
' 172 while pos != -1:
' 173 count = 8 - (pos % 8)
' 174 if count:
' 175 spaces = ' ' * count
' 176 s = s.replace('\t', spaces, 1)
' 177 pos = s.find("\t")
' 178 return s
' 179
2006-12-25 albertito 180 def replace_links(s):
22:18:20 ' 181 """Replace user defined strings with links, as specified in the
' 182 configuration file."""
' 183 import re
' 184
' 185 vardict = {
' 186 "myreponame": config.myreponame,
' 187 "reponame": config.reponame,
' 188 }
' 189
' 190 for link_pat, link_dst in config.url_links:
' 191 s = re.sub(link_pat, link_dst % vardict, s)
' 192
' 193 return s
' 194
2010-03-28 simon 195 def strip_ignore_this(s):
16:37:55 ' 196 """Strip out darcs' Ignore-this: metadata if present."""
' 197 import re
' 198 return re.sub(r'^Ignore-this:[^\n]*\n?','',s)
2006-12-25 albertito 199
2006-01-09 albertogli 200 def highlight(s, l):
05:24:26 ' 201 "Highlights appearences of s in l"
' 202 import re
' 203 # build the regexp by leaving "(s)", replacing '(' and ') first
' 204 s = s.replace('\\', '\\\\')
' 205 s = s.replace('(', '\\(')
' 206 s = s.replace(')', '\\)')
' 207 s = '(' + escape(s) + ')'
' 208 try:
' 209 pat = re.compile(s, re.I)
' 210 repl = '<span style="color:#e00000">\\1</span>'
' 211 l = re.sub(pat, repl, l)
' 212 except:
' 213 pass
' 214 return l
' 215
2005-07-01 albertogli 216 def fperms(fname):
02:55:14 ' 217 m = os.stat(fname)[stat.ST_MODE]
' 218 m = m & 0777
' 219 s = []
' 220 if os.path.isdir(fname): s.append('d')
' 221 else: s.append('-')
' 222
' 223 if m & 0400: s.append('r')
' 224 else: s.append('-')
' 225 if m & 0200: s.append('w')
' 226 else: s.append('-')
' 227 if m & 0100: s.append('x')
' 228 else: s.append('-')
' 229
' 230 if m & 0040: s.append('r')
' 231 else: s.append('-')
' 232 if m & 0020: s.append('w')
' 233 else: s.append('-')
' 234 if m & 0010: s.append('x')
' 235 else: s.append('-')
' 236
' 237 if m & 0004: s.append('r')
' 238 else: s.append('-')
' 239 if m & 0002: s.append('w')
' 240 else: s.append('-')
' 241 if m & 0001: s.append('x')
' 242 else: s.append('-')
' 243
2006-11-30 kirr 244 return ''.join(s)
2005-07-01 albertogli 245
2007-05-03 vmiklos 246 def fsize(fname):
16:18:30 ' 247 s = os.stat(fname)[stat.ST_SIZE]
' 248 if s < 1024:
' 249 return "%s" % s
' 250 elif s < 1048576:
' 251 return "%sK" % (s / 1024)
' 252 elif s < 1073741824:
' 253 return "%sM" % (s / 1048576)
2005-07-01 albertogli 254
02:55:14 ' 255 def isbinary(fname):
' 256 import re
' 257 bins = open(config.repodir + '/_darcs/prefs/binaries').readlines()
' 258 bins = [b[:-1] for b in bins if b and b[0] != '#']
' 259 for b in bins:
' 260 if re.compile(b).search(fname):
' 261 return 1
' 262 return 0
' 263
2005-10-03 albertogli 264 def realpath(fname):
2006-05-13 albertogli 265 realf = filter_file(config.repodir + '/_darcs/pristine/' + fname)
23:23:21 ' 266 if os.path.exists(realf):
' 267 return realf
2005-10-03 albertogli 268 realf = filter_file(config.repodir + '/_darcs/current/' + fname)
2006-05-13 albertogli 269 if os.path.exists(realf):
23:23:21 ' 270 return realf
' 271 realf = filter_file(config.repodir + '/' + fname)
2005-10-03 albertogli 272 return realf
2005-07-01 albertogli 273
2006-02-23 albertogli 274 def log_times(cache_hit, repo = None, event = None):
2006-02-20 albertogli 275 if not config.logtimes:
03:23:19 ' 276 return
' 277
' 278 time_total = time.time() - time_begin
' 279 processing = time_total - time_imports
' 280 if not event:
' 281 event = action
' 282 if cache_hit:
' 283 event = event + " (hit)"
2006-02-23 albertogli 284 s = '%s\n' % event
19:47:31 ' 285
' 286 if repo:
' 287 s += '\trepo: %s\n' % repo
' 288
' 289 s += """\
2006-02-20 albertogli 290 total: %.3f
03:23:19 ' 291 processing: %.3f
2006-02-23 albertogli 292 imports: %.3f\n""" % (time_total, processing, time_imports)
2006-02-20 albertogli 293
03:23:19 ' 294 if darcs_runs:
' 295 s += "\truns:\n"
' 296 for params in darcs_runs:
' 297 s += '\t\t%s\n' % params
' 298 s += '\n'
' 299
' 300 lf = open(config.logtimes, 'a')
' 301 lf.write(s)
' 302 lf.close()
' 303
2005-10-03 albertogli 304
2008-08-07 albertito 305 def parse_darcs_time(s):
04:41:45 ' 306 "Try to convert a darcs' time string into a Python time tuple."
' 307 try:
' 308 return time.strptime(s, "%Y%m%d%H%M%S")
' 309 except ValueError:
' 310 # very old darcs commits use a different format, for example:
2010-03-28 simon 311 # "Wed May 21 19:39:10 CEST 2003" or even:
18:57:50 ' 312 # "Sun Sep 21 07:23:57 Pacific Daylight Time 2003"
' 313 # we can't parse the time zone part reliably, so we ignore it
2008-08-07 albertito 314 fmt = "%a %b %d %H:%M:%S %Y"
04:41:45 ' 315 parts = s.split()
2010-03-28 simon 316 ns = ' '.join(parts[0:4]) + ' ' + parts[-1]
2008-08-07 albertito 317 return time.strptime(ns, fmt)
04:41:45 ' 318
' 319
' 320
2005-07-01 albertogli 321 #
02:55:14 ' 322 # generic html functions
' 323 #
' 324
' 325 def print_header():
2005-11-12 niol 326 print "Content-type: text/html; charset=utf-8"
2005-07-01 albertogli 327 print """
02:55:14 ' 328 <?xml version="1.0" encoding="utf-8"?>
' 329 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
' 330 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
' 331 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
2008-10-14 albertito 332 <!-- darcsweb 1.1
2008-10-28 albertito 333 Alberto Bertogli (albertito@blitiri.com.ar).
2005-07-01 albertogli 334
02:55:14 ' 335 Based on gitweb, which is written by Kay Sievers <kay.sievers@vrfy.org>
' 336 and Christian Gierke <ch@gierke.de>
' 337 -->
' 338 <head>
' 339 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
' 340 <meta name="robots" content="index, nofollow"/>
' 341 <title>darcs - %(reponame)s</title>
2005-07-01 albertogli 342 <link rel="stylesheet" type="text/css" href="%(css)s"/>
2005-07-01 albertogli 343 <link rel="alternate" title="%(reponame)s" href="%(url)s;a=rss"
02:55:14 ' 344 type="application/rss+xml"/>
2005-12-13 albertogli 345 <link rel="alternate" title="%(reponame)s" href="%(url)s;a=atom"
14:12:44 ' 346 type='application/atom+xml'/>
2005-07-01 albertogli 347 <link rel="shortcut icon" href="%(fav)s"/>
20:01:39 ' 348 <link rel="icon" href="%(fav)s"/>
2005-07-01 albertogli 349 </head>
02:55:14 ' 350
' 351 <body>
' 352 <div class="page_header">
2006-01-09 albertogli 353 <div class="search_box">
05:24:26 ' 354 <form action="%(myname)s" method="get"><div>
' 355 <input type="hidden" name="r" value="%(reponame)s"/>
' 356 <input type="hidden" name="a" value="search"/>
' 357 <input type="text" name="s" size="20" class="search_text"/>
' 358 <input type="submit" value="search" class="search_button"/>
' 359 <a href="http://darcs.net" title="darcs">
' 360 <img src="%(logo)s" alt="darcs logo" class="logo"/>
' 361 </a>
' 362 </div></form>
' 363 </div>
' 364 <a href="%(myname)s">repos</a> /
' 365 <a href="%(myreponame)s;a=summary">%(reponame)s</a> /
' 366 %(action)s
' 367 </div>
2005-07-01 albertogli 368 """ % {
02:55:14 ' 369 'reponame': config.reponame,
' 370 'css': config.cssfile,
' 371 'url': config.myurl + '/' + config.myreponame,
' 372 'fav': config.darcsfav,
' 373 'logo': config.darcslogo,
2006-01-09 albertogli 374 'myname': config.myname,
05:24:26 ' 375 'myreponame': config.myreponame,
' 376 'action': action
2005-07-01 albertogli 377 }
02:55:14 ' 378
' 379
' 380 def print_footer(put_rss = 1):
' 381 print """
' 382 <div class="page_footer">
2005-08-24 albertogli 383 <div class="page_footer_text">%s</div>
18:38:04 ' 384 """ % config.footer
2005-07-01 albertogli 385 if put_rss:
2005-07-01 albertogli 386 print '<a class="rss_logo" href="%s;a=rss">RSS</a>' % \
2005-07-01 albertogli 387 (config.myurl + '/' + config.myreponame)
02:55:14 ' 388 print "</div>\n</body>\n</html>"
' 389
' 390
' 391 def print_navbar(h = "", f = ""):
' 392 print """
' 393 <div class="page_nav">
' 394 <a href="%(myreponame)s;a=summary">summary</a>
' 395 | <a href="%(myreponame)s;a=shortlog">shortlog</a>
' 396 | <a href="%(myreponame)s;a=log">log</a>
2005-10-03 albertogli 397 | <a href="%(myreponame)s;a=tree">tree</a>
2005-07-01 albertogli 398 """ % { "myreponame": config.myreponame }
2005-07-25 albertogli 399
2005-07-01 albertogli 400 if h:
02:55:14 ' 401 print """
' 402 | <a href="%(myreponame)s;a=commit;h=%(hash)s">commit</a>
' 403 | <a href="%(myreponame)s;a=commitdiff;h=%(hash)s">commitdiff</a>
' 404 | <a href="%(myreponame)s;a=headdiff;h=%(hash)s">headdiff</a>
' 405 """ % { "myreponame": config.myreponame, 'hash': h }
' 406
2005-10-03 albertogli 407 realf = realpath(f)
2006-02-23 albertogli 408 f = urllib.quote(f)
2005-07-01 albertogli 409
2005-09-19 albertogli 410 if f and h:
02:50:04 ' 411 print """
2005-10-03 albertogli 412 | <a href="%(myreponame)s;a=annotate_shade;f=%(fname)s;h=%(hash)s">annotate</a>
2005-09-19 albertogli 413 """ % {
02:50:04 ' 414 'myreponame': config.myreponame,
' 415 'hash': h,
' 416 'fname': f
' 417 }
' 418 elif f:
' 419 print """
2005-10-03 albertogli 420 | <a href="%(myreponame)s;a=annotate_shade;f=%(fname)s">annotate</a>
2005-09-19 albertogli 421 """ % { "myreponame": config.myreponame, 'fname': f }
02:50:04 ' 422
2005-07-01 albertogli 423 if f and os.path.isfile(realf):
02:55:14 ' 424 print """
' 425 | <a href="%(myreponame)s;a=headblob;f=%(fname)s">headblob</a>
' 426 """ % { "myreponame": config.myreponame, 'fname': f }
' 427
' 428 if f and os.path.isdir(realf):
' 429 print """
' 430 | <a href="%(myreponame)s;a=tree;f=%(fname)s">headtree</a>
' 431 """ % { "myreponame": config.myreponame, 'fname': f }
' 432
' 433 if h and f and (os.path.isfile(realf) or os.path.isdir(realf)):
' 434 print """
' 435 | <a href="%(myreponame)s;a=headfilediff;h=%(hash)s;f=%(fname)s">headfilediff</a>
' 436 """ % { "myreponame": config.myreponame, 'hash': h, 'fname': f }
' 437
2005-07-23 albertogli 438 if f:
22:54:35 ' 439 print """
' 440 | <a class="link" href="%(myreponame)s;a=filehistory;f=%(fname)s">filehistory</a>
' 441 """ % { "myreponame": config.myreponame, 'fname': f }
' 442
2005-08-23 albertogli 443 print "<br/>"
23:04:30 ' 444
2005-09-07 albertogli 445 efaction = action
06:25:28 ' 446 if '_' in action:
' 447 # action is composed as "format_action", like
' 448 # "darcs_commitdiff"; so we get the "effective action" to
' 449 # decide if we need to present the "alternative formats" menu
' 450 pos = action.find('_')
' 451 fmt = action[:pos]
' 452 efaction = action[pos + 1:]
2005-09-07 albertogli 453 if efaction in ("commit", "commitdiff", "filediff", "headdiff",
16:58:43 ' 454 "headfilediff"):
' 455
' 456 # in order to show the small bar in the commit page too, we
' 457 # accept it here and change efaction to commitdiff, because
' 458 # that's what we're really intrested in
' 459 if efaction == "commit":
' 460 efaction = "commitdiff"
' 461
2005-08-23 albertogli 462 params = 'h=%s;' % h
23:04:30 ' 463 if f:
' 464 params += 'f=%s;' % f
' 465
2005-09-07 albertogli 466 # normal (unified)
06:25:28 ' 467 print """
' 468 <a class="link" href="%(myreponame)s;a=%(act)s;%(params)s">unified</a>
' 469 """ % { "myreponame": config.myreponame, "act": efaction,
' 470 "params": params }
' 471
' 472 # plain
2005-08-23 albertogli 473 print """
2005-09-07 albertogli 474 | <a class="link" href="%(myreponame)s;a=plain_%(act)s;%(params)s">plain</a>
06:25:28 ' 475 """ % { "myreponame": config.myreponame, "act": efaction,
2005-08-23 albertogli 476 "params": params }
23:04:30 ' 477
' 478 # darcs, htmlized
2005-09-07 albertogli 479 print """
06:25:28 ' 480 | <a class="link" href="%(myreponame)s;a=darcs_%(act)s;%(params)s">darcs</a>
' 481 """ % { "myreponame": config.myreponame, "act": efaction,
' 482 "params": params }
2005-08-23 albertogli 483
23:04:30 ' 484 # darcs, raw, if available; and only for commitdiff
' 485 realf = filter_file(config.repodir + '/_darcs/patches/' + h)
2005-09-07 albertogli 486 if efaction == "commitdiff" and os.path.isfile(realf):
2005-08-23 albertogli 487 print """
23:04:30 ' 488 | <a class="link" href="%(myreponame)s;a=raw_%(act)s;%(params)s">raw</a>
' 489 """ % { "myreponame": config.myreponame,
2005-09-07 albertogli 490 "act": efaction, "params": params }
2005-08-23 albertogli 491
23:04:30 ' 492 elif f and action == "headblob":
' 493 # show the only alternative format: plain
' 494 print """
' 495 <a class="link" href="%(myreponame)s;a=plainblob;f=%(fname)s">plain</a>
' 496 """ % { "myreponame": config.myreponame, "fname": f }
2005-09-21 albertogli 497
18:24:58 ' 498 elif f and h and action.startswith("annotate"):
2005-09-19 albertogli 499 # same for annotate
02:50:04 ' 500 print """
2005-10-03 albertogli 501 <a href="%(myreponame)s;a=annotate_normal;f=%(fname)s;h=%(hash)s">normal</a>
2005-09-21 albertogli 502 | <a href="%(myreponame)s;a=annotate_plain;f=%(fname)s;h=%(hash)s">plain</a>
18:24:58 ' 503 | <a href="%(myreponame)s;a=annotate_shade;f=%(fname)s;h=%(hash)s">shade</a>
' 504 | <a href="%(myreponame)s;a=annotate_zebra;f=%(fname)s;h=%(hash)s">zebra</a>
2005-09-19 albertogli 505 """ % {
02:50:04 ' 506 "myreponame": config.myreponame,
' 507 "fname": f,
' 508 "hash": h
' 509 }
2005-08-23 albertogli 510
23:04:30 ' 511 print '<br/>'
' 512 print '</div>'
2005-07-01 albertogli 513
02:55:14 ' 514 def print_plain_header():
2005-09-19 albertogli 515 print "Content-type: text/plain; charset=utf-8\n"
2005-11-17 albertogli 516
2005-12-21 albertogli 517 def print_binary_header(fname = None):
2005-12-24 albertogli 518 import mimetypes
2005-12-21 gaetan.lehma 519 if fname :
22:24:47 ' 520 (mime, enc) = mimetypes.guess_type(fname)
' 521 else :
' 522 mime = None
' 523 if mime :
' 524 print "Content-type: %s" % mime
' 525 else :
' 526 print "Content-type: application/octet-stream"
2005-12-21 albertogli 527 if fname:
15:00:33 ' 528 print "Content-Disposition:attachment;filename=%s" % fname
' 529 print
2005-11-17 albertogli 530
2007-02-01 vmiklos 531 def gen_authorlink(author, shortauthor=None):
17:30:50 ' 532 if not config.author_links:
' 533 if shortauthor:
' 534 return shortauthor
' 535 else:
' 536 return author
' 537 if not shortauthor:
' 538 shortauthor = author
' 539 return '<a href="' + config.author_links % { 'author': author } + '">%s</a>' % shortauthor
2005-11-17 albertogli 540
03:10:28 ' 541 #
' 542 # basic caching
' 543 #
' 544
' 545 class Cache:
' 546 def __init__(self, basedir, url):
2006-02-22 albertogli 547 import sha
2005-11-17 albertogli 548 self.basedir = basedir
03:10:28 ' 549 self.url = url
2006-01-09 albertogli 550 self.fname = sha.sha(repr(url)).hexdigest()
2005-11-17 albertogli 551 self.file = None
03:10:28 ' 552 self.mode = None
' 553 self.real_stdout = sys.stdout
' 554
' 555 def open(self):
' 556 "Returns 1 on hit, 0 on miss"
' 557 fname = self.basedir + '/' + self.fname
' 558
' 559 if not os.access(fname, os.R_OK):
' 560 # the file doesn't exist, direct miss
' 561 pid = str(os.getpid())
' 562 fname = self.basedir + '/.' + self.fname + '-' + pid
' 563 self.file = open(fname, 'w')
' 564 self.mode = 'w'
2006-02-19 albertogli 565 os.chmod(fname, stat.S_IRUSR | stat.S_IWUSR)
2005-11-17 albertogli 566
03:10:28 ' 567 # step over stdout so when "print" tries to write
' 568 # output, we get it first
' 569 sys.stdout = self
' 570 return 0
' 571
2008-08-03 albertito 572 inv = config.repodir + '/_darcs/patches'
2005-11-17 albertogli 573 cache_lastmod = os.stat(fname).st_mtime
03:10:28 ' 574 repo_lastmod = os.stat(inv).st_mtime
2005-12-13 albertogli 575 dw_lastmod = os.stat(sys.argv[0]).st_mtime
2005-11-17 albertogli 576
2005-12-13 albertogli 577 if repo_lastmod > cache_lastmod or dw_lastmod > cache_lastmod:
2005-11-17 albertogli 578 # the entry is too old, remove it and return a miss
03:10:28 ' 579 os.unlink(fname)
' 580
' 581 pid = str(os.getpid())
' 582 fname = self.basedir + '/.' + self.fname + '-' + pid
' 583 self.file = open(fname, 'w')
' 584 self.mode = 'w'
' 585 sys.stdout = self
' 586 return 0
' 587
' 588 # the entry is still valid, hit!
' 589 self.file = open(fname, 'r')
' 590 self.mode = 'r'
' 591 return 1
' 592
' 593
' 594 def dump(self):
' 595 for l in self.file:
' 596 self.real_stdout.write(l)
' 597
' 598 def write(self, s):
' 599 # this gets called from print, because we replaced stdout with
' 600 # ourselves
' 601 self.file.write(s)
' 602 self.real_stdout.write(s)
' 603
' 604 def close(self):
' 605 if self.file:
' 606 self.file.close()
' 607 sys.stdout = self.real_stdout
' 608 if self.mode == 'w':
' 609 pid = str(os.getpid())
' 610 fname1 = self.basedir + '/.' + self.fname + '-' + pid
' 611 fname2 = self.basedir + '/' + self.fname
' 612 os.rename(fname1, fname2)
' 613 self.mode = 'c'
' 614
' 615 def cancel(self):
' 616 "Like close() but don't save the entry."
' 617 if self.file:
' 618 self.file.close()
' 619 sys.stdout = self.real_stdout
' 620 if self.mode == 'w':
' 621 pid = str(os.getpid())
' 622 fname = self.basedir + '/.' + self.fname + '-' + pid
' 623 os.unlink(fname)
' 624 self.mode = 'c'
2005-07-01 albertogli 625
02:55:14 ' 626
' 627 #
' 628 # darcs repo manipulation
' 629 #
' 630
' 631 def repo_get_owner():
' 632 try:
' 633 fd = open(config.repodir + '/_darcs/prefs/author')
2011-11-01 pix 634 for line in fd:
09:54:21 ' 635 line = line.strip()
' 636 if line != "" and line[0] != "#":
' 637 return line.strip()
2005-07-01 albertogli 638 except:
2011-11-01 pix 639 return None
2005-07-01 albertogli 640
02:55:14 ' 641 def run_darcs(params):
' 642 """Runs darcs on the repodir with the given params, return a file
' 643 object with its output."""
' 644 os.chdir(config.repodir)
2007-01-17 jonathan.buc 645 try:
23:02:12 ' 646 original_8bit_setting = os.environ['DARCS_DONT_ESCAPE_8BIT']
' 647 except KeyError:
' 648 original_8bit_setting = None
' 649 os.environ['DARCS_DONT_ESCAPE_8BIT'] = '1'
' 650 cmd = config.darcspath + "darcs " + params
2005-08-26 albertogli 651 inf, outf = os.popen4(cmd, 't')
2006-02-20 albertogli 652 darcs_runs.append(params)
2007-01-17 jonathan.buc 653 if original_8bit_setting == None:
23:02:12 ' 654 del(os.environ['DARCS_DONT_ESCAPE_8BIT'])
' 655 else:
' 656 os.environ['DARCS_DONT_ESCAPE_8BIT'] = original_8bit_setting
2005-07-01 albertogli 657 return outf
02:55:14 ' 658
' 659
' 660 class Patch:
' 661 "Represents a single patch/record"
' 662 def __init__(self):
' 663 self.hash = ''
' 664 self.author = ''
' 665 self.shortauthor = ''
' 666 self.date = 0
' 667 self.local_date = 0
' 668 self.name = ''
' 669 self.comment = ''
' 670 self.inverted = False;
' 671 self.adds = []
' 672 self.removes = []
' 673 self.modifies = {}
' 674 self.diradds = []
' 675 self.dirremoves = []
2005-09-07 albertogli 676 self.replaces = {}
2005-07-01 albertogli 677 self.moves = {}
02:55:14 ' 678
' 679 def tostr(self):
' 680 s = "%s\n\tAuthor: %s\n\tDate: %s\n\tHash: %s\n" % \
' 681 (self.name, self.author, self.date, self.hash)
' 682 return s
' 683
' 684 def getdiff(self):
' 685 """Returns a list of lines from the diff -u corresponding with
' 686 the patch."""
2010-10-15 fx 687 params = 'diff --quiet -u --match "hash %s"' % self.hash
2005-07-01 albertogli 688 f = run_darcs(params)
02:55:14 ' 689 return f.readlines()
' 690
2006-01-09 albertogli 691 def matches(self, s):
05:24:26 ' 692 "Defines if the patch matches a given string"
' 693 if s.lower() in self.comment.lower():
' 694 return self.comment
' 695 elif s.lower() in self.name.lower():
' 696 return self.name
' 697 elif s.lower() in self.author.lower():
' 698 return self.author
' 699 elif s == self.hash:
' 700 return self.hash
' 701
' 702 s = s.lower()
' 703 for l in (self.adds, self.removes, self.modifies,
' 704 self.diradds, self.dirremoves,
' 705 self.replaces.keys(), self.moves.keys(),
' 706 self.moves.keys() ):
' 707 for i in l:
' 708 if s in i.lower():
' 709 return i
' 710 return ''
' 711
2006-02-24 albertogli 712 class XmlInputWrapper:
00:31:28 ' 713 def __init__(self, fd):
' 714 self.fd = fd
' 715 self.times = 0
' 716 self._read = self.read
' 717
' 718 def read(self, *args, **kwargs):
' 719 self.times += 1
' 720 if self.times == 1:
' 721 return '<?xml version="1.0" encoding="utf-8"?>\n'
' 722 s = self.fd.read(*args, **kwargs)
' 723 if not s:
' 724 return s
' 725 return fixu8(s)
' 726
' 727 def close(self, *args, **kwargs):
' 728 return self.fd.close(*args, **kwargs)
' 729
2005-07-01 albertogli 730
02:55:14 ' 731 # patch parsing, we get them through "darcs changes --xml-output"
' 732 class BuildPatchList(xml.sax.handler.ContentHandler):
' 733 def __init__(self):
' 734 self.db = {}
' 735 self.list = []
' 736 self.cur_hash = ''
' 737 self.cur_elem = None
' 738 self.cur_val = ''
' 739 self.cur_file = ''
' 740
' 741 def startElement(self, name, attrs):
2005-07-24 albertogli 742 # When you ask for changes to a given file, the xml output
01:05:22 ' 743 # begins with the patch that creates it is enclosed in a
' 744 # "created_as" tag; then, later, it gets shown again in its
' 745 # usual place. The following two "if"s take care of ignoring
' 746 # everything inside the "created_as" tag, since we don't care.
' 747 if name == 'created_as':
' 748 self.cur_elem = 'created_as'
' 749 return
' 750 if self.cur_elem == 'created_as':
' 751 return
' 752
' 753 # now parse the tags normally
2005-07-01 albertogli 754 if name == 'patch':
02:55:14 ' 755 p = Patch()
' 756 p.hash = fixu8(attrs.get('hash'))
' 757
' 758 au = attrs.get('author', None)
' 759 p.author = fixu8(escape(au))
' 760 if au.find('<') != -1:
' 761 au = au[:au.find('<')].strip()
' 762 p.shortauthor = fixu8(escape(au))
' 763
2008-08-07 albertito 764 td = parse_darcs_time(attrs.get('date', None))
2005-07-01 albertogli 765 p.date = time.mktime(td)
02:55:14 ' 766 p.date_str = time.strftime("%a, %d %b %Y %H:%M:%S", td)
' 767
' 768 td = time.strptime(attrs.get('local_date', None),
' 769 "%a %b %d %H:%M:%S %Z %Y")
' 770 p.local_date = time.mktime(td)
' 771 p.local_date_str = \
' 772 time.strftime("%a, %d %b %Y %H:%M:%S", td)
' 773
' 774 inverted = attrs.get('inverted', None)
' 775 if inverted and inverted == 'True':
' 776 p.inverted = True
' 777
' 778 self.db[p.hash] = p
' 779 self.current = p.hash
' 780 self.list.append(p.hash)
' 781 elif name == 'name':
' 782 self.db[self.current].name = ''
' 783 self.cur_elem = 'name'
' 784 elif name == 'comment':
' 785 self.db[self.current].comment = ''
' 786 self.cur_elem = 'comment'
' 787 elif name == 'add_file':
' 788 self.cur_elem = 'add_file'
' 789 elif name == 'remove_file':
' 790 self.cur_elem = 'remove_file'
' 791 elif name == 'add_directory':
' 792 self.cur_elem = 'add_directory'
' 793 elif name == 'remove_directory':
' 794 self.cur_elem = 'remove_dir'
' 795 elif name == 'modify_file':
' 796 self.cur_elem = 'modify_file'
' 797 elif name == 'removed_lines':
' 798 if self.cur_val:
' 799 self.cur_file = fixu8(self.cur_val.strip())
' 800 cf = self.cur_file
' 801 p = self.db[self.current]
' 802 # the current value holds the file name at this point
' 803 if not p.modifies.has_key(cf):
' 804 p.modifies[cf] = { '+': 0, '-': 0 }
' 805 p.modifies[cf]['-'] = int(attrs.get('num', None))
' 806 elif name == 'added_lines':
' 807 if self.cur_val:
' 808 self.cur_file = fixu8(self.cur_val.strip())
' 809 cf = self.cur_file
' 810 p = self.db[self.current]
' 811 if not p.modifies.has_key(cf):
' 812 p.modifies[cf] = { '+': 0, '-': 0 }
' 813 p.modifies[cf]['+'] = int(attrs.get('num', None))
' 814 elif name == 'move':
' 815 src = fixu8(attrs.get('from', None))
' 816 dst = fixu8(attrs.get('to', None))
' 817 p = self.db[self.current]
' 818 p.moves[src] = dst
2005-09-07 albertogli 819 elif name == 'replaced_tokens':
16:59:52 ' 820 if self.cur_val:
' 821 self.cur_file = fixu8(self.cur_val.strip())
' 822 cf = self.cur_file
' 823 p = self.db[self.current]
' 824 if not p.replaces.has_key(cf):
' 825 p.replaces[cf] = 0
' 826 p.replaces[cf] = int(attrs.get('num', None))
2005-07-01 albertogli 827 else:
02:55:14 ' 828 self.cur_elem = None
' 829
' 830 def characters(self, s):
' 831 if not self.cur_elem:
' 832 return
' 833 self.cur_val += s
' 834
' 835 def endElement(self, name):
2005-07-24 albertogli 836 # See the comment in startElement()
01:05:22 ' 837 if name == 'created_as':
' 838 self.cur_elem = None
' 839 self.cur_val = ''
' 840 return
' 841 if self.cur_elem == 'created_as':
' 842 return
2005-09-07 albertogli 843 if name == 'replaced_tokens':
16:59:52 ' 844 return
2005-07-24 albertogli 845
2005-07-01 albertogli 846 if name == 'name':
02:55:14 ' 847 p = self.db[self.current]
' 848 p.name = fixu8(self.cur_val)
' 849 if p.inverted:
' 850 p.name = 'UNDO: ' + p.name
' 851 elif name == 'comment':
2010-03-28 simon 852 self.db[self.current].comment = fixu8(strip_ignore_this(self.cur_val))
2005-07-01 albertogli 853 elif name == 'add_file':
02:55:14 ' 854 scv = fixu8(self.cur_val.strip())
' 855 self.db[self.current].adds.append(scv)
' 856 elif name == 'remove_file':
' 857 scv = fixu8(self.cur_val.strip())
' 858 self.db[self.current].removes.append(scv)
' 859 elif name == 'add_directory':
' 860 scv = fixu8(self.cur_val.strip())
' 861 self.db[self.current].diradds.append(scv)
' 862 elif name == 'remove_directory':
' 863 scv = fixu8(self.cur_val.strip())
' 864 self.db[self.current].dirremoves.append(scv)
' 865
' 866 elif name == 'modify_file':
' 867 if not self.cur_file:
' 868 # binary modification appear without a line
' 869 # change summary, so we add it manually here
' 870 f = fixu8(self.cur_val.strip())
' 871 p = self.db[self.current]
' 872 p.modifies[f] = { '+': 0, '-': 0, 'b': 1 }
' 873 self.cur_file = ''
' 874
' 875 self.cur_elem = None
' 876 self.cur_val = ''
' 877
' 878 def get_list(self):
' 879 plist = []
' 880 for h in self.list:
' 881 plist.append(self.db[h])
' 882 return plist
' 883
' 884 def get_db(self):
' 885 return self.db
' 886
' 887 def get_list_db(self):
' 888 return (self.list, self.db)
' 889
' 890 def get_changes_handler(params):
' 891 "Returns a handler for the changes output, run with the given params"
' 892 parser = xml.sax.make_parser()
' 893 handler = BuildPatchList()
' 894 parser.setContentHandler(handler)
' 895
' 896 # get the xml output and parse it
' 897 xmlf = run_darcs("changes --xml-output " + params)
2006-02-24 albertogli 898 parser.parse(XmlInputWrapper(xmlf))
2005-07-01 albertogli 899 xmlf.close()
02:55:14 ' 900
' 901 return handler
' 902
2005-07-23 albertogli 903 def get_last_patches(last = 15, topi = 0, fname = None):
2005-07-01 albertogli 904 """Gets the last N patches from the repo, returns a patch list. If
02:55:14 ' 905 "topi" is specified, then it will return the N patches that preceeded
' 906 the patch number topi in the list. It sounds messy but it's quite
2005-07-23 albertogli 907 simple. You can optionally pass a filename and only changes that
22:54:35 ' 908 affect it will be returned. FIXME: there's probably a more efficient
' 909 way of doing this."""
' 910
' 911 # darcs calculate last first, and then filters the filename,
' 912 # so it's not so simple to combine them; that's why we do so much
' 913 # special casing here
2005-07-01 albertogli 914 toget = last + topi
02:55:14 ' 915
2005-07-23 albertogli 916 if fname:
22:54:35 ' 917 if fname[0] == '/': fname = fname[1:]
2005-12-30 albertogli 918 s = '-s "%s"' % fname
2005-07-23 albertogli 919 else:
22:54:35 ' 920 s = "-s --last=%d" % toget
' 921
' 922 handler = get_changes_handler(s)
' 923
2005-07-01 albertogli 924 # return the list of all the patch objects
02:55:14 ' 925 return handler.get_list()[topi:toget]
' 926
' 927 def get_patch(hash):
' 928 handler = get_changes_handler('-s --match "hash %s"' % hash)
' 929 patch = handler.db[handler.list[0]]
' 930 return patch
2005-08-23 albertogli 931
23:04:30 ' 932 def get_diff(hash):
2010-10-15 fx 933 return run_darcs('diff --quiet -u --match "hash %s"' % hash)
2005-07-01 albertogli 934
02:55:14 ' 935 def get_file_diff(hash, fname):
2010-10-15 fx 936 return run_darcs('diff --quiet -u --match "hash %s" "%s"' % (hash, fname))
2005-07-01 albertogli 937
02:55:14 ' 938 def get_file_headdiff(hash, fname):
2010-10-15 fx 939 return run_darcs('diff --quiet -u --from-match "hash %s" "%s"' % (hash, fname))
2005-07-01 albertogli 940
02:55:14 ' 941 def get_patch_headdiff(hash):
2010-10-15 fx 942 return run_darcs('diff --quiet -u --from-match "hash %s"' % hash)
2005-08-23 albertogli 943
23:04:30 ' 944 def get_raw_diff(hash):
' 945 import gzip
' 946 realf = filter_file(config.repodir + '/_darcs/patches/' + hash)
' 947 if not os.path.isfile(realf):
' 948 return None
2005-12-21 albertogli 949 file = open(realf, 'rb')
13:47:50 ' 950 if file.read(2) == '\x1f\x8b':
' 951 # file begins with gzip magic
' 952 file.close()
' 953 dsrc = gzip.open(realf)
' 954 else:
' 955 file.seek(0)
' 956 dsrc = file
2005-08-23 albertogli 957 return dsrc
2005-09-07 albertogli 958
06:25:28 ' 959 def get_darcs_diff(hash, fname = None):
' 960 cmd = 'changes -v --matches "hash %s"' % hash
' 961 if fname:
' 962 cmd += ' "%s"' % fname
' 963 return run_darcs(cmd)
2005-07-01 albertogli 964
2005-09-07 albertogli 965 def get_darcs_headdiff(hash, fname = None):
06:25:28 ' 966 cmd = 'changes -v --from-match "hash %s"' % hash
' 967 if fname:
' 968 cmd += ' "%s"' % fname
' 969 return run_darcs(cmd)
2005-07-01 albertogli 970
2005-09-19 albertogli 971
02:50:04 ' 972 class Annotate:
' 973 def __init__(self):
' 974 self.fname = ""
' 975 self.creator_hash = ""
' 976 self.created_as = ""
' 977 self.lastchange_hash = ""
' 978 self.lastchange_author = ""
' 979 self.lastchange_name = ""
2005-09-21 albertogli 980 self.lastchange_date = None
05:51:22 ' 981 self.firstdate = None
' 982 self.lastdate = None
2005-09-19 albertogli 983 self.lines = []
2005-09-21 albertogli 984 self.patches = {}
2005-09-19 albertogli 985
02:50:04 ' 986 class Line:
' 987 def __init__(self):
' 988 self.text = ""
' 989 self.phash = None
' 990 self.pauthor = None
2005-09-21 albertogli 991 self.pdate = None
2005-09-19 albertogli 992
02:50:04 ' 993 def parse_annotate(src):
' 994 import xml.dom.minidom
' 995
' 996 annotate = Annotate()
2005-09-19 albertogli 997
03:19:14 ' 998 # FIXME: convert the source to UTF8; it _has_ to be a way to let
' 999 # minidom know the source encoding
' 1000 s = ""
' 1001 for i in src:
2011-11-13 pix 1002 s += fixu8(i).replace('^L', '^L')
2005-09-19 albertogli 1003
03:19:14 ' 1004 dom = xml.dom.minidom.parseString(s)
2005-09-19 albertogli 1005
02:50:04 ' 1006 file = dom.getElementsByTagName("file")[0]
2005-09-19 albertogli 1007 annotate.fname = fixu8(file.getAttribute("name"))
2005-09-19 albertogli 1008
02:50:04 ' 1009 createinfo = dom.getElementsByTagName("created_as")[0]
2005-09-19 albertogli 1010 annotate.created_as = fixu8(createinfo.getAttribute("original_name"))
2005-09-19 albertogli 1011
02:50:04 ' 1012 creator = createinfo.getElementsByTagName("patch")[0]
2005-09-19 albertogli 1013 annotate.creator_hash = fixu8(creator.getAttribute("hash"))
2005-09-19 albertogli 1014
02:50:04 ' 1015 mod = dom.getElementsByTagName("modified")[0]
' 1016 lastpatch = mod.getElementsByTagName("patch")[0]
2005-09-19 albertogli 1017 annotate.lastchange_hash = fixu8(lastpatch.getAttribute("hash"))
06:20:23 ' 1018 annotate.lastchange_author = fixu8(lastpatch.getAttribute("author"))
2005-09-19 albertogli 1019
02:50:04 ' 1020 lastname = lastpatch.getElementsByTagName("name")[0]
' 1021 lastname = lastname.childNodes[0].wholeText
2005-09-19 albertogli 1022 annotate.lastchange_name = fixu8(lastname)
06:20:23 ' 1023
2008-08-07 albertito 1024 lastdate = parse_darcs_time(lastpatch.getAttribute("date"))
2005-09-21 albertogli 1025 annotate.lastchange_date = lastdate
05:51:22 ' 1026
' 1027 annotate.patches[annotate.lastchange_hash] = annotate.lastchange_date
' 1028
' 1029 # these will be overriden by the real dates later
' 1030 annotate.firstdate = lastdate
' 1031 annotate.lastdate = 0
2005-09-19 albertogli 1032
02:50:04 ' 1033 file = dom.getElementsByTagName("file")[0]
' 1034
' 1035 for l in file.childNodes:
' 1036 # we're only intrested in normal and added lines
' 1037 if l.nodeName not in ["normal_line", "added_line"]:
' 1038 continue
' 1039 line = Annotate.Line()
' 1040
' 1041 if l.nodeName == "normal_line":
' 1042 patch = l.getElementsByTagName("patch")[0]
' 1043 phash = patch.getAttribute("hash")
' 1044 pauthor = patch.getAttribute("author")
2005-09-19 albertogli 1045 pdate = patch.getAttribute("date")
2008-08-07 albertito 1046 pdate = parse_darcs_time(pdate)
2005-09-19 albertogli 1047 else:
02:50:04 ' 1048 # added lines inherit the creation from the annotate
' 1049 # patch
' 1050 phash = annotate.lastchange_hash
' 1051 pauthor = annotate.lastchange_author
2005-09-19 albertogli 1052 pdate = annotate.lastchange_date
2005-09-19 albertogli 1053
02:50:04 ' 1054 text = ""
' 1055 for node in l.childNodes:
' 1056 if node.nodeType == node.TEXT_NODE:
' 1057 text += node.wholeText
' 1058
' 1059 # strip all "\n"s at the beginning; because the way darcs
' 1060 # formats the xml output it makes the DOM parser to add "\n"s
' 1061 # in front of it
' 1062 text = text.lstrip("\n")
' 1063
2005-09-19 albertogli 1064 line.text = fixu8(text)
06:20:23 ' 1065 line.phash = fixu8(phash)
' 1066 line.pauthor = fixu8(pauthor)
2005-09-21 albertogli 1067 line.pdate = pdate
2005-09-19 albertogli 1068 annotate.lines.append(line)
2005-09-21 albertogli 1069 annotate.patches[line.phash] = line.pdate
05:51:22 ' 1070
' 1071 if pdate > annotate.lastdate:
' 1072 annotate.lastdate = pdate
' 1073 if pdate < annotate.firstdate:
' 1074 annotate.firstdate = pdate
2005-09-19 albertogli 1075
02:50:04 ' 1076 return annotate
' 1077
' 1078 def get_annotate(fname, hash = None):
2008-08-03 albertito 1079 if config.disable_annotate:
15:03:41 ' 1080 return None
' 1081
2005-09-19 albertogli 1082 cmd = 'annotate --xml-output'
02:50:04 ' 1083 if hash:
' 1084 cmd += ' --match="hash %s"' % hash
2008-08-03 albertito 1085
15:02:56 ' 1086 if fname.startswith('/'):
' 1087 # darcs 2 doesn't like files starting with /, and darcs 1
' 1088 # doesn't really care
' 1089 fname = fname[1:]
2005-12-30 albertogli 1090 cmd += ' "%s"' % fname
2008-08-03 albertito 1091
15:03:41 ' 1092 return parse_annotate(run_darcs(cmd))
2005-09-19 albertogli 1093
2011-11-13 pix 1094 def get_readme():
11:23:24 ' 1095 import glob
' 1096 readmes = glob.glob("README*")
' 1097 if len(readmes) == 0: return False, False
' 1098 import re
' 1099 for p in readmes:
' 1100 file = os.path.basename(p)
' 1101 if re.search('\.(md|markdown)$', p):
' 1102 import codecs
' 1103 import markdown
' 1104 f = codecs.open(p, encoding=config.repoencoding[0])
' 1105 str = f.read()
' 1106 html = markdown.markdown(str, ['extra', 'codehilite(css_class=page_body)'])
' 1107 return file, fixu8(html)
' 1108 elif re.search('README$', p):
' 1109 f = open(p)
' 1110 str = f.read()
' 1111 return file, '<pre>%s</pre>' % fixu8(escape(str))
' 1112 # We can't handle this ourselves, try shelling out
' 1113 if not config.readme_converter: return False, False
' 1114 cmd = '%s "%s"' % (config.readme_converter, readmes[0])
' 1115 inf, outf = os.popen2(cmd, 't')
' 1116 return os.path.basename(readmes[0]), fixu8(outf.read())
2005-09-19 albertogli 1117
02:50:04 ' 1118
2005-07-01 albertogli 1119 #
02:55:14 ' 1120 # specific html functions
' 1121 #
' 1122
' 1123 def print_diff(dsrc):
' 1124 for l in dsrc:
2006-02-24 albertogli 1125 l = fixu8(l)
2005-07-01 albertogli 1126
02:55:14 ' 1127 # remove the trailing newline
' 1128 if len(l) > 1:
' 1129 l = l[:-1]
' 1130
' 1131 if l.startswith('diff'):
' 1132 # file lines, they have their own class
2005-09-07 albertogli 1133 print '<div class="diff_info">%s</div>' % escape(l)
2005-07-01 albertogli 1134 continue
02:55:14 ' 1135
' 1136 color = ""
' 1137 if l[0] == '+':
' 1138 color = 'style="color:#008800;"'
' 1139 elif l[0] == '-':
' 1140 color = 'style="color:#cc0000;"'
' 1141 elif l[0] == '@':
2007-04-16 albertito 1142 color = 'style="color:#990099; '
19:06:18 ' 1143 color += 'border: solid #ffe0ff; '
' 1144 color += 'border-width: 1px 0px 0px 0px; '
' 1145 color += 'margin-top: 2px;"'
2005-07-01 albertogli 1146 elif l.startswith('Files'):
02:55:14 ' 1147 # binary differences
' 1148 color = 'style="color:#666;"'
' 1149 print '<div class="pre" %s>' % color + escape(l) + '</div>'
2005-09-07 albertogli 1150
06:25:28 ' 1151
' 1152 def print_darcs_diff(dsrc):
' 1153 for l in dsrc:
2006-02-24 albertogli 1154 l = fixu8(l)
2005-09-07 albertogli 1155
06:25:28 ' 1156 if not l.startswith(" "):
' 1157 # comments and normal stuff
' 1158 print '<div class="pre">' + escape(l) + "</div>"
' 1159 continue
' 1160
' 1161 l = l.strip()
2006-08-09 albertito 1162 if not l:
17:54:30 ' 1163 continue
2005-09-07 albertogli 1164
06:25:28 ' 1165 if l[0] == '+':
' 1166 cl = 'class="pre" style="color:#008800;"'
' 1167 elif l[0] == '-':
' 1168 cl = 'class="pre" style="color:#cc0000;"'
' 1169 else:
' 1170 cl = 'class="diff_info"'
' 1171 print '<div %s>' % cl + escape(l) + '</div>'
2005-07-01 albertogli 1172
02:55:14 ' 1173
2010-03-28 simon 1174 def print_shortlog(last = PATCHES_PER_PAGE, topi = 0, fname = None):
2005-07-23 albertogli 1175 ps = get_last_patches(last, topi, fname)
22:54:35 ' 1176
' 1177 if fname:
' 1178 title = '<a class="title" href="%s;a=filehistory;f=%s">' % \
' 1179 (config.myreponame, fname)
2005-12-30 albertogli 1180 title += 'History for path %s' % escape(fname)
2005-07-23 albertogli 1181 title += '</a>'
22:54:35 ' 1182 else:
' 1183 title = '<a class="title" href="%s;a=shortlog">shortlog</a>' \
' 1184 % config.myreponame
' 1185
' 1186 print '<div>%s</div>' % title
2005-07-01 albertogli 1187 print '<table cellspacing="0">'
2005-07-01 albertogli 1188
02:55:14 ' 1189 if topi != 0:
' 1190 # put a link to the previous page
' 1191 ntopi = topi - last
' 1192 if ntopi < 0:
' 1193 ntopi = 0
2005-07-23 albertogli 1194 print '<tr><td>'
22:54:35 ' 1195 if fname:
' 1196 print '<a href="%s;a=filehistory;topi=%d;f=%s">...</a>' \
' 1197 % (config.myreponame, ntopi, fname)
' 1198 else:
' 1199 print '<a href="%s;a=shortlog;topi=%d">...</a>' \
' 1200 % (config.myreponame, ntopi)
' 1201 print '</td></tr>'
2005-07-01 albertogli 1202
2006-02-21 albertogli 1203 alt = True
2005-07-01 albertogli 1204 for p in ps:
2005-11-10 albertogli 1205 if p.name.startswith("TAG "):
00:34:34 ' 1206 print '<tr class="tag">'
' 1207 elif alt:
2005-07-01 albertogli 1208 print '<tr class="dark">'
02:55:14 ' 1209 else:
' 1210 print '<tr class="light">'
' 1211 alt = not alt
' 1212
' 1213 print """
' 1214 <td><i>%(age)s</i></td>
' 1215 <td>%(author)s</td>
' 1216 <td>
2005-10-30 albertogli 1217 <a class="list" title="%(fullname)s" href="%(myrname)s;a=commit;h=%(hash)s">
21:54:41 ' 1218 <b>%(name)s</b>
' 1219 </a>
2005-07-01 albertogli 1220 </td>
02:55:14 ' 1221 <td class="link">
2005-07-01 albertogli 1222 <a href="%(myrname)s;a=commit;h=%(hash)s">commit</a> |
2005-07-01 albertogli 1223 <a href="%(myrname)s;a=commitdiff;h=%(hash)s">commitdiff</a>
02:55:14 ' 1224 </td>
' 1225 """ % {
' 1226 'age': how_old(p.local_date),
2007-02-01 vmiklos 1227 'author': gen_authorlink(p.author, shorten_str(p.shortauthor, 26)),
2005-07-01 albertogli 1228 'myrname': config.myreponame,
02:55:14 ' 1229 'hash': p.hash,
2005-12-27 mike 1230 'name': escape(shorten_str(p.name)),
2005-11-09 albertogli 1231 'fullname': escape(p.name),
2005-07-01 albertogli 1232 }
02:55:14 ' 1233 print "</tr>"
' 1234
' 1235 if len(ps) >= last:
' 1236 # only show if we've not shown them all already
2005-07-23 albertogli 1237 print '<tr><td>'
22:54:35 ' 1238 if fname:
' 1239 print '<a href="%s;a=filehistory;topi=%d;f=%s">...</a>' \
' 1240 % (config.myreponame, topi + last, fname)
' 1241 else:
' 1242 print '<a href="%s;a=shortlog;topi=%d">...</a>' \
' 1243 % (config.myreponame, topi + last)
' 1244 print '</td></tr>'
2005-07-01 albertogli 1245 print "</table>"
02:55:14 ' 1246
' 1247
2011-11-05 pix 1248 def print_readme():
2011-11-13 pix 1249 head, body = get_readme()
11:23:24 ' 1250 if not head: return False
' 1251 print '<div class="title">%s</div>' % head
' 1252 print '<section>%s</section' % body
2011-11-05 pix 1253
10:18:50 ' 1254
2010-03-28 simon 1255 def print_log(last = PATCHES_PER_PAGE, topi = 0):
2005-07-01 albertogli 1256 ps = get_last_patches(last, topi)
02:55:14 ' 1257
' 1258 if topi != 0:
' 1259 # put a link to the previous page
' 1260 ntopi = topi - last
' 1261 if ntopi < 0:
' 1262 ntopi = 0
2005-07-01 albertogli 1263 print '<p/><a href="%s;a=log;topi=%d">&lt;- Prev</a><p/>' % \
2005-07-01 albertogli 1264 (config.myreponame, ntopi)
02:55:14 ' 1265
' 1266 for p in ps:
' 1267 if p.comment:
2006-12-25 albertito 1268 comment = replace_links(escape(p.comment))
2005-07-23 albertogli 1269 fmt_comment = comment.replace('\n', '<br/>') + '\n'
2005-07-01 albertogli 1270 fmt_comment += '<br/><br/>'
2005-07-01 albertogli 1271 else:
02:55:14 ' 1272 fmt_comment = ''
' 1273 print """
2005-07-01 albertogli 1274 <div><a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">
20:01:39 ' 1275 <span class="age">%(age)s</span>%(desc)s
2005-07-01 albertogli 1276 </a></div>
2005-07-01 albertogli 1277 <div class="title_text">
20:01:39 ' 1278 <div class="log_link">
2005-07-01 albertogli 1279 <a href="%(myreponame)s;a=commit;h=%(hash)s">commit</a> |
2005-07-01 albertogli 1280 <a href="%(myreponame)s;a=commitdiff;h=%(hash)s">commitdiff</a><br/>
2005-07-01 albertogli 1281 </div>
2005-07-01 albertogli 1282 <i>%(author)s [%(date)s]</i><br/>
2005-07-01 albertogli 1283 </div>
02:55:14 ' 1284 <div class="log_body">
' 1285 %(comment)s
' 1286 </div>
' 1287
' 1288 """ % {
' 1289 'myreponame': config.myreponame,
' 1290 'age': how_old(p.local_date),
' 1291 'date': p.local_date_str,
2007-02-01 vmiklos 1292 'author': gen_authorlink(p.author, p.shortauthor),
2005-07-01 albertogli 1293 'hash': p.hash,
2005-07-01 albertogli 1294 'desc': escape(p.name),
2005-07-23 albertogli 1295 'comment': fmt_comment
2005-07-01 albertogli 1296 }
02:55:14 ' 1297
' 1298 if len(ps) >= last:
' 1299 # only show if we've not shown them all already
2005-07-01 albertogli 1300 print '<p><a href="%s;a=log;topi=%d">Next -&gt;</a></p>' % \
2005-07-01 albertogli 1301 (config.myreponame, topi + last)
02:55:14 ' 1302
' 1303
' 1304 def print_blob(fname):
2005-12-30 albertogli 1305 print '<div class="page_path"><b>%s</b></div>' % escape(fname)
2005-07-01 albertogli 1306 if isbinary(fname):
02:55:14 ' 1307 print """
2008-08-07 alexandre.ro 1308 <div class="page_body">
2008-08-03 albertito 1309 <i>This is a binary file and its contents will not be displayed.</i>
2005-07-01 albertogli 1310 </div>
02:55:14 ' 1311 """
' 1312 return
' 1313
2008-10-05 albertito 1314 try:
15:53:16 ' 1315 import pygments
' 1316 except ImportError:
' 1317 pygments = False
' 1318
2008-08-07 alexandre.ro 1319 if not pygments:
05:31:41 ' 1320 print_blob_simple(fname)
' 1321 return
' 1322 else:
' 1323 try:
' 1324 print_blob_highlighted(fname)
' 1325 except ValueError:
' 1326 # pygments couldn't guess a lexer to highlight the code, try
' 1327 # another method with sampling the file contents.
' 1328 try:
' 1329 print_blob_highlighted(fname, sample_code=True)
' 1330 except ValueError:
' 1331 # pygments really could not find any lexer for this file.
' 1332 print_blob_simple(fname)
' 1333
' 1334 def print_blob_simple(fname):
' 1335 print '<div class="page_body">'
' 1336
2005-10-03 albertogli 1337 f = open(realpath(fname), 'r')
2005-07-01 albertogli 1338 count = 1
02:55:14 ' 1339 for l in f:
' 1340 l = fixu8(escape(l))
' 1341 if l and l[-1] == '\n':
' 1342 l = l[:-1]
2005-09-20 albertogli 1343 l = replace_tabs(l)
2005-07-01 albertogli 1344
2005-07-01 albertogli 1345 print """\
20:01:39 ' 1346 <div class="pre">\
' 1347 <a id="l%(c)d" href="#l%(c)d" class="linenr">%(c)4d</a> %(l)s\
2006-07-31 albertito 1348 </div>\
2005-07-01 albertogli 1349 """ % {
02:55:14 ' 1350 'c': count,
' 1351 'l': l
' 1352 }
' 1353 count += 1
' 1354 print '</div>'
' 1355
2008-08-07 alexandre.ro 1356 def print_blob_highlighted(fname, sample_code=False):
2008-10-05 albertito 1357 import pygments
15:53:16 ' 1358 import pygments.lexers
' 1359 import pygments.formatters
' 1360
2008-08-07 alexandre.ro 1361 code = open(realpath(fname), 'r').read()
05:31:41 ' 1362 if sample_code:
' 1363 lexer = pygments.lexers.guess_lexer(code[:200],
' 1364 encoding=config.repoencoding[0])
' 1365 else:
' 1366 lexer = pygments.lexers.guess_lexer_for_filename(fname, code[:200],
' 1367 encoding=config.repoencoding[0])
2008-08-12 alexandre.ro 1368
09:50:07 ' 1369 pygments_version = map(int, pygments.__version__.split('.'))
' 1370 if pygments_version >= [0, 7]:
' 1371 linenos_method = 'inline'
' 1372 else:
' 1373 linenos_method = True
' 1374 formatter = pygments.formatters.HtmlFormatter(linenos=linenos_method,
2008-08-07 alexandre.ro 1375 cssclass='page_body')
2008-08-12 alexandre.ro 1376
2008-08-07 alexandre.ro 1377 print pygments.highlight(code, lexer, formatter)
05:31:41 ' 1378
2005-09-21 albertogli 1379 def print_annotate(ann, style):
2005-09-19 albertogli 1380 print '<div class="page_body">'
02:50:04 ' 1381 if isbinary(ann.fname):
' 1382 print """
2008-08-03 albertito 1383 <i>This is a binary file and its contents will not be displayed.</i>
2005-09-19 albertogli 1384 </div>
02:50:04 ' 1385 """
' 1386 return
' 1387
2005-09-21 albertogli 1388 if style == 'shade':
18:24:58 ' 1389 # here's the idea: we will assign to each patch a shade of
' 1390 # color from its date (newer gets darker)
' 1391 max = 0xff
' 1392 min = max - 80
' 1393
' 1394 # to do that, we need to get a list of the patch hashes
' 1395 # ordered by their dates
' 1396 l = [ (date, hash) for (hash, date) in ann.patches.items() ]
' 1397 l.sort()
' 1398 l = [ hash for (date, hash) in l ]
' 1399
' 1400 # now we have to map each element to a number in the range
' 1401 # min-max, with max being close to l[0] and min l[len(l) - 1]
' 1402 lenn = max - min
' 1403 lenl = len(l)
' 1404 shadetable = {}
' 1405 for i in range(0, lenl):
' 1406 hash = l[i]
' 1407 n = float(i * lenn) / lenl
' 1408 n = max - int(round(n))
' 1409 shadetable[hash] = n
' 1410 elif style == "zebra":
' 1411 lineclass = 'dark'
' 1412
2005-09-19 albertogli 1413 count = 1
2005-09-20 albertogli 1414 prevhash = None
2005-09-19 albertogli 1415 for l in ann.lines:
2005-09-19 albertogli 1416 text = escape(l.text)
2005-09-19 albertogli 1417 text = text.rstrip()
2005-09-20 albertogli 1418 text = replace_tabs(text)
2005-09-21 albertogli 1419 plongdate = time.strftime("%Y-%m-%d %H:%M:%S", l.pdate)
05:51:22 ' 1420 title = "%s by %s" % (plongdate, escape(l.pauthor) )
2005-09-19 albertogli 1421
02:50:04 ' 1422 link = "%(myrname)s;a=commit;h=%(hash)s" % {
' 1423 'myrname': config.myreponame,
' 1424 'hash': l.phash
' 1425 }
2005-09-20 albertogli 1426
2005-09-21 albertogli 1427 if style == "shade":
18:24:58 ' 1428 linestyle = 'style="background-color:#ffff%.2x"' % \
' 1429 shadetable[l.phash]
' 1430 lineclass = ''
' 1431 elif style == "zebra":
' 1432 linestyle = ''
' 1433 if l.phash != prevhash:
' 1434 if lineclass == 'dark':
' 1435 lineclass = 'light'
' 1436 else:
' 1437 lineclass = 'dark'
' 1438 else:
' 1439 linestyle = ''
' 1440 lineclass = ''
' 1441
2005-09-20 albertogli 1442 if l.phash != prevhash:
2005-09-21 albertogli 1443 pdate = time.strftime("%Y-%m-%d", l.pdate)
2005-09-20 albertogli 1444
07:40:25 ' 1445 left = l.pauthor.find('<')
' 1446 right = l.pauthor.find('@')
' 1447 if left != -1 and right != -1:
' 1448 shortau = l.pauthor[left + 1:right]
' 1449 elif l.pauthor.find(" ") != -1:
' 1450 shortau = l.pauthor[:l.pauthor.find(" ")]
2005-09-21 albertogli 1451 elif right != -1:
18:36:17 ' 1452 shortau = l.pauthor[:right]
2005-09-20 albertogli 1453 else:
07:40:25 ' 1454 shortau = l.pauthor
' 1455
2005-09-29 me 1456 desc = "%12.12s" % shortau
2005-09-20 albertogli 1457 date = "%-10.10s" % pdate
07:40:25 ' 1458 prevhash = l.phash
2005-09-29 me 1459 line = 1
2005-09-20 albertogli 1460 else:
2005-10-31 albertogli 1461 if line == 1 and style in ["shade", "zebra"]:
00:11:03 ' 1462 t = "%s " % time.strftime("%H:%M:%S", l.pdate)
' 1463 desc = "%12.12s" % "'"
' 1464 date = "%-10.10s" % t
2005-09-29 me 1465 else:
22:09:49 ' 1466 desc = "%12.12s" % "'"
' 1467 date = "%-10.10s" % ""
2005-10-31 albertogli 1468 line += 1
2005-09-20 albertogli 1469
2005-09-19 albertogli 1470 print """\
2005-09-21 albertogli 1471 <div class="pre %(class)s" %(style)s>\
2005-09-20 albertogli 1472 <a href="%(link)s" title="%(title)s" class="annotate_desc">%(date)s %(desc)s</a> \
2005-09-19 albertogli 1473 <a href="%(link)s" title="%(title)s" class="linenr">%(c)4d</a> \
06:20:23 ' 1474 <a href="%(link)s" title="%(title)s" class="line">%(text)s</a>\
2006-07-31 albertito 1475 </div>\
2005-09-19 albertogli 1476 """ % {
2005-09-21 albertogli 1477 'class': lineclass,
18:24:58 ' 1478 'style': linestyle,
2005-09-20 albertogli 1479 'date': date,
2005-09-29 me 1480 'desc': escape(desc),
2005-09-19 albertogli 1481 'c': count,
02:50:04 ' 1482 'text': text,
2005-09-19 albertogli 1483 'title': title,
2005-09-19 albertogli 1484 'link': link
02:50:04 ' 1485 }
' 1486
' 1487 count += 1
' 1488
' 1489 print '</div>'
' 1490
2005-07-01 albertogli 1491
02:55:14 ' 1492 #
' 1493 # available actions
' 1494 #
' 1495
' 1496 def do_summary():
' 1497 print_header()
' 1498 print_navbar()
' 1499 owner = repo_get_owner()
' 1500
' 1501 # we should optimize this, it's a pity to go in such a mess for just
' 1502 # one hash
' 1503 ps = get_last_patches(1)
' 1504
2005-07-01 albertogli 1505 print '<div class="title">&nbsp;</div>'
20:01:39 ' 1506 print '<table cellspacing="0">'
2006-05-29 albertogli 1507 print ' <tr><td>description</td><td>%s</td></tr>' % \
15:04:37 ' 1508 escape(config.repodesc)
2005-11-09 albertogli 1509 if owner:
00:30:02 ' 1510 print ' <tr><td>owner</td><td>%s</td></tr>' % escape(owner)
2005-10-31 sojkam1 1511 if len(ps) > 0:
10:24:23 ' 1512 print ' <tr><td>last change</td><td>%s</td></tr>' % \
2005-07-01 albertogli 1513 ps[0].local_date_str
02:55:14 ' 1514 print ' <tr><td>url</td><td><a href="%(url)s">%(url)s</a></td></tr>' %\
' 1515 { 'url': config.repourl }
2006-07-31 albertito 1516 if config.repoprojurl:
04:54:05 ' 1517 print ' <tr><td>project url</td>'
2007-04-04 alexandre.ro 1518 print ' <td><a href="%(url)s">%(url)s</a></td></tr>' % \
2006-07-31 albertito 1519 { 'url': config.repoprojurl }
2011-11-01 pix 1520 if config.repolisturl:
08:30:12 ' 1521 print ' <tr><td>mailing list url</td>'
' 1522 print ' <td><a href="%(url)s">%(url)s</a></td></tr>' % \
' 1523 { 'url': config.repolisturl }
2005-07-01 albertogli 1524 print '</table>'
02:55:14 ' 1525
' 1526 print_shortlog(15)
2011-11-05 pix 1527 print_readme()
2005-07-01 albertogli 1528 print_footer()
02:55:14 ' 1529
' 1530
' 1531 def do_commitdiff(phash):
' 1532 print_header()
' 1533 print_navbar(h = phash)
' 1534 p = get_patch(phash)
' 1535 print """
' 1536 <div>
2005-07-01 albertogli 1537 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">%(name)s</a>
2005-07-01 albertogli 1538 </div>
02:55:14 ' 1539 """ % {
' 1540 'myreponame': config.myreponame,
' 1541 'hash': p.hash,
2005-12-27 mike 1542 'name': escape(p.name),
2005-07-01 albertogli 1543 }
02:55:14 ' 1544
' 1545 dsrc = p.getdiff()
' 1546 print_diff(dsrc)
' 1547 print_footer()
2005-08-23 albertogli 1548
23:04:30 ' 1549 def do_plain_commitdiff(phash):
' 1550 print_plain_header()
' 1551 dsrc = get_diff(phash)
' 1552 for l in dsrc:
2005-09-19 albertogli 1553 sys.stdout.write(fixu8(l))
2005-08-23 albertogli 1554
23:04:30 ' 1555 def do_darcs_commitdiff(phash):
2005-09-07 albertogli 1556 print_header()
06:25:28 ' 1557 print_navbar(h = phash)
' 1558 p = get_patch(phash)
' 1559 print """
' 1560 <div>
' 1561 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">%(name)s</a>
' 1562 </div>
' 1563 """ % {
' 1564 'myreponame': config.myreponame,
' 1565 'hash': p.hash,
2005-12-27 mike 1566 'name': escape(p.name),
2005-09-07 albertogli 1567 }
06:25:28 ' 1568
' 1569 dsrc = get_darcs_diff(phash)
' 1570 print_darcs_diff(dsrc)
' 1571 print_footer()
2005-08-23 albertogli 1572
23:04:30 ' 1573 def do_raw_commitdiff(phash):
' 1574 print_plain_header()
' 1575 dsrc = get_raw_diff(phash)
' 1576 if not dsrc:
' 1577 print "Error opening file!"
' 1578 return
' 1579 for l in dsrc:
' 1580 sys.stdout.write(l)
2005-07-01 albertogli 1581
02:55:14 ' 1582
' 1583 def do_headdiff(phash):
' 1584 print_header()
' 1585 print_navbar(h = phash)
' 1586 p = get_patch(phash)
' 1587 print """
' 1588 <div>
2005-07-01 albertogli 1589 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">
2005-07-01 albertogli 1590 %(name)s --&gt; to head</a>
02:55:14 ' 1591 </div>
' 1592 """ % {
' 1593 'myreponame': config.myreponame,
' 1594 'hash': p.hash,
2005-12-27 mike 1595 'name': escape(p.name),
2005-07-01 albertogli 1596 }
02:55:14 ' 1597
' 1598 dsrc = get_patch_headdiff(phash)
' 1599 print_diff(dsrc)
' 1600 print_footer()
2005-08-23 albertogli 1601
23:04:30 ' 1602 def do_plain_headdiff(phash):
' 1603 print_plain_header()
' 1604 dsrc = get_patch_headdiff(phash)
' 1605 for l in dsrc:
2005-09-19 albertogli 1606 sys.stdout.write(fixu8(l))
2005-08-23 albertogli 1607
23:04:30 ' 1608 def do_darcs_headdiff(phash):
2005-09-07 albertogli 1609 print_header()
06:25:28 ' 1610 print_navbar(h = phash)
' 1611 p = get_patch(phash)
' 1612 print """
' 1613 <div>
' 1614 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">
' 1615 %(name)s --&gt; to head</a>
' 1616 </div>
' 1617 """ % {
' 1618 'myreponame': config.myreponame,
' 1619 'hash': p.hash,
2005-12-27 mike 1620 'name': escape(p.name),
2005-09-07 albertogli 1621 }
06:25:28 ' 1622
' 1623 dsrc = get_darcs_headdiff(phash)
' 1624 print_darcs_diff(dsrc)
' 1625 print_footer()
' 1626
' 1627 def do_raw_headdiff(phash):
2005-08-23 albertogli 1628 print_plain_header()
2005-09-07 albertogli 1629 dsrc = get_darcs_headdiff(phash)
06:25:28 ' 1630 for l in dsrc:
' 1631 sys.stdout.write(l)
2005-07-01 albertogli 1632
02:55:14 ' 1633
' 1634 def do_filediff(phash, fname):
' 1635 print_header()
' 1636 print_navbar(h = phash, f = fname)
' 1637 p = get_patch(phash)
' 1638 dsrc = get_file_diff(phash, fname)
' 1639 print """
' 1640 <div>
2005-07-01 albertogli 1641 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">%(name)s</a>
2005-07-01 albertogli 1642 </div>
02:55:14 ' 1643 <div class="page_path"><b>%(fname)s</b></div>
' 1644 """ % {
' 1645 'myreponame': config.myreponame,
' 1646 'hash': p.hash,
2005-12-27 mike 1647 'name': escape(p.name),
2005-12-30 albertogli 1648 'fname': escape(fname),
2005-07-01 albertogli 1649 }
02:55:14 ' 1650
' 1651 print_diff(dsrc)
' 1652 print_footer()
2005-08-23 albertogli 1653
23:04:30 ' 1654 def do_plain_filediff(phash, fname):
' 1655 print_plain_header()
' 1656 dsrc = get_file_diff(phash, fname)
' 1657 for l in dsrc:
2005-09-19 albertogli 1658 sys.stdout.write(fixu8(l))
2005-08-23 albertogli 1659
23:04:30 ' 1660 def do_darcs_filediff(phash, fname):
2005-09-07 albertogli 1661 print_header()
2005-09-07 albertogli 1662 print_navbar(h = phash, f = fname)
2005-09-07 albertogli 1663 p = get_patch(phash)
06:25:28 ' 1664 print """
' 1665 <div>
' 1666 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">%(name)s</a>
' 1667 </div>
' 1668 <div class="page_path"><b>%(fname)s</b></div>
' 1669 """ % {
' 1670 'myreponame': config.myreponame,
' 1671 'hash': p.hash,
2005-12-27 mike 1672 'name': escape(p.name),
2005-12-30 albertogli 1673 'fname': escape(fname),
2005-09-07 albertogli 1674 }
06:25:28 ' 1675
' 1676 dsrc = get_darcs_diff(phash, fname)
' 1677 print_darcs_diff(dsrc)
' 1678 print_footer()
2005-07-01 albertogli 1679
02:55:14 ' 1680
' 1681 def do_file_headdiff(phash, fname):
' 1682 print_header()
' 1683 print_navbar(h = phash, f = fname)
' 1684 p = get_patch(phash)
' 1685 dsrc = get_file_headdiff(phash, fname)
' 1686 print """
' 1687 <div>
2005-07-01 albertogli 1688 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">
2005-07-01 albertogli 1689 %(name)s --&gt; to head</a>
02:55:14 ' 1690 </div>
' 1691 <div class="page_path"><b>%(fname)s</b></div>
' 1692 """ % {
' 1693 'myreponame': config.myreponame,
' 1694 'hash': p.hash,
2005-12-27 mike 1695 'name': escape(p.name),
2005-12-30 albertogli 1696 'fname': escape(fname),
2005-07-01 albertogli 1697 }
02:55:14 ' 1698
' 1699 print_diff(dsrc)
' 1700 print_footer()
' 1701
2005-08-23 albertogli 1702 def do_plain_fileheaddiff(phash, fname):
2005-07-01 albertogli 1703 print_plain_header()
2005-08-23 albertogli 1704 dsrc = get_file_headdiff(phash, fname)
2005-07-01 albertogli 1705 for l in dsrc:
2005-09-19 albertogli 1706 sys.stdout.write(fixu8(l))
2005-08-23 albertogli 1707
23:04:30 ' 1708 def do_darcs_fileheaddiff(phash, fname):
2005-09-07 albertogli 1709 print_header()
2005-09-07 albertogli 1710 print_navbar(h = phash, f = fname)
2005-09-07 albertogli 1711 p = get_patch(phash)
06:25:28 ' 1712 print """
' 1713 <div>
' 1714 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">
' 1715 %(name)s --&gt; to head</a>
' 1716 </div>
' 1717 <div class="page_path"><b>%(fname)s</b></div>
' 1718 """ % {
' 1719 'myreponame': config.myreponame,
' 1720 'hash': p.hash,
2005-12-27 mike 1721 'name': escape(p.name),
2005-12-30 albertogli 1722 'fname': escape(fname),
2005-09-07 albertogli 1723 }
06:25:28 ' 1724
' 1725 dsrc = get_darcs_headdiff(phash, fname)
' 1726 print_darcs_diff(dsrc)
' 1727 print_footer()
' 1728
2005-08-23 albertogli 1729 print_plain_header()
23:04:30 ' 1730 print "Not yet implemented"
2005-07-01 albertogli 1731
02:55:14 ' 1732
' 1733 def do_commit(phash):
' 1734 print_header()
' 1735 print_navbar(h = phash)
' 1736 p = get_patch(phash)
' 1737
' 1738 print """
' 1739 <div>
2005-07-01 albertogli 1740 <a class="title" href="%(myreponame)s;a=commitdiff;h=%(hash)s">%(name)s</a>
2005-07-01 albertogli 1741 </div>
02:55:14 ' 1742
2005-07-01 albertogli 1743 <div class="title_text">
20:01:39 ' 1744 <table cellspacing="0">
2005-07-01 albertogli 1745 <tr><td>author</td><td>%(author)s</td></tr>
02:55:14 ' 1746 <tr><td>local date</td><td>%(local_date)s</td></tr>
' 1747 <tr><td>date</td><td>%(date)s</td></tr>
' 1748 <tr><td>hash</td><td style="font-family: monospace">%(hash)s</td></tr>
' 1749 </table>
' 1750 </div>
' 1751 """ % {
' 1752 'myreponame': config.myreponame,
2007-02-01 vmiklos 1753 'author': gen_authorlink(p.author),
2005-07-01 albertogli 1754 'local_date': p.local_date_str,
02:55:14 ' 1755 'date': p.date_str,
' 1756 'hash': p.hash,
2005-12-27 mike 1757 'name': escape(p.name),
2005-07-01 albertogli 1758 }
02:55:14 ' 1759 if p.comment:
2006-12-25 albertito 1760 comment = replace_links(escape(p.comment))
2005-12-30 albertogli 1761 c = comment.replace('\n', '<br/>\n')
2005-11-06 albertogli 1762 print '<div class="page_body">'
2006-12-25 albertito 1763 print replace_links(escape(p.name)), '<br/><br/>'
2005-11-06 albertogli 1764 print c
23:48:38 ' 1765 print '</div>'
2005-07-01 albertogli 1766
02:55:14 ' 1767 changed = p.adds + p.removes + p.modifies.keys() + p.moves.keys() + \
2005-09-07 albertogli 1768 p.diradds + p.dirremoves + p.replaces.keys()
2005-07-01 albertogli 1769
02:55:14 ' 1770 if changed or p.moves:
' 1771 n = len(changed)
2005-07-01 albertogli 1772 print '<div class="list_head">%d file(s) changed:</div>' % n
2005-07-01 albertogli 1773
2005-07-01 albertogli 1774 print '<table cellspacing="0">'
2005-07-01 albertogli 1775 changed.sort()
2006-02-21 albertogli 1776 alt = True
2005-07-01 albertogli 1777 for f in changed:
02:55:14 ' 1778 if alt:
' 1779 print '<tr class="dark">'
' 1780 else:
' 1781 print '<tr class="light">'
' 1782 alt = not alt
' 1783
' 1784 show_diff = 1
' 1785 if p.moves.has_key(f):
' 1786 # don't show diffs for moves, they're broken as of
' 1787 # darcs 1.0.3
' 1788 show_diff = 0
' 1789
' 1790 if show_diff:
' 1791 print """
' 1792 <td>
2005-07-01 albertogli 1793 <a class="list" href="%(myreponame)s;a=filediff;h=%(hash)s;f=%(file)s">
2006-02-23 albertogli 1794 %(fname)s</a>
2005-07-01 albertogli 1795 </td>
02:55:14 ' 1796 """ % {
' 1797 'myreponame': config.myreponame,
' 1798 'hash': p.hash,
2006-02-23 albertogli 1799 'file': urllib.quote(f),
18:51:21 ' 1800 'fname': escape(f),
2005-07-01 albertogli 1801 }
02:55:14 ' 1802 else:
' 1803 print "<td>%s</td>" % f
' 1804
' 1805 show_diff = 1
' 1806 if f in p.adds:
' 1807 print '<td><span style="color:#008000">',
' 1808 print '[added]',
' 1809 print '</span></td>'
' 1810 elif f in p.diradds:
' 1811 print '<td><span style="color:#008000">',
' 1812 print '[added dir]',
' 1813 print '</span></td>'
' 1814 elif f in p.removes:
' 1815 print '<td><span style="color:#800000">',
' 1816 print '[removed]',
' 1817 print '</span></td>'
' 1818 elif f in p.dirremoves:
' 1819 print '<td><span style="color:#800000">',
' 1820 print '[removed dir]',
2005-09-07 albertogli 1821 print '</span></td>'
16:59:52 ' 1822 elif p.replaces.has_key(f):
' 1823 print '<td><span style="color:#800000">',
' 1824 print '[replaced %d tokens]' % p.replaces[f],
2005-07-01 albertogli 1825 print '</span></td>'
02:55:14 ' 1826 elif p.moves.has_key(f):
' 1827 print '<td><span style="color:#000080">',
' 1828 print '[moved to "%s"]' % p.moves[f]
' 1829 print '</span></td>'
' 1830 show_diff = 0
' 1831 else:
' 1832 print '<td><span style="color:#000080">',
' 1833 if p.modifies[f].has_key('b'):
' 1834 # binary modification
' 1835 print '(binary)'
' 1836 else:
' 1837 print '+%(+)d -%(-)d' % p.modifies[f],
' 1838 print '</span></td>'
' 1839
' 1840 if show_diff:
' 1841 print """
2005-07-23 albertogli 1842 <td class="link">
23:11:32 ' 1843 <a href="%(myreponame)s;a=filediff;h=%(hash)s;f=%(file)s">diff</a> |
2005-09-19 albertogli 1844 <a href="%(myreponame)s;a=filehistory;f=%(file)s">history</a> |
2005-10-03 albertogli 1845 <a href="%(myreponame)s;a=annotate_shade;h=%(hash)s;f=%(file)s">annotate</a>
2005-07-23 albertogli 1846 </td>
2005-07-01 albertogli 1847 """ % {
02:55:14 ' 1848 'myreponame': config.myreponame,
' 1849 'hash': p.hash,
2006-02-23 albertogli 1850 'file': urllib.quote(f)
2005-07-01 albertogli 1851 }
02:55:14 ' 1852 print '</tr>'
' 1853 print '</table>'
' 1854 print_footer()
' 1855
' 1856
' 1857 def do_tree(dname):
' 1858 print_header()
' 1859 print_navbar()
' 1860
' 1861 # the head
' 1862 print """
2005-07-01 albertogli 1863 <div><a class="title" href="%s;a=tree">Current tree</a></div>
2005-07-01 albertogli 1864 <div class="page_path"><b>
02:55:14 ' 1865 """ % config.myreponame
' 1866
' 1867 # and the linked, with links
' 1868 parts = dname.split('/')
' 1869 print '/ '
' 1870 sofar = '/'
' 1871 for p in parts:
' 1872 if not p: continue
' 1873 sofar += '/' + p
' 1874 print '<a href="%s;a=tree;f=%s">%s</a> /' % \
2006-02-23 albertogli 1875 (config.myreponame, urllib.quote(sofar), p)
2005-07-01 albertogli 1876
02:55:14 ' 1877 print """
' 1878 </b></div>
' 1879 <div class="page_body">
' 1880 <table cellspacing="0">
' 1881 """
' 1882
2005-10-03 albertogli 1883 path = realpath(dname) + '/'
2005-10-03 albertogli 1884
2006-02-21 albertogli 1885 alt = True
2005-10-03 albertogli 1886 files = os.listdir(path)
2005-07-01 albertogli 1887 files.sort()
02:55:14 ' 1888
' 1889 # list directories first
' 1890 dlist = []
' 1891 flist = []
' 1892 for f in files:
2005-10-03 albertogli 1893 if f == "_darcs":
04:47:34 ' 1894 continue
' 1895 realfile = path + f
2005-07-01 albertogli 1896 if os.path.isdir(realfile):
02:55:14 ' 1897 dlist.append(f)
' 1898 else:
' 1899 flist.append(f)
' 1900 files = dlist + flist
' 1901
' 1902 for f in files:
' 1903 if alt:
' 1904 print '<tr class="dark">'
' 1905 else:
' 1906 print '<tr class="light">'
' 1907 alt = not alt
2005-10-03 albertogli 1908 realfile = path + f
2006-02-23 albertogli 1909 fullf = filter_file(dname + '/' + f)
2005-07-01 albertogli 1910 print '<td style="font-family:monospace">', fperms(realfile),
02:55:14 ' 1911 print '</td>'
2007-05-03 vmiklos 1912 print '<td style="font-family:monospace">', fsize(realfile),
16:18:30 ' 1913 print '</td>'
2005-07-01 albertogli 1914
02:55:14 ' 1915 if f in dlist:
' 1916 print """
2006-07-06 albertogli 1917 <td>
17:04:59 ' 1918 <a class="link" href="%(myrname)s;a=tree;f=%(fullf)s">%(f)s/</a>
' 1919 </td>
2005-07-23 albertogli 1920 <td class="link">
2006-02-23 albertogli 1921 <a href="%(myrname)s;a=filehistory;f=%(fullf)s">history</a> |
18:51:21 ' 1922 <a href="%(myrname)s;a=tree;f=%(fullf)s">tree</a>
2005-07-23 albertogli 1923 </td>
2005-07-01 albertogli 1924 """ % {
02:55:14 ' 1925 'myrname': config.myreponame,
2005-12-30 albertogli 1926 'f': escape(f),
2006-02-23 albertogli 1927 'fullf': urllib.quote(fullf),
2005-07-01 albertogli 1928 }
02:55:14 ' 1929 else:
' 1930 print """
2005-07-01 albertogli 1931 <td><a class="list" href="%(myrname)s;a=headblob;f=%(fullf)s">%(f)s</a></td>
2005-07-23 albertogli 1932 <td class="link">
23:11:32 ' 1933 <a href="%(myrname)s;a=filehistory;f=%(fullf)s">history</a> |
2005-09-19 albertogli 1934 <a href="%(myrname)s;a=headblob;f=%(fullf)s">headblob</a> |
2005-10-03 albertogli 1935 <a href="%(myrname)s;a=annotate_shade;f=%(fullf)s">annotate</a>
2005-07-23 albertogli 1936 </td>
2005-07-01 albertogli 1937 """ % {
02:55:14 ' 1938 'myrname': config.myreponame,
2005-12-30 albertogli 1939 'f': escape(f),
2006-02-23 albertogli 1940 'fullf': urllib.quote(fullf),
2005-07-01 albertogli 1941 }
02:55:14 ' 1942 print '</tr>'
' 1943 print '</table></div>'
' 1944 print_footer()
' 1945
' 1946
' 1947 def do_headblob(fname):
' 1948 print_header()
' 1949 print_navbar(f = fname)
' 1950 filepath = os.path.dirname(fname)
' 1951
2006-07-31 albertito 1952 if filepath == '/':
05:10:03 ' 1953 print '<div><a class="title" href="%s;a=tree">/</a></div>' % \
' 1954 (config.myreponame)
' 1955 else:
' 1956 print '<div class="title"><b>'
2005-07-01 albertogli 1957
2006-07-31 albertito 1958 # and the linked, with links
05:10:03 ' 1959 parts = filepath.split('/')
' 1960 print '/ '
' 1961 sofar = '/'
' 1962 for p in parts:
' 1963 if not p: continue
' 1964 sofar += '/' + p
' 1965 print '<a href="%s;a=tree;f=%s">%s</a> /' % \
' 1966 (config.myreponame, sofar, p)
' 1967
' 1968 print '</b></div>'
2005-07-01 albertogli 1969
02:55:14 ' 1970 print_blob(fname)
' 1971 print_footer()
' 1972
' 1973
' 1974 def do_plainblob(fname):
2005-10-03 albertogli 1975 f = open(realpath(fname), 'r')
2005-12-21 albertogli 1976
15:00:33 ' 1977 if isbinary(fname):
' 1978 print_binary_header(os.path.basename(fname))
' 1979 for l in f:
' 1980 sys.stdout.write(l)
' 1981 else:
' 1982 print_plain_header()
' 1983 for l in f:
' 1984 sys.stdout.write(fixu8(l))
2005-09-19 albertogli 1985
02:50:04 ' 1986
2005-09-21 albertogli 1987 def do_annotate(fname, phash, style):
2005-09-19 albertogli 1988 print_header()
02:50:04 ' 1989 ann = get_annotate(fname, phash)
2007-03-16 vmiklos 1990 if not ann:
19:27:14 ' 1991 print """
' 1992 <i>The annotate feature has been disabled</i>
' 1993 </div>
' 1994 """
' 1995 print_footer()
' 1996 return
2005-09-19 albertogli 1997 print_navbar(f = fname, h = ann.lastchange_hash)
02:50:04 ' 1998
' 1999 print """
' 2000 <div>
' 2001 <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">%(name)s</a>
' 2002 </div>
' 2003 <div class="page_path"><b>
' 2004 Annotate for file %(fname)s
' 2005 </b></div>
' 2006 """ % {
' 2007 'myreponame': config.myreponame,
' 2008 'hash': ann.lastchange_hash,
2005-09-19 albertogli 2009 'name': escape(ann.lastchange_name),
06:20:23 ' 2010 'fname': escape(fname),
2005-09-19 albertogli 2011 }
02:50:04 ' 2012
2005-09-21 albertogli 2013 print_annotate(ann, style)
2005-09-19 albertogli 2014 print_footer()
02:50:04 ' 2015
' 2016 def do_annotate_plain(fname, phash):
' 2017 print_plain_header()
' 2018 ann = get_annotate(fname, phash)
' 2019 for l in ann.lines:
' 2020 sys.stdout.write(l.text)
2005-07-01 albertogli 2021
02:55:14 ' 2022
2010-03-28 simon 2023 def do_shortlog(topi, last=PATCHES_PER_PAGE):
2005-07-01 albertogli 2024 print_header()
02:55:14 ' 2025 print_navbar()
2010-03-28 simon 2026 print_shortlog(topi = topi, last = last)
2005-07-01 albertogli 2027 print_footer()
02:55:14 ' 2028
2010-03-28 simon 2029 def do_filehistory(topi, f, last=PATCHES_PER_PAGE):
2005-07-23 albertogli 2030 print_header()
22:54:35 ' 2031 print_navbar(f = fname)
2010-03-28 simon 2032 print_shortlog(topi = topi, fname = fname, last = last)
2005-07-23 albertogli 2033 print_footer()
2005-07-01 albertogli 2034
2010-03-28 simon 2035 def do_log(topi, last=PATCHES_PER_PAGE):
2005-07-01 albertogli 2036 print_header()
02:55:14 ' 2037 print_navbar()
2010-03-28 simon 2038 print_log(topi = topi, last = last)
2005-07-01 albertogli 2039 print_footer()
02:55:14 ' 2040
2005-12-01 stephane 2041 def do_atom():
22:07:08 ' 2042 print "Content-type: application/atom+xml; charset=utf-8\n"
' 2043 print '<?xml version="1.0" encoding="utf-8"?>'
2008-08-03 albertito 2044 inv = config.repodir + '/_darcs/patches'
2005-12-01 stephane 2045 repo_lastmod = os.stat(inv).st_mtime
2005-12-13 albertogli 2046 str_lastmod = time.strftime(iso_datetime,
14:12:44 ' 2047 time.localtime(repo_lastmod))
' 2048
' 2049 print """
' 2050 <feed xmlns="http://www.w3.org/2005/Atom">
2005-12-01 stephane 2051 <title>%(reponame)s darcs repository</title>
22:07:08 ' 2052 <link rel="alternate" type="text/html" href="%(url)s"/>
2005-12-13 albertogli 2053 <link rel="self" type="application/atom+xml" href="%(url)s;a=atom"/>
2005-12-01 stephane 2054 <id>%(url)s</id> <!-- TODO: find a better <id>, see RFC 4151 -->
22:07:08 ' 2055 <author><name>darcs repository (several authors)</name></author>
' 2056 <generator>darcsweb.cgi</generator>
' 2057 <updated>%(lastmod)s</updated>
' 2058 <subtitle>%(desc)s</subtitle>
' 2059 """ % {
' 2060 'reponame': config.reponame,
' 2061 'url': config.myurl + '/' + config.myreponame,
2006-05-29 albertogli 2062 'desc': escape(config.repodesc),
2005-12-13 albertogli 2063 'lastmod': str_lastmod,
14:12:44 ' 2064 }
' 2065
2005-12-01 stephane 2066 ps = get_last_patches(20)
22:07:08 ' 2067 for p in ps:
' 2068 title = time.strftime('%d %b %H:%M', time.localtime(p.date))
' 2069 title += ' - ' + p.name
' 2070 pdate = time.strftime(iso_datetime,
' 2071 time.localtime(p.date))
' 2072 link = '%s/%s;a=commit;h=%s' % (config.myurl,
' 2073 config.myreponame, p.hash)
2005-07-01 albertogli 2074
2006-02-22 albertogli 2075 import email.Utils
2005-12-13 albertogli 2076 addr, author = email.Utils.parseaddr(p.author)
14:12:44 ' 2077 if not addr:
' 2078 addr = "unknown_email@example.com"
' 2079 if not author:
' 2080 author = addr
' 2081
2005-12-01 stephane 2082 print """
22:07:08 ' 2083 <entry>
' 2084 <title>%(title)s</title>
2005-12-13 albertogli 2085 <author>
14:12:44 ' 2086 <name>%(author)s</name>
' 2087 <email>%(email)s</email>
' 2088 </author>
2005-12-01 stephane 2089 <updated>%(pdate)s</updated>
2005-12-13 albertogli 2090 <id>%(link)s</id>
2005-12-01 stephane 2091 <link rel="alternate" href="%(link)s"/>
22:07:08 ' 2092 <summary>%(desc)s</summary>
2005-12-13 albertogli 2093 <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>
2005-12-01 stephane 2094 """ % {
22:07:08 ' 2095 'title': escape(title),
2005-12-13 albertogli 2096 'author': author,
14:12:44 ' 2097 'email': addr,
2005-12-01 stephane 2098 'url': config.myurl + '/' + config.myreponame,
22:07:08 ' 2099 'pdate': pdate,
2005-12-13 albertogli 2100 'myrname': config.myreponame,
14:12:44 ' 2101 'hash': p.hash,
2005-12-01 stephane 2102 'pname': escape(p.name),
22:07:08 ' 2103 'link': link,
' 2104 'desc': escape(p.name),
' 2105 }
2005-12-13 albertogli 2106
2005-12-01 stephane 2107 # TODO: allow to get plain text, not HTML?
22:07:08 ' 2108 print escape(p.name) + '<br/>'
' 2109 if p.comment:
' 2110 print '<br/>'
' 2111 print escape(p.comment).replace('\n', '<br/>\n')
' 2112 print '<br/>'
' 2113 print '<br/>'
' 2114 changed = p.adds + p.removes + p.modifies.keys() + \
' 2115 p.moves.keys() + p.diradds + p.dirremoves + \
' 2116 p.replaces.keys()
' 2117 for i in changed: # TODO: link to the file
' 2118 print '<code>%s</code><br/>' % i
' 2119 print '</p></div>'
' 2120 print '</content></entry>'
' 2121 print '</feed>'
2005-12-13 albertogli 2122
2005-07-01 albertogli 2123 def do_rss():
02:55:14 ' 2124 print "Content-type: text/xml; charset=utf-8\n"
' 2125 print '<?xml version="1.0" encoding="utf-8"?>'
' 2126 print """
' 2127 <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
' 2128 <channel>
' 2129 <title>%(reponame)s</title>
' 2130 <link>%(url)s</link>
' 2131 <description>%(desc)s</description>
' 2132 <language>en</language>
' 2133 """ % {
' 2134 'reponame': config.reponame,
' 2135 'url': config.myurl + '/' + config.myreponame,
2006-05-29 albertogli 2136 'desc': escape(config.repodesc),
2005-07-01 albertogli 2137 }
02:55:14 ' 2138
' 2139 ps = get_last_patches(20)
' 2140 for p in ps:
2005-08-24 albertogli 2141 title = time.strftime('%d %b %H:%M', time.localtime(p.date))
2005-07-01 albertogli 2142 title += ' - ' + p.name
02:55:14 ' 2143 pdate = time.strftime("%a, %d %b %Y %H:%M:%S +0000",
' 2144 time.localtime(p.date))
' 2145 link = '%s/%s;a=commit;h=%s' % (config.myurl,
' 2146 config.myreponame, p.hash)
2005-08-23 albertogli 2147
23:54:36 ' 2148 # the author field is tricky because the standard requires it
' 2149 # has an email address; so we need to check that and lie
' 2150 # otherwise; there's more info at
' 2151 # http://feedvalidator.org/docs/error/InvalidContact.html
' 2152 if "@" in p.author:
' 2153 author = p.author
' 2154 else:
2005-09-12 ttimonen 2155 author = "%s &lt;unknown@email&gt;" % p.author
2005-08-23 albertogli 2156
2005-07-01 albertogli 2157 print """
02:55:14 ' 2158 <item>
' 2159 <title>%(title)s</title>
2005-08-23 albertogli 2160 <author>%(author)s</author>
2005-07-01 albertogli 2161 <pubDate>%(pdate)s</pubDate>
02:55:14 ' 2162 <link>%(link)s</link>
' 2163 <description>%(desc)s</description>
' 2164 """ % {
' 2165 'title': escape(title),
2005-08-23 albertogli 2166 'author': author,
2005-07-01 albertogli 2167 'pdate': pdate,
02:55:14 ' 2168 'link': link,
' 2169 'desc': escape(p.name),
' 2170 }
' 2171 print ' <content:encoded><![CDATA['
2005-07-01 albertogli 2172 print escape(p.name) + '<br/>'
2005-07-01 albertogli 2173 if p.comment:
2005-07-01 albertogli 2174 print '<br/>'
20:01:39 ' 2175 print escape(p.comment).replace('\n', '<br/>\n')
2005-10-30 albertogli 2176 print '<br/>'
23:23:47 ' 2177 print '<br/>'
' 2178 changed = p.adds + p.removes + p.modifies.keys() + \
' 2179 p.moves.keys() + p.diradds + p.dirremoves + \
' 2180 p.replaces.keys()
' 2181 for i in changed:
' 2182 print '%s<br/>' % i
2005-07-01 albertogli 2183 print ']]>'
02:55:14 ' 2184 print '</content:encoded></item>'
' 2185
' 2186 print '</channel></rss>'
' 2187
' 2188
2006-01-09 albertogli 2189 def do_search(s):
05:24:26 ' 2190 print_header()
' 2191 print_navbar()
' 2192 ps = get_last_patches(config.searchlimit)
' 2193
' 2194 print '<div class="title">Search last %d commits for "%s"</div>' \
' 2195 % (config.searchlimit, escape(s))
' 2196 print '<table cellspacing="0">'
' 2197
2006-02-21 albertogli 2198 alt = True
2006-01-09 albertogli 2199 for p in ps:
05:24:26 ' 2200 match = p.matches(s)
' 2201 if not match:
' 2202 continue
' 2203
' 2204 if alt:
' 2205 print '<tr class="dark">'
' 2206 else:
' 2207 print '<tr class="light">'
' 2208 alt = not alt
' 2209
' 2210 print """
' 2211 <td><i>%(age)s</i></td>
' 2212 <td>%(author)s</td>
' 2213 <td>
' 2214 <a class="list" title="%(fullname)s" href="%(myrname)s;a=commit;h=%(hash)s">
' 2215 <b>%(name)s</b>
' 2216 </a><br/>
' 2217 %(match)s
' 2218 </td>
' 2219 <td class="link">
' 2220 <a href="%(myrname)s;a=commit;h=%(hash)s">commit</a> |
' 2221 <a href="%(myrname)s;a=commitdiff;h=%(hash)s">commitdiff</a>
' 2222 </td>
' 2223 """ % {
' 2224 'age': how_old(p.local_date),
2007-02-01 vmiklos 2225 'author': gen_authorlink(p.author, shorten_str(p.shortauthor, 26)),
2006-01-09 albertogli 2226 'myrname': config.myreponame,
05:24:26 ' 2227 'hash': p.hash,
' 2228 'name': escape(shorten_str(p.name)),
' 2229 'fullname': escape(p.name),
' 2230 'match': highlight(s, shorten_str(match)),
' 2231 }
' 2232 print "</tr>"
' 2233
' 2234 print '</table>'
' 2235 print_footer()
' 2236
' 2237
2005-07-01 albertogli 2238 def do_die():
02:55:14 ' 2239 print_header()
' 2240 print "<p><font color=red>Error! Malformed query</font></p>"
' 2241 print_footer()
' 2242
' 2243
' 2244 def do_listrepos():
' 2245 import config as all_configs
2006-07-31 albertito 2246 expand_multi_config(all_configs)
2005-07-01 albertogli 2247
02:55:14 ' 2248 # the header here is special since we don't have a repo
' 2249 print "Content-type: text/html; charset=utf-8\n"
2005-10-26 niol 2250 print '<?xml version="1.0" encoding="utf-8"?>'
2005-07-01 albertogli 2251 print """
02:55:14 ' 2252 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
' 2253 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
' 2254 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
' 2255 <head>
' 2256 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
' 2257 <meta name="robots" content="index, nofollow"/>
' 2258 <title>darcs - Repositories</title>
2005-07-01 albertogli 2259 <link rel="stylesheet" type="text/css" href="%(css)s"/>
20:01:39 ' 2260 <link rel="shortcut icon" href="%(fav)s"/>
' 2261 <link rel="icon" href="%(fav)s"/>
2005-07-01 albertogli 2262 </head>
02:55:14 ' 2263
' 2264 <body>
' 2265 <div class="page_header">
2005-07-01 albertogli 2266 <a href="http://darcs.net" title="darcs">
20:01:39 ' 2267 <img src="%(logo)s" alt="darcs logo" style="float:right; border-width:0px;"/>
2005-07-01 albertogli 2268 </a>
02:55:14 ' 2269 <a href="%(myname)s">repos</a> / index
' 2270 </div>
' 2271 <div class="index_include">
2005-08-24 albertogli 2272 %(summary)s
2005-07-01 albertogli 2273 </div>
02:55:14 ' 2274 <table cellspacing="0">
' 2275 <tr>
' 2276 <th>Project</th>
' 2277 <th>Description</th>
2011-11-01 pix 2278 <th>Owner</th>
10:19:57 ' 2279 <th>Last Change</th>
2005-07-01 albertogli 2280 <th></th>
02:55:14 ' 2281 </tr>
' 2282 """ % {
2005-08-24 albertogli 2283 'myname': config.myname,
18:38:04 ' 2284 'css': config.cssfile,
' 2285 'fav': config.darcsfav,
' 2286 'logo': config.darcslogo,
' 2287 'summary': config.summary
2005-07-01 albertogli 2288 }
02:55:14 ' 2289
' 2290 # some python magic
2006-02-21 albertogli 2291 alt = True
2005-07-01 albertogli 2292 for conf in dir(all_configs):
02:55:14 ' 2293 if conf.startswith('__'):
' 2294 continue
' 2295 c = all_configs.__getattribute__(conf)
' 2296 if 'reponame' not in dir(c):
' 2297 continue
' 2298 name = escape(c.reponame)
' 2299 desc = escape(c.repodesc)
' 2300
' 2301 if alt: print '<tr class="dark">'
' 2302 else: print '<tr class="light">'
' 2303 alt = not alt
2011-11-01 pix 2304 try: orig_repodir = config.repodir
10:19:57 ' 2305 except: orig_repodir = None
' 2306 config.repodir = c.repodir
2005-07-01 albertogli 2307 print """
2005-07-03 albertogli 2308 <td><a class="list" href="%(myname)s?r=%(name)s;a=summary">%(dname)s</a></td>
2005-07-01 albertogli 2309 <td>%(desc)s</td>
2011-11-01 pix 2310 <td>%(owner)s</td>
10:19:57 ' 2311 <td>%(lastchange)s</td>
2005-07-01 albertogli 2312 <td class="link"><a href="%(myname)s?r=%(name)s;a=summary">summary</a> |
20:01:39 ' 2313 <a href="%(myname)s?r=%(name)s;a=shortlog">shortlog</a> |
' 2314 <a href="%(myname)s?r=%(name)s;a=log">log</a> |
' 2315 <a href="%(myname)s?r=%(name)s;a=tree">tree</a>
2005-07-01 albertogli 2316 </td>
02:55:14 ' 2317 </tr>
' 2318 """ % {
2006-07-31 albertito 2319 'myname': config.myname,
2005-07-03 albertogli 2320 'dname': name,
21:39:57 ' 2321 'name': urllib.quote(name),
2011-11-01 pix 2322 'desc': shorten_str(desc, 60),
10:19:57 ' 2323 'owner': escape(repo_get_owner() or ''),
' 2324 'lastchange': how_old(os.stat(c.repodir + '/_darcs/patches').st_mtime),
2005-07-01 albertogli 2325 }
2011-11-01 pix 2326 config.repodir = orig_repodir
2005-07-01 albertogli 2327 print "</table>"
02:55:14 ' 2328 print_footer(put_rss = 0)
' 2329
2005-11-09 albertogli 2330 def expand_multi_config(config):
00:17:31 ' 2331 """Expand configuration entries that serve as "template" to others;
' 2332 this make it easier to have a single directory with all the repos,
' 2333 because they don't need specific entries in the configuration anymore.
' 2334 """
' 2335
' 2336 for conf in dir(config):
' 2337 if conf.startswith('__'):
' 2338 continue
' 2339 c = config.__getattribute__(conf)
' 2340 if 'multidir' not in dir(c):
' 2341 continue
' 2342
2008-10-05 albertito 2343 if not os.path.isdir(c.multidir):
15:48:31 ' 2344 continue
' 2345
2005-11-09 albertogli 2346 if 'exclude' not in dir(c):
23:59:47 ' 2347 c.exclude = []
2005-12-20 nils 2348
16:30:22 ' 2349 entries = []
' 2350 if 'multidir_deep' in dir(c) and c.multidir_deep:
2005-12-21 albertogli 2351 for (root, dirs, files) in os.walk(c.multidir):
14:29:46 ' 2352 # do not visit hidden directories
' 2353 dirs[:] = [d for d in dirs \
' 2354 if not d.startswith('.')]
' 2355 if '_darcs' in dirs:
' 2356 p = root[1 + len(c.multidir):]
' 2357 entries.append(p)
2005-12-20 nils 2358 else:
2005-12-21 albertogli 2359 entries = os.listdir(c.multidir)
2005-12-20 nils 2360
2005-11-09 albertogli 2361 entries.sort()
2005-11-09 albertogli 2362 for name in entries:
2007-05-16 jonathan.buc 2363 name = name.replace('\\', '/')
2005-11-09 albertogli 2364 if name.startswith('.'):
00:23:06 ' 2365 continue
' 2366 fulldir = c.multidir + '/' + name
2005-11-09 albertogli 2367 if not os.path.isdir(fulldir + '/_darcs'):
2005-11-09 albertogli 2368 continue
23:59:47 ' 2369 if name in c.exclude:
2005-11-09 albertogli 2370 continue
00:23:06 ' 2371
2008-03-27 albertito 2372 # set the display name at the beginning, so it can be
01:02:58 ' 2373 # used by the other replaces
' 2374 if 'displayname' in dir(c):
' 2375 dname = c.displayname % { 'name': name }
' 2376 else:
' 2377 dname = name
' 2378
' 2379 rep_dict = { 'name': name, 'dname': dname }
' 2380
2005-12-30 albertogli 2381 if 'autoexclude' in dir(c) and c.autoexclude:
23:44:19 ' 2382 dpath = fulldir + \
' 2383 '/_darcs/third_party/darcsweb'
' 2384 if not os.path.isdir(dpath):
' 2385 continue
' 2386
' 2387 if 'autodesc' in dir(c) and c.autodesc:
' 2388 dpath = fulldir + \
' 2389 '/_darcs/third_party/darcsweb/desc'
' 2390 if os.access(dpath, os.R_OK):
2007-04-16 alexandre.ro 2391 desc = open(dpath).readline().rstrip("\n")
2005-12-30 albertogli 2392 else:
2008-03-27 albertito 2393 desc = c.repodesc % rep_dict
2005-12-30 albertogli 2394 else:
2008-03-27 albertito 2395 desc = c.repodesc % rep_dict
2005-12-30 albertogli 2396
2006-07-14 albertogli 2397 if 'autourl' in dir(c) and c.autourl:
19:27:30 ' 2398 dpath = fulldir + \
' 2399 '/_darcs/third_party/darcsweb/url'
' 2400 if os.access(dpath, os.R_OK):
2007-04-16 alexandre.ro 2401 url = open(dpath).readline().rstrip("\n")
2006-07-14 albertogli 2402 else:
2008-03-27 albertito 2403 url = c.repourl % rep_dict
2006-07-14 albertogli 2404 else:
2008-03-27 albertito 2405 url = c.repourl % rep_dict
2006-07-14 albertogli 2406
2006-07-31 albertito 2407 if 'autoprojurl' in dir(c) and c.autoprojurl:
04:54:05 ' 2408 dpath = fulldir + \
' 2409 '/_darcs/third_party/darcsweb/projurl'
' 2410 if os.access(dpath, os.R_OK):
2007-04-16 alexandre.ro 2411 projurl = open(dpath).readline().rstrip("\n")
2006-07-31 albertito 2412 elif 'repoprojurl' in dir(c):
2008-03-27 albertito 2413 projurl = c.repoprojurl % rep_dict
2006-07-31 albertito 2414 else:
04:54:05 ' 2415 projurl = None
' 2416 elif 'repoprojurl' in dir(c):
2008-03-27 albertito 2417 projurl = c.repoprojurl % rep_dict
2006-07-31 albertito 2418 else:
04:54:05 ' 2419 projurl = None
' 2420
2011-11-01 pix 2421 if 'autolisturl' in dir(c) and c.autolisturl:
08:30:12 ' 2422 dpath = fulldir + \
' 2423 '/_darcs/third_party/darcsweb/listurl'
' 2424 if os.access(dpath, os.R_OK):
' 2425 listurl = open(dpath).readline().rstrip("\n")
' 2426 elif 'repolisturl' in dir(c):
' 2427 listurl = c.repolisturl % rep_dict
' 2428 else:
' 2429 listurl = None
' 2430 elif 'repolisturl' in dir(c):
' 2431 listurl = c.repolisturl % rep_dict
' 2432 else:
' 2433 listurl = None
' 2434
2005-11-09 albertogli 2435 rdir = fulldir
2005-11-09 albertogli 2436 class tmp_config:
2008-03-27 albertito 2437 reponame = dname
2005-11-09 albertogli 2438 repodir = rdir
00:17:31 ' 2439 repodesc = desc
' 2440 repourl = url
2006-02-24 albertogli 2441 repoencoding = c.repoencoding
2006-07-31 albertito 2442 repoprojurl = projurl
2011-11-01 pix 2443 repolisturl = listurl
2006-02-24 albertogli 2444
2005-11-09 albertogli 2445 if 'footer' in dir(c):
00:17:31 ' 2446 footer = c.footer
2006-07-31 albertito 2447
2008-03-27 albertito 2448 # index by display name to avoid clashes
01:02:58 ' 2449 config.__setattr__(dname, tmp_config)
2005-11-09 albertogli 2450
2005-08-24 albertogli 2451 def fill_config(name = None):
2005-07-01 albertogli 2452 import config as all_configs
2005-11-09 albertogli 2453 expand_multi_config(all_configs)
2005-08-24 albertogli 2454
18:38:04 ' 2455 if name:
' 2456 # we only care about setting some configurations if a repo was
' 2457 # specified; otherwise we only set the common configuration
' 2458 # directives
' 2459 for conf in dir(all_configs):
' 2460 if conf.startswith('__'):
' 2461 continue
' 2462 c = all_configs.__getattribute__(conf)
' 2463 if 'reponame' not in dir(c):
' 2464 continue
' 2465 if c.reponame == name:
' 2466 break
' 2467 else:
' 2468 # not found
2010-06-25 albertito 2469 raise Exception, "Repo not found: " + repr(name)
2005-07-01 albertogli 2470
02:55:14 ' 2471 # fill the configuration
' 2472 base = all_configs.base
2006-07-31 albertito 2473 if 'myname' not in dir(base):
04:10:20 ' 2474 # SCRIPT_NAME has the full path, we only take the file name
' 2475 config.myname = os.path.basename(os.environ['SCRIPT_NAME'])
' 2476 else:
' 2477 config.myname = base.myname
' 2478
2011-11-01 pix 2479 if 'myurl' not in dir(base):
2006-07-31 albertito 2480 n = os.environ['SERVER_NAME']
04:10:20 ' 2481 p = os.environ['SERVER_PORT']
2007-05-16 jonathan.buc 2482 s = os.path.dirname(os.environ['SCRIPT_NAME'])
2007-06-22 peterco 2483 u = os.environ.get('HTTPS', 'off') in ('on', '1')
09:30:21 ' 2484 if not u and p == '80' or u and p == '443':
2006-07-31 albertito 2485 p = ''
04:10:20 ' 2486 else:
' 2487 p = ':' + p
2007-06-22 peterco 2488 config.myurl = 'http%s://%s%s%s' % (u and 's' or '', n, p, s)
2006-07-31 albertito 2489 else:
04:10:20 ' 2490 config.myurl = base.myurl
' 2491
2005-07-01 albertogli 2492 config.darcslogo = base.darcslogo
02:55:14 ' 2493 config.darcsfav = base.darcsfav
' 2494 config.cssfile = base.cssfile
2005-08-24 albertogli 2495 if name:
2006-07-31 albertito 2496 config.myreponame = config.myname + '?r=' + urllib.quote(name)
2005-08-24 albertogli 2497 config.reponame = c.reponame
18:38:04 ' 2498 config.repodesc = c.repodesc
' 2499 config.repodir = c.repodir
' 2500 config.repourl = c.repourl
2006-07-31 albertito 2501
04:54:05 ' 2502 config.repoprojurl = None
' 2503 if 'repoprojurl' in dir(c):
' 2504 config.repoprojurl = c.repoprojurl
' 2505
2011-11-01 pix 2506 config.repolisturl = None
08:30:12 ' 2507 if 'repolisturl' in dir(c):
' 2508 config.repolisturl = c.repolisturl
' 2509
2006-02-24 albertogli 2510 # repoencoding must be a tuple
01:37:00 ' 2511 if isinstance(c.repoencoding, str):
' 2512 config.repoencoding = (c.repoencoding, )
' 2513 else:
' 2514 config.repoencoding = c.repoencoding
2005-08-23 albertogli 2515
23:16:47 ' 2516 # optional parameters
' 2517 if "darcspath" in dir(base):
' 2518 config.darcspath = base.darcspath + '/'
' 2519 else:
' 2520 config.darcspath = ""
2005-08-24 albertogli 2521
18:38:04 ' 2522 if "summary" in dir(base):
' 2523 config.summary = base.summary
' 2524 else:
' 2525 config.summary = """
' 2526 This is the repository index for a darcsweb site.<br/>
' 2527 These are all the available repositories.<br/>
' 2528 """
2005-11-17 albertogli 2529
03:10:28 ' 2530 if "cachedir" in dir(base):
' 2531 config.cachedir = base.cachedir
' 2532 else:
' 2533 config.cachedir = None
2005-08-24 albertogli 2534
2006-01-09 albertogli 2535 if "searchlimit" in dir(base):
05:24:26 ' 2536 config.searchlimit = base.searchlimit
' 2537 else:
' 2538 config.searchlimit = 100
' 2539
2006-02-20 albertogli 2540 if "logtimes" in dir(base):
03:23:19 ' 2541 config.logtimes = base.logtimes
' 2542 else:
' 2543 config.logtimes = None
' 2544
2006-12-25 albertito 2545 if "url_links" in dir(base):
22:18:20 ' 2546 config.url_links = base.url_links
' 2547 else:
' 2548 config.url_links = ()
' 2549
2005-08-24 albertogli 2550 if name and "footer" in dir(c):
18:38:04 ' 2551 config.footer = c.footer
' 2552 elif "footer" in dir(base):
' 2553 config.footer = base.footer
' 2554 else:
' 2555 config.footer = "Crece desde el pueblo el futuro / " \
' 2556 + "crece desde el pie"
2007-02-01 vmiklos 2557 if "author_links" in dir(base):
17:30:50 ' 2558 config.author_links = base.author_links
' 2559 else:
' 2560 config.author_links = None
2007-03-16 vmiklos 2561 if "disable_annotate" in dir(base):
19:27:14 ' 2562 config.disable_annotate = base.disable_annotate
' 2563 else:
' 2564 config.disable_annotate = False
2005-11-17 albertogli 2565
2011-11-13 pix 2566 if "readme_converter" in dir(base):
11:23:24 ' 2567 config.readme_converter = base.readme_converter
' 2568 else:
' 2569 config.readme_converter = False
' 2570
2005-07-01 albertogli 2571
02:55:14 ' 2572
' 2573 #
' 2574 # main
' 2575 #
2007-01-24 albertito 2576
23:38:07 ' 2577 if sys.version_info < (2, 3):
' 2578 print "Sorry, but Python 2.3 or above is required to run darcsweb."
' 2579 sys.exit(1)
2005-07-01 albertogli 2580
02:55:14 ' 2581 form = cgi.FieldStorage()
' 2582
' 2583 # if they don't specify a repo, print the list and exit
' 2584 if not form.has_key('r'):
2005-08-24 albertogli 2585 fill_config()
2005-07-01 albertogli 2586 do_listrepos()
2006-02-20 albertogli 2587 log_times(cache_hit = 0, event = 'index')
2005-07-01 albertogli 2588 sys.exit(0)
02:55:14 ' 2589
' 2590 # get the repo configuration and fill the config class
2005-07-03 albertogli 2591 current_repo = urllib.unquote(form['r'].value)
2005-07-01 albertogli 2592 fill_config(current_repo)
02:55:14 ' 2593
' 2594
' 2595 # get the action, or default to summary
' 2596 if not form.has_key("a"):
' 2597 action = "summary"
' 2598 else:
2005-08-23 albertogli 2599 action = filter_act(form["a"].value)
2005-11-17 albertogli 2600
03:10:28 ' 2601 # check if we have the page in the cache
' 2602 if config.cachedir:
' 2603 url_request = os.environ['QUERY_STRING']
2006-01-09 albertogli 2604 # create a string representation of the request, ignoring all the
05:58:01 ' 2605 # unused parameters to avoid DoS
2010-03-28 simon 2606 params = ['r', 'a', 'f', 'h', 'topi', 'last']
2006-01-09 albertogli 2607 params = [ x for x in form.keys() if x in params ]
05:58:01 ' 2608 url_request = [ (x, form[x].value) for x in params ]
' 2609 url_request.sort()
2005-11-17 albertogli 2610 cache = Cache(config.cachedir, url_request)
03:10:28 ' 2611 if cache.open():
' 2612 # we have a hit, dump and run
' 2613 cache.dump()
' 2614 cache.close()
2006-02-23 albertogli 2615 log_times(cache_hit = 1, repo = config.reponame)
2005-11-17 albertogli 2616 sys.exit(0)
03:10:28 ' 2617 # if there is a miss, the cache will step over stdout, intercepting
' 2618 # all "print"s and writing them to the cache file automatically
2005-07-01 albertogli 2619
02:55:14 ' 2620
' 2621 # see what should we do according to the received action
' 2622 if action == "summary":
' 2623 do_summary()
2005-08-23 albertogli 2624
2005-07-01 albertogli 2625 elif action == "commit":
02:55:14 ' 2626 phash = filter_hash(form["h"].value)
' 2627 do_commit(phash)
' 2628 elif action == "commitdiff":
' 2629 phash = filter_hash(form["h"].value)
' 2630 do_commitdiff(phash)
2005-08-23 albertogli 2631 elif action == "plain_commitdiff":
23:04:30 ' 2632 phash = filter_hash(form["h"].value)
' 2633 do_plain_commitdiff(phash)
' 2634 elif action == "darcs_commitdiff":
' 2635 phash = filter_hash(form["h"].value)
' 2636 do_darcs_commitdiff(phash)
' 2637 elif action == "raw_commitdiff":
' 2638 phash = filter_hash(form["h"].value)
' 2639 do_raw_commitdiff(phash)
' 2640
2005-07-01 albertogli 2641 elif action == 'headdiff':
02:55:14 ' 2642 phash = filter_hash(form["h"].value)
' 2643 do_headdiff(phash)
2005-08-23 albertogli 2644 elif action == "plain_headdiff":
23:04:30 ' 2645 phash = filter_hash(form["h"].value)
' 2646 do_plain_headdiff(phash)
' 2647 elif action == "darcs_headdiff":
' 2648 phash = filter_hash(form["h"].value)
' 2649 do_darcs_headdiff(phash)
' 2650
2005-07-01 albertogli 2651 elif action == "filediff":
02:55:14 ' 2652 phash = filter_hash(form["h"].value)
' 2653 fname = filter_file(form["f"].value)
' 2654 do_filediff(phash, fname)
2005-08-23 albertogli 2655 elif action == "plain_filediff":
23:04:30 ' 2656 phash = filter_hash(form["h"].value)
' 2657 fname = filter_file(form["f"].value)
' 2658 do_plain_filediff(phash, fname)
' 2659 elif action == "darcs_filediff":
' 2660 phash = filter_hash(form["h"].value)
2005-09-07 albertogli 2661 fname = filter_file(form["f"].value)
06:25:28 ' 2662 do_darcs_filediff(phash, fname)
2005-08-23 albertogli 2663
2005-07-01 albertogli 2664 elif action == 'headfilediff':
02:55:14 ' 2665 phash = filter_hash(form["h"].value)
' 2666 fname = filter_file(form["f"].value)
' 2667 do_file_headdiff(phash, fname)
2005-08-23 albertogli 2668 elif action == "plain_headfilediff":
2005-07-01 albertogli 2669 phash = filter_hash(form["h"].value)
02:55:14 ' 2670 fname = filter_file(form["f"].value)
2005-08-23 albertogli 2671 do_plain_fileheaddiff(phash, fname)
23:04:30 ' 2672 elif action == "darcs_headfilediff":
' 2673 phash = filter_hash(form["h"].value)
2005-09-07 albertogli 2674 fname = filter_file(form["f"].value)
06:25:28 ' 2675 do_darcs_fileheaddiff(phash, fname)
2005-08-23 albertogli 2676
2005-10-03 albertogli 2677 elif action == "annotate_normal":
2005-09-19 albertogli 2678 fname = filter_file(form["f"].value)
02:50:04 ' 2679 if form.has_key("h"):
' 2680 phash = filter_hash(form["h"].value)
' 2681 else:
' 2682 phash = None
2005-09-21 albertogli 2683 do_annotate(fname, phash, "normal")
2005-09-19 albertogli 2684 elif action == "annotate_plain":
02:50:04 ' 2685 fname = filter_file(form["f"].value)
' 2686 if form.has_key("h"):
' 2687 phash = filter_hash(form["h"].value)
' 2688 else:
' 2689 phash = None
' 2690 do_annotate_plain(fname, phash)
2005-09-21 albertogli 2691 elif action == "annotate_zebra":
18:24:58 ' 2692 fname = filter_file(form["f"].value)
' 2693 if form.has_key("h"):
' 2694 phash = filter_hash(form["h"].value)
' 2695 else:
' 2696 phash = None
' 2697 do_annotate(fname, phash, "zebra")
' 2698 elif action == "annotate_shade":
' 2699 fname = filter_file(form["f"].value)
' 2700 if form.has_key("h"):
' 2701 phash = filter_hash(form["h"].value)
' 2702 else:
' 2703 phash = None
' 2704 do_annotate(fname, phash, "shade")
2005-08-23 albertogli 2705
2005-07-01 albertogli 2706 elif action == "shortlog":
02:55:14 ' 2707 if form.has_key("topi"):
' 2708 topi = int(filter_num(form["topi"].value))
' 2709 else:
' 2710 topi = 0
2010-03-28 simon 2711 if form.has_key("last"):
16:40:18 ' 2712 last = int(filter_num(form["last"].value))
' 2713 else:
' 2714 last = PATCHES_PER_PAGE
' 2715 do_shortlog(topi=topi,last=last)
2005-08-23 albertogli 2716
2005-07-23 albertogli 2717 elif action == "filehistory":
22:54:35 ' 2718 if form.has_key("topi"):
' 2719 topi = int(filter_num(form["topi"].value))
' 2720 else:
' 2721 topi = 0
' 2722 fname = filter_file(form["f"].value)
2010-03-28 simon 2723 if form.has_key("last"):
16:40:18 ' 2724 last = int(filter_num(form["last"].value))
' 2725 else:
' 2726 last = PATCHES_PER_PAGE
' 2727 do_filehistory(topi, fname, last=last)
2005-08-23 albertogli 2728
2005-07-01 albertogli 2729 elif action == "log":
02:55:14 ' 2730 if form.has_key("topi"):
' 2731 topi = int(filter_num(form["topi"].value))
' 2732 else:
' 2733 topi = 0
2010-03-28 simon 2734 if form.has_key("last"):
16:40:18 ' 2735 last = int(filter_num(form["last"].value))
' 2736 else:
' 2737 last = PATCHES_PER_PAGE
' 2738 do_log(topi, last=last)
2005-08-23 albertogli 2739
2005-07-01 albertogli 2740 elif action == 'headblob':
02:55:14 ' 2741 fname = filter_file(form["f"].value)
' 2742 do_headblob(fname)
2005-08-23 albertogli 2743
2005-07-01 albertogli 2744 elif action == 'plainblob':
02:55:14 ' 2745 fname = filter_file(form["f"].value)
' 2746 do_plainblob(fname)
2005-08-23 albertogli 2747
2005-07-01 albertogli 2748 elif action == 'tree':
02:55:14 ' 2749 if form.has_key('f'):
' 2750 fname = filter_file(form["f"].value)
' 2751 else:
' 2752 fname = '/'
' 2753 do_tree(fname)
2005-08-23 albertogli 2754
2005-07-01 albertogli 2755 elif action == 'rss':
02:55:14 ' 2756 do_rss()
2005-12-01 stephane 2757
22:07:08 ' 2758 elif action == 'atom':
' 2759 do_atom()
2005-08-23 albertogli 2760
2006-01-09 albertogli 2761 elif action == 'search':
05:24:26 ' 2762 if form.has_key('s'):
' 2763 s = form["s"].value
' 2764 else:
' 2765 s = ''
' 2766 do_search(s)
' 2767 if config.cachedir:
' 2768 cache.cancel()
' 2769
2005-07-01 albertogli 2770 else:
02:55:14 ' 2771 action = "invalid query"
' 2772 do_die()
2005-11-17 albertogli 2773 if config.cachedir:
03:27:57 ' 2774 cache.cancel()
2005-09-19 albertogli 2775
2005-07-01 albertogli 2776
2005-11-17 albertogli 2777 if config.cachedir:
03:10:28 ' 2778 cache.close()
2005-07-01 albertogli 2779
2006-02-23 albertogli 2780 log_times(cache_hit = 0, repo = config.reponame)
2006-02-20 albertogli 2781
03:23:19 ' 2782