repos
/
darcsweb
/ annotate_shade
summary
|
shortlog
|
log
|
tree
|
commit
|
commitdiff
|
headdiff
|
annotate
|
headblob
|
headfilediff
|
filehistory
normal
|
plain
|
shade
|
zebra
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('"', '"')
'
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"><- 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 -></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"> </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 --> 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 --> 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 --> 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 --> 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 <unknown@email>" % 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