##// END OF EJS Templates
hgweb: kill off #filenode#
Brendan Cully -
r3206:79fd7a92 default
parent child Browse files
Show More
@@ -1,957 +1,954
1 # hgweb/hgweb_mod.py - Web interface for a repository.
1 # hgweb/hgweb_mod.py - Web interface for a repository.
2 #
2 #
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms
6 # This software may be used and distributed according to the terms
7 # of the GNU General Public License, incorporated herein by reference.
7 # of the GNU General Public License, incorporated herein by reference.
8
8
9 import os
9 import os
10 import os.path
10 import os.path
11 import mimetypes
11 import mimetypes
12 from mercurial.demandload import demandload
12 from mercurial.demandload import demandload
13 demandload(globals(), "re zlib ConfigParser mimetools cStringIO sys tempfile")
13 demandload(globals(), "re zlib ConfigParser mimetools cStringIO sys tempfile")
14 demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,streamclone,patch")
14 demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,streamclone,patch")
15 demandload(globals(), "mercurial:templater")
15 demandload(globals(), "mercurial:templater")
16 demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile")
16 demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile")
17 from mercurial.node import *
17 from mercurial.node import *
18 from mercurial.i18n import gettext as _
18 from mercurial.i18n import gettext as _
19
19
20 def _up(p):
20 def _up(p):
21 if p[0] != "/":
21 if p[0] != "/":
22 p = "/" + p
22 p = "/" + p
23 if p[-1] == "/":
23 if p[-1] == "/":
24 p = p[:-1]
24 p = p[:-1]
25 up = os.path.dirname(p)
25 up = os.path.dirname(p)
26 if up == "/":
26 if up == "/":
27 return "/"
27 return "/"
28 return up + "/"
28 return up + "/"
29
29
30 class hgweb(object):
30 class hgweb(object):
31 def __init__(self, repo, name=None):
31 def __init__(self, repo, name=None):
32 if type(repo) == type(""):
32 if type(repo) == type(""):
33 self.repo = hg.repository(ui.ui(), repo)
33 self.repo = hg.repository(ui.ui(), repo)
34 else:
34 else:
35 self.repo = repo
35 self.repo = repo
36
36
37 self.mtime = -1
37 self.mtime = -1
38 self.reponame = name
38 self.reponame = name
39 self.archives = 'zip', 'gz', 'bz2'
39 self.archives = 'zip', 'gz', 'bz2'
40 self.stripecount = 1
40 self.stripecount = 1
41 self.templatepath = self.repo.ui.config("web", "templates",
41 self.templatepath = self.repo.ui.config("web", "templates",
42 templater.templatepath())
42 templater.templatepath())
43
43
44 def refresh(self):
44 def refresh(self):
45 mtime = get_mtime(self.repo.root)
45 mtime = get_mtime(self.repo.root)
46 if mtime != self.mtime:
46 if mtime != self.mtime:
47 self.mtime = mtime
47 self.mtime = mtime
48 self.repo = hg.repository(self.repo.ui, self.repo.root)
48 self.repo = hg.repository(self.repo.ui, self.repo.root)
49 self.maxchanges = int(self.repo.ui.config("web", "maxchanges", 10))
49 self.maxchanges = int(self.repo.ui.config("web", "maxchanges", 10))
50 self.stripecount = int(self.repo.ui.config("web", "stripes", 1))
50 self.stripecount = int(self.repo.ui.config("web", "stripes", 1))
51 self.maxshortchanges = int(self.repo.ui.config("web", "maxshortchanges", 60))
51 self.maxshortchanges = int(self.repo.ui.config("web", "maxshortchanges", 60))
52 self.maxfiles = int(self.repo.ui.config("web", "maxfiles", 10))
52 self.maxfiles = int(self.repo.ui.config("web", "maxfiles", 10))
53 self.allowpull = self.repo.ui.configbool("web", "allowpull", True)
53 self.allowpull = self.repo.ui.configbool("web", "allowpull", True)
54
54
55 def archivelist(self, nodeid):
55 def archivelist(self, nodeid):
56 allowed = self.repo.ui.configlist("web", "allow_archive")
56 allowed = self.repo.ui.configlist("web", "allow_archive")
57 for i in self.archives:
57 for i in self.archives:
58 if i in allowed or self.repo.ui.configbool("web", "allow" + i):
58 if i in allowed or self.repo.ui.configbool("web", "allow" + i):
59 yield {"type" : i, "node" : nodeid, "url": ""}
59 yield {"type" : i, "node" : nodeid, "url": ""}
60
60
61 def listfiles(self, files, mf):
61 def listfiles(self, files, mf):
62 for f in files[:self.maxfiles]:
62 for f in files[:self.maxfiles]:
63 yield self.t("filenodelink", node=hex(mf[f]), file=f)
63 yield self.t("filenodelink", node=hex(mf[f]), file=f)
64 if len(files) > self.maxfiles:
64 if len(files) > self.maxfiles:
65 yield self.t("fileellipses")
65 yield self.t("fileellipses")
66
66
67 def listfilediffs(self, files, changeset):
67 def listfilediffs(self, files, changeset):
68 for f in files[:self.maxfiles]:
68 for f in files[:self.maxfiles]:
69 yield self.t("filedifflink", node=hex(changeset), file=f)
69 yield self.t("filedifflink", node=hex(changeset), file=f)
70 if len(files) > self.maxfiles:
70 if len(files) > self.maxfiles:
71 yield self.t("fileellipses")
71 yield self.t("fileellipses")
72
72
73 def siblings(self, siblings=[], rev=None, hiderev=None, **args):
73 def siblings(self, siblings=[], rev=None, hiderev=None, **args):
74 if not rev:
74 if not rev:
75 rev = lambda x: ""
75 rev = lambda x: ""
76 siblings = [s for s in siblings if s != nullid]
76 siblings = [s for s in siblings if s != nullid]
77 if len(siblings) == 1 and rev(siblings[0]) == hiderev:
77 if len(siblings) == 1 and rev(siblings[0]) == hiderev:
78 return
78 return
79 for s in siblings:
79 for s in siblings:
80 yield dict(node=hex(s), rev=rev(s), **args)
80 yield dict(node=hex(s), rev=rev(s), **args)
81
81
82 def renamelink(self, fl, node):
82 def renamelink(self, fl, node):
83 r = fl.renamed(node)
83 r = fl.renamed(node)
84 if r:
84 if r:
85 return [dict(file=r[0], node=hex(r[1]))]
85 return [dict(file=r[0], node=hex(r[1]))]
86 return []
86 return []
87
87
88 def showtag(self, t1, node=nullid, **args):
88 def showtag(self, t1, node=nullid, **args):
89 for t in self.repo.nodetags(node):
89 for t in self.repo.nodetags(node):
90 yield self.t(t1, tag=t, **args)
90 yield self.t(t1, tag=t, **args)
91
91
92 def diff(self, node1, node2, files):
92 def diff(self, node1, node2, files):
93 def filterfiles(filters, files):
93 def filterfiles(filters, files):
94 l = [x for x in files if x in filters]
94 l = [x for x in files if x in filters]
95
95
96 for t in filters:
96 for t in filters:
97 if t and t[-1] != os.sep:
97 if t and t[-1] != os.sep:
98 t += os.sep
98 t += os.sep
99 l += [x for x in files if x.startswith(t)]
99 l += [x for x in files if x.startswith(t)]
100 return l
100 return l
101
101
102 parity = [0]
102 parity = [0]
103 def diffblock(diff, f, fn):
103 def diffblock(diff, f, fn):
104 yield self.t("diffblock",
104 yield self.t("diffblock",
105 lines=prettyprintlines(diff),
105 lines=prettyprintlines(diff),
106 parity=parity[0],
106 parity=parity[0],
107 file=f,
107 file=f,
108 filenode=hex(fn or nullid))
108 filenode=hex(fn or nullid))
109 parity[0] = 1 - parity[0]
109 parity[0] = 1 - parity[0]
110
110
111 def prettyprintlines(diff):
111 def prettyprintlines(diff):
112 for l in diff.splitlines(1):
112 for l in diff.splitlines(1):
113 if l.startswith('+'):
113 if l.startswith('+'):
114 yield self.t("difflineplus", line=l)
114 yield self.t("difflineplus", line=l)
115 elif l.startswith('-'):
115 elif l.startswith('-'):
116 yield self.t("difflineminus", line=l)
116 yield self.t("difflineminus", line=l)
117 elif l.startswith('@'):
117 elif l.startswith('@'):
118 yield self.t("difflineat", line=l)
118 yield self.t("difflineat", line=l)
119 else:
119 else:
120 yield self.t("diffline", line=l)
120 yield self.t("diffline", line=l)
121
121
122 r = self.repo
122 r = self.repo
123 cl = r.changelog
123 cl = r.changelog
124 mf = r.manifest
124 mf = r.manifest
125 change1 = cl.read(node1)
125 change1 = cl.read(node1)
126 change2 = cl.read(node2)
126 change2 = cl.read(node2)
127 mmap1 = mf.read(change1[0])
127 mmap1 = mf.read(change1[0])
128 mmap2 = mf.read(change2[0])
128 mmap2 = mf.read(change2[0])
129 date1 = util.datestr(change1[2])
129 date1 = util.datestr(change1[2])
130 date2 = util.datestr(change2[2])
130 date2 = util.datestr(change2[2])
131
131
132 modified, added, removed, deleted, unknown = r.status(node1, node2)[:5]
132 modified, added, removed, deleted, unknown = r.status(node1, node2)[:5]
133 if files:
133 if files:
134 modified, added, removed = map(lambda x: filterfiles(files, x),
134 modified, added, removed = map(lambda x: filterfiles(files, x),
135 (modified, added, removed))
135 (modified, added, removed))
136
136
137 diffopts = patch.diffopts(self.repo.ui)
137 diffopts = patch.diffopts(self.repo.ui)
138 for f in modified:
138 for f in modified:
139 to = r.file(f).read(mmap1[f])
139 to = r.file(f).read(mmap1[f])
140 tn = r.file(f).read(mmap2[f])
140 tn = r.file(f).read(mmap2[f])
141 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
141 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
142 opts=diffopts), f, tn)
142 opts=diffopts), f, tn)
143 for f in added:
143 for f in added:
144 to = None
144 to = None
145 tn = r.file(f).read(mmap2[f])
145 tn = r.file(f).read(mmap2[f])
146 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
146 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
147 opts=diffopts), f, tn)
147 opts=diffopts), f, tn)
148 for f in removed:
148 for f in removed:
149 to = r.file(f).read(mmap1[f])
149 to = r.file(f).read(mmap1[f])
150 tn = None
150 tn = None
151 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
151 yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
152 opts=diffopts), f, tn)
152 opts=diffopts), f, tn)
153
153
154 def changelog(self, pos, shortlog=False):
154 def changelog(self, pos, shortlog=False):
155 def changenav(**map):
155 def changenav(**map):
156 def seq(factor, maxchanges=None):
156 def seq(factor, maxchanges=None):
157 if maxchanges:
157 if maxchanges:
158 yield maxchanges
158 yield maxchanges
159 if maxchanges >= 20 and maxchanges <= 40:
159 if maxchanges >= 20 and maxchanges <= 40:
160 yield 50
160 yield 50
161 else:
161 else:
162 yield 1 * factor
162 yield 1 * factor
163 yield 3 * factor
163 yield 3 * factor
164 for f in seq(factor * 10):
164 for f in seq(factor * 10):
165 yield f
165 yield f
166
166
167 l = []
167 l = []
168 last = 0
168 last = 0
169 maxchanges = shortlog and self.maxshortchanges or self.maxchanges
169 maxchanges = shortlog and self.maxshortchanges or self.maxchanges
170 for f in seq(1, maxchanges):
170 for f in seq(1, maxchanges):
171 if f < maxchanges or f <= last:
171 if f < maxchanges or f <= last:
172 continue
172 continue
173 if f > count:
173 if f > count:
174 break
174 break
175 last = f
175 last = f
176 r = "%d" % f
176 r = "%d" % f
177 if pos + f < count:
177 if pos + f < count:
178 l.append(("+" + r, pos + f))
178 l.append(("+" + r, pos + f))
179 if pos - f >= 0:
179 if pos - f >= 0:
180 l.insert(0, ("-" + r, pos - f))
180 l.insert(0, ("-" + r, pos - f))
181
181
182 yield {"rev": 0, "label": "(0)"}
182 yield {"rev": 0, "label": "(0)"}
183
183
184 for label, rev in l:
184 for label, rev in l:
185 yield {"label": label, "rev": rev}
185 yield {"label": label, "rev": rev}
186
186
187 yield {"label": "tip", "rev": "tip"}
187 yield {"label": "tip", "rev": "tip"}
188
188
189 def changelist(**map):
189 def changelist(**map):
190 parity = (start - end) & 1
190 parity = (start - end) & 1
191 cl = self.repo.changelog
191 cl = self.repo.changelog
192 l = [] # build a list in forward order for efficiency
192 l = [] # build a list in forward order for efficiency
193 for i in range(start, end):
193 for i in range(start, end):
194 n = cl.node(i)
194 n = cl.node(i)
195 changes = cl.read(n)
195 changes = cl.read(n)
196 hn = hex(n)
196 hn = hex(n)
197
197
198 l.insert(0, {"parity": parity,
198 l.insert(0, {"parity": parity,
199 "author": changes[1],
199 "author": changes[1],
200 "parent": self.siblings(cl.parents(n), cl.rev,
200 "parent": self.siblings(cl.parents(n), cl.rev,
201 cl.rev(n) - 1),
201 cl.rev(n) - 1),
202 "child": self.siblings(cl.children(n), cl.rev,
202 "child": self.siblings(cl.children(n), cl.rev,
203 cl.rev(n) + 1),
203 cl.rev(n) + 1),
204 "changelogtag": self.showtag("changelogtag",n),
204 "changelogtag": self.showtag("changelogtag",n),
205 "desc": changes[4],
205 "desc": changes[4],
206 "date": changes[2],
206 "date": changes[2],
207 "files": self.listfilediffs(changes[3], n),
207 "files": self.listfilediffs(changes[3], n),
208 "rev": i,
208 "rev": i,
209 "node": hn})
209 "node": hn})
210 parity = 1 - parity
210 parity = 1 - parity
211
211
212 for e in l:
212 for e in l:
213 yield e
213 yield e
214
214
215 maxchanges = shortlog and self.maxshortchanges or self.maxchanges
215 maxchanges = shortlog and self.maxshortchanges or self.maxchanges
216 cl = self.repo.changelog
216 cl = self.repo.changelog
217 mf = cl.read(cl.tip())[0]
217 mf = cl.read(cl.tip())[0]
218 count = cl.count()
218 count = cl.count()
219 start = max(0, pos - maxchanges + 1)
219 start = max(0, pos - maxchanges + 1)
220 end = min(count, start + maxchanges)
220 end = min(count, start + maxchanges)
221 pos = end - 1
221 pos = end - 1
222
222
223 yield self.t(shortlog and 'shortlog' or 'changelog',
223 yield self.t(shortlog and 'shortlog' or 'changelog',
224 changenav=changenav,
224 changenav=changenav,
225 node=hex(cl.tip()),
225 node=hex(cl.tip()),
226 rev=pos, changesets=count, entries=changelist,
226 rev=pos, changesets=count, entries=changelist,
227 archives=self.archivelist("tip"))
227 archives=self.archivelist("tip"))
228
228
229 def search(self, query):
229 def search(self, query):
230
230
231 def changelist(**map):
231 def changelist(**map):
232 cl = self.repo.changelog
232 cl = self.repo.changelog
233 count = 0
233 count = 0
234 qw = query.lower().split()
234 qw = query.lower().split()
235
235
236 def revgen():
236 def revgen():
237 for i in range(cl.count() - 1, 0, -100):
237 for i in range(cl.count() - 1, 0, -100):
238 l = []
238 l = []
239 for j in range(max(0, i - 100), i):
239 for j in range(max(0, i - 100), i):
240 n = cl.node(j)
240 n = cl.node(j)
241 changes = cl.read(n)
241 changes = cl.read(n)
242 l.append((n, j, changes))
242 l.append((n, j, changes))
243 l.reverse()
243 l.reverse()
244 for e in l:
244 for e in l:
245 yield e
245 yield e
246
246
247 for n, i, changes in revgen():
247 for n, i, changes in revgen():
248 miss = 0
248 miss = 0
249 for q in qw:
249 for q in qw:
250 if not (q in changes[1].lower() or
250 if not (q in changes[1].lower() or
251 q in changes[4].lower() or
251 q in changes[4].lower() or
252 q in " ".join(changes[3][:20]).lower()):
252 q in " ".join(changes[3][:20]).lower()):
253 miss = 1
253 miss = 1
254 break
254 break
255 if miss:
255 if miss:
256 continue
256 continue
257
257
258 count += 1
258 count += 1
259 hn = hex(n)
259 hn = hex(n)
260
260
261 yield self.t('searchentry',
261 yield self.t('searchentry',
262 parity=self.stripes(count),
262 parity=self.stripes(count),
263 author=changes[1],
263 author=changes[1],
264 parent=self.siblings(cl.parents(n), cl.rev),
264 parent=self.siblings(cl.parents(n), cl.rev),
265 child=self.siblings(cl.children(n), cl.rev),
265 child=self.siblings(cl.children(n), cl.rev),
266 changelogtag=self.showtag("changelogtag",n),
266 changelogtag=self.showtag("changelogtag",n),
267 desc=changes[4],
267 desc=changes[4],
268 date=changes[2],
268 date=changes[2],
269 files=self.listfilediffs(changes[3], n),
269 files=self.listfilediffs(changes[3], n),
270 rev=i,
270 rev=i,
271 node=hn)
271 node=hn)
272
272
273 if count >= self.maxchanges:
273 if count >= self.maxchanges:
274 break
274 break
275
275
276 cl = self.repo.changelog
276 cl = self.repo.changelog
277 mf = cl.read(cl.tip())[0]
277 mf = cl.read(cl.tip())[0]
278
278
279 yield self.t('search',
279 yield self.t('search',
280 query=query,
280 query=query,
281 node=hex(cl.tip()),
281 node=hex(cl.tip()),
282 entries=changelist)
282 entries=changelist)
283
283
284 def changeset(self, nodeid):
284 def changeset(self, nodeid):
285 cl = self.repo.changelog
285 cl = self.repo.changelog
286 n = self.repo.lookup(nodeid)
286 n = self.repo.lookup(nodeid)
287 nodeid = hex(n)
287 nodeid = hex(n)
288 changes = cl.read(n)
288 changes = cl.read(n)
289 p1 = cl.parents(n)[0]
289 p1 = cl.parents(n)[0]
290
290
291 files = []
291 files = []
292 mf = self.repo.manifest.read(changes[0])
292 mf = self.repo.manifest.read(changes[0])
293 parity = 0
293 parity = 0
294 for f in changes[3]:
294 for f in changes[3]:
295 files.append(self.t("filenodelink",
295 files.append(self.t("filenodelink",
296 filenode=hex(mf.get(f, nullid)), file=f,
296 node=hex(n), file=f,
297 parity=parity))
297 parity=parity))
298 parity = 1 - parity
298 parity = 1 - parity
299
299
300 def diff(**map):
300 def diff(**map):
301 yield self.diff(p1, n, None)
301 yield self.diff(p1, n, None)
302
302
303 yield self.t('changeset',
303 yield self.t('changeset',
304 diff=diff,
304 diff=diff,
305 rev=cl.rev(n),
305 rev=cl.rev(n),
306 node=nodeid,
306 node=nodeid,
307 parent=self.siblings(cl.parents(n), cl.rev),
307 parent=self.siblings(cl.parents(n), cl.rev),
308 child=self.siblings(cl.children(n), cl.rev),
308 child=self.siblings(cl.children(n), cl.rev),
309 changesettag=self.showtag("changesettag",n),
309 changesettag=self.showtag("changesettag",n),
310 author=changes[1],
310 author=changes[1],
311 desc=changes[4],
311 desc=changes[4],
312 date=changes[2],
312 date=changes[2],
313 files=files,
313 files=files,
314 archives=self.archivelist(nodeid))
314 archives=self.archivelist(nodeid))
315
315
316 def filelog(self, f, filenode):
316 def filelog(self, fctx):
317 f = fctx.path()
317 cl = self.repo.changelog
318 cl = self.repo.changelog
318 fl = self.repo.file(f)
319 fl = fctx.filelog()
319 filenode = hex(fl.lookup(filenode))
320 count = fl.count()
320 count = fl.count()
321
321
322 def entries(**map):
322 def entries(**map):
323 l = []
323 l = []
324 parity = (count - 1) & 1
324 parity = (count - 1) & 1
325
325
326 for i in range(count):
326 for i in range(count):
327 n = fl.node(i)
327 n = fl.node(i)
328 lr = fl.linkrev(n)
328 lr = fl.linkrev(n)
329 cn = cl.node(lr)
329 ctx = self.repo.changectx(lr)
330 cs = cl.read(cl.node(lr))
331
330
332 l.insert(0, {"parity": parity,
331 l.insert(0, {"parity": parity,
333 "filenode": hex(n),
334 "filerev": i,
332 "filerev": i,
335 "file": f,
333 "file": f,
336 "node": hex(cn),
334 "node": hex(ctx.node()),
337 "author": cs[1],
335 "author": ctx.user(),
338 "date": cs[2],
336 "date": ctx.date(),
339 "rename": self.renamelink(fl, n),
337 "rename": self.renamelink(fl, n),
340 "parent": self.siblings(fl.parents(n),
338 "parent": self.siblings(fl.parents(n),
341 fl.rev, file=f),
339 fl.rev, file=f),
342 "child": self.siblings(fl.children(n),
340 "child": self.siblings(fl.children(n),
343 fl.rev, file=f),
341 fl.rev, file=f),
344 "desc": cs[4]})
342 "desc": ctx.description()})
345 parity = 1 - parity
343 parity = 1 - parity
346
344
347 for e in l:
345 for e in l:
348 yield e
346 yield e
349
347
350 yield self.t("filelog", file=f, filenode=filenode, entries=entries)
348 yield self.t("filelog", file=f, node=hex(fctx.node()), entries=entries)
351
349
352 def filerevision(self, f, node):
350 def filerevision(self, fctx):
353 fl = self.repo.file(f)
351 f = fctx.path()
354 n = fl.lookup(node)
352 text = fctx.data()
355 node = hex(n)
353 fl = fctx.filelog()
356 text = fl.read(n)
354 n = fctx.filenode()
357 changerev = fl.linkrev(n)
358 cl = self.repo.changelog
359 cn = cl.node(changerev)
360 cs = cl.read(cn)
361 mfn = cs[0]
362
355
363 mt = mimetypes.guess_type(f)[0]
356 mt = mimetypes.guess_type(f)[0]
364 rawtext = text
357 rawtext = text
365 if util.binary(text):
358 if util.binary(text):
366 mt = mt or 'application/octet-stream'
359 mt = mt or 'application/octet-stream'
367 text = "(binary:%s)" % mt
360 text = "(binary:%s)" % mt
368 mt = mt or 'text/plain'
361 mt = mt or 'text/plain'
369
362
370 def lines():
363 def lines():
371 for l, t in enumerate(text.splitlines(1)):
364 for l, t in enumerate(text.splitlines(1)):
372 yield {"line": t,
365 yield {"line": t,
373 "linenumber": "% 6d" % (l + 1),
366 "linenumber": "% 6d" % (l + 1),
374 "parity": self.stripes(l)}
367 "parity": self.stripes(l)}
375
368
376 yield self.t("filerevision",
369 yield self.t("filerevision",
377 file=f,
370 file=f,
378 filenode=node,
379 path=_up(f),
371 path=_up(f),
380 text=lines(),
372 text=lines(),
381 raw=rawtext,
373 raw=rawtext,
382 mimetype=mt,
374 mimetype=mt,
383 rev=changerev,
375 rev=fctx.rev(),
384 node=hex(cn),
376 node=hex(fctx.node()),
385 author=cs[1],
377 author=fctx.user(),
386 date=cs[2],
378 date=fctx.date(),
387 parent=self.siblings(fl.parents(n), fl.rev, file=f),
379 parent=self.siblings(fl.parents(n), fl.rev, file=f),
388 child=self.siblings(fl.children(n), fl.rev, file=f),
380 child=self.siblings(fl.children(n), fl.rev, file=f),
389 rename=self.renamelink(fl, n),
381 rename=self.renamelink(fl, n),
390 permissions=self.repo.manifest.read(mfn).execf(f))
382 permissions=fctx.manifest().execf(f))
391
383
392 def fileannotate(self, f, node):
384 def fileannotate(self, fctx):
393 fctx = self.repo.filectx(f, fileid=node)
385 f = fctx.path()
394 n = fctx.filenode()
386 n = fctx.filenode()
395 fl = fctx.filelog()
387 fl = fctx.filelog()
396
388
397 def annotate(**map):
389 def annotate(**map):
398 parity = 0
390 parity = 0
399 last = None
391 last = None
400 for f, l in fctx.annotate(follow=True):
392 for f, l in fctx.annotate(follow=True):
401 fnode = f.filenode()
393 fnode = f.filenode()
402 name = self.repo.ui.shortuser(f.user())
394 name = self.repo.ui.shortuser(f.user())
403
395
404 if last != fnode:
396 if last != fnode:
405 parity = 1 - parity
397 parity = 1 - parity
406 last = fnode
398 last = fnode
407
399
408 yield {"parity": parity,
400 yield {"parity": parity,
409 "node": hex(f.node()),
401 "node": hex(f.node()),
410 "filenode": hex(fnode),
411 "rev": f.rev(),
402 "rev": f.rev(),
412 "author": name,
403 "author": name,
413 "file": f.path(),
404 "file": f.path(),
414 "line": l}
405 "line": l}
415
406
416 yield self.t("fileannotate",
407 yield self.t("fileannotate",
417 file=f,
408 file=f,
418 filenode=node,
419 annotate=annotate,
409 annotate=annotate,
420 path=_up(f),
410 path=_up(f),
421 rev=fctx.rev(),
411 rev=fctx.rev(),
422 node=hex(fctx.node()),
412 node=hex(fctx.node()),
423 author=fctx.user(),
413 author=fctx.user(),
424 date=fctx.date(),
414 date=fctx.date(),
425 rename=self.renamelink(fl, n),
415 rename=self.renamelink(fl, n),
426 parent=self.siblings(fl.parents(n), fl.rev, file=f),
416 parent=self.siblings(fl.parents(n), fl.rev, file=f),
427 child=self.siblings(fl.children(n), fl.rev, file=f),
417 child=self.siblings(fl.children(n), fl.rev, file=f),
428 permissions=fctx.manifest().execf(f))
418 permissions=fctx.manifest().execf(f))
429
419
430 def manifest(self, ctx, path):
420 def manifest(self, ctx, path):
431 mf = ctx.manifest()
421 mf = ctx.manifest()
432 node = ctx.node()
422 node = ctx.node()
433
423
434 files = {}
424 files = {}
435
425
436 p = path[1:]
426 p = path[1:]
437 if p and p[-1] != "/":
427 if p and p[-1] != "/":
438 p += "/"
428 p += "/"
439 l = len(p)
429 l = len(p)
440
430
441 for f,n in mf.items():
431 for f,n in mf.items():
442 if f[:l] != p:
432 if f[:l] != p:
443 continue
433 continue
444 remain = f[l:]
434 remain = f[l:]
445 if "/" in remain:
435 if "/" in remain:
446 short = remain[:remain.index("/") + 1] # bleah
436 short = remain[:remain.index("/") + 1] # bleah
447 files[short] = (f, None)
437 files[short] = (f, None)
448 else:
438 else:
449 short = os.path.basename(remain)
439 short = os.path.basename(remain)
450 files[short] = (f, n)
440 files[short] = (f, n)
451
441
452 def filelist(**map):
442 def filelist(**map):
453 parity = 0
443 parity = 0
454 fl = files.keys()
444 fl = files.keys()
455 fl.sort()
445 fl.sort()
456 for f in fl:
446 for f in fl:
457 full, fnode = files[f]
447 full, fnode = files[f]
458 if not fnode:
448 if not fnode:
459 continue
449 continue
460
450
461 yield {"file": full,
451 yield {"file": full,
462 "filenode": hex(fnode),
452 "filenode": hex(fnode),
463 "parity": self.stripes(parity),
453 "parity": self.stripes(parity),
464 "basename": f,
454 "basename": f,
465 "permissions": mf.execf(full)}
455 "permissions": mf.execf(full)}
466 parity += 1
456 parity += 1
467
457
468 def dirlist(**map):
458 def dirlist(**map):
469 parity = 0
459 parity = 0
470 fl = files.keys()
460 fl = files.keys()
471 fl.sort()
461 fl.sort()
472 for f in fl:
462 for f in fl:
473 full, fnode = files[f]
463 full, fnode = files[f]
474 if fnode:
464 if fnode:
475 continue
465 continue
476
466
477 yield {"parity": self.stripes(parity),
467 yield {"parity": self.stripes(parity),
478 "path": os.path.join(path, f),
468 "path": os.path.join(path, f),
479 "basename": f[:-1]}
469 "basename": f[:-1]}
480 parity += 1
470 parity += 1
481
471
482 yield self.t("manifest",
472 yield self.t("manifest",
483 rev=ctx.rev(),
473 rev=ctx.rev(),
484 node=hex(node),
474 node=hex(node),
485 path=path,
475 path=path,
486 up=_up(path),
476 up=_up(path),
487 fentries=filelist,
477 fentries=filelist,
488 dentries=dirlist,
478 dentries=dirlist,
489 archives=self.archivelist(hex(node)))
479 archives=self.archivelist(hex(node)))
490
480
491 def tags(self):
481 def tags(self):
492 cl = self.repo.changelog
482 cl = self.repo.changelog
493
483
494 i = self.repo.tagslist()
484 i = self.repo.tagslist()
495 i.reverse()
485 i.reverse()
496
486
497 def entries(notip=False, **map):
487 def entries(notip=False, **map):
498 parity = 0
488 parity = 0
499 for k,n in i:
489 for k,n in i:
500 if notip and k == "tip": continue
490 if notip and k == "tip": continue
501 yield {"parity": self.stripes(parity),
491 yield {"parity": self.stripes(parity),
502 "tag": k,
492 "tag": k,
503 "date": cl.read(n)[2],
493 "date": cl.read(n)[2],
504 "node": hex(n)}
494 "node": hex(n)}
505 parity += 1
495 parity += 1
506
496
507 yield self.t("tags",
497 yield self.t("tags",
508 node=hex(self.repo.changelog.tip()),
498 node=hex(self.repo.changelog.tip()),
509 entries=lambda **x: entries(False, **x),
499 entries=lambda **x: entries(False, **x),
510 entriesnotip=lambda **x: entries(True, **x))
500 entriesnotip=lambda **x: entries(True, **x))
511
501
512 def summary(self):
502 def summary(self):
513 cl = self.repo.changelog
503 cl = self.repo.changelog
514
504
515 i = self.repo.tagslist()
505 i = self.repo.tagslist()
516 i.reverse()
506 i.reverse()
517
507
518 def tagentries(**map):
508 def tagentries(**map):
519 parity = 0
509 parity = 0
520 count = 0
510 count = 0
521 for k,n in i:
511 for k,n in i:
522 if k == "tip": # skip tip
512 if k == "tip": # skip tip
523 continue;
513 continue;
524
514
525 count += 1
515 count += 1
526 if count > 10: # limit to 10 tags
516 if count > 10: # limit to 10 tags
527 break;
517 break;
528
518
529 c = cl.read(n)
519 c = cl.read(n)
530 m = c[0]
520 m = c[0]
531 t = c[2]
521 t = c[2]
532
522
533 yield self.t("tagentry",
523 yield self.t("tagentry",
534 parity = self.stripes(parity),
524 parity = self.stripes(parity),
535 tag = k,
525 tag = k,
536 node = hex(n),
526 node = hex(n),
537 date = t)
527 date = t)
538 parity += 1
528 parity += 1
539
529
540 def changelist(**map):
530 def changelist(**map):
541 parity = 0
531 parity = 0
542 cl = self.repo.changelog
532 cl = self.repo.changelog
543 l = [] # build a list in forward order for efficiency
533 l = [] # build a list in forward order for efficiency
544 for i in range(start, end):
534 for i in range(start, end):
545 n = cl.node(i)
535 n = cl.node(i)
546 changes = cl.read(n)
536 changes = cl.read(n)
547 hn = hex(n)
537 hn = hex(n)
548 t = changes[2]
538 t = changes[2]
549
539
550 l.insert(0, self.t(
540 l.insert(0, self.t(
551 'shortlogentry',
541 'shortlogentry',
552 parity = parity,
542 parity = parity,
553 author = changes[1],
543 author = changes[1],
554 desc = changes[4],
544 desc = changes[4],
555 date = t,
545 date = t,
556 rev = i,
546 rev = i,
557 node = hn))
547 node = hn))
558 parity = 1 - parity
548 parity = 1 - parity
559
549
560 yield l
550 yield l
561
551
562 count = cl.count()
552 count = cl.count()
563 start = max(0, count - self.maxchanges)
553 start = max(0, count - self.maxchanges)
564 end = min(count, start + self.maxchanges)
554 end = min(count, start + self.maxchanges)
565
555
566 yield self.t("summary",
556 yield self.t("summary",
567 desc = self.repo.ui.config("web", "description", "unknown"),
557 desc = self.repo.ui.config("web", "description", "unknown"),
568 owner = (self.repo.ui.config("ui", "username") or # preferred
558 owner = (self.repo.ui.config("ui", "username") or # preferred
569 self.repo.ui.config("web", "contact") or # deprecated
559 self.repo.ui.config("web", "contact") or # deprecated
570 self.repo.ui.config("web", "author", "unknown")), # also
560 self.repo.ui.config("web", "author", "unknown")), # also
571 lastchange = (0, 0), # FIXME
561 lastchange = (0, 0), # FIXME
572 tags = tagentries,
562 tags = tagentries,
573 shortlog = changelist,
563 shortlog = changelist,
574 node = hex(self.repo.changelog.tip()),
564 node = hex(self.repo.changelog.tip()),
575 archives=self.archivelist("tip"))
565 archives=self.archivelist("tip"))
576
566
577 def filediff(self, file, changeset):
567 def filediff(self, file, changeset):
578 cl = self.repo.changelog
568 cl = self.repo.changelog
579 n = self.repo.lookup(changeset)
569 n = self.repo.lookup(changeset)
580 changeset = hex(n)
570 changeset = hex(n)
581 p1 = cl.parents(n)[0]
571 p1 = cl.parents(n)[0]
582 cs = cl.read(n)
572 cs = cl.read(n)
583 mf = self.repo.manifest.read(cs[0])
573 mf = self.repo.manifest.read(cs[0])
584
574
585 def diff(**map):
575 def diff(**map):
586 yield self.diff(p1, n, [file])
576 yield self.diff(p1, n, [file])
587
577
588 yield self.t("filediff",
578 yield self.t("filediff",
589 file=file,
579 file=file,
590 filenode=hex(mf.get(file, nullid)),
580 filenode=hex(mf.get(file, nullid)),
591 node=changeset,
581 node=changeset,
592 rev=self.repo.changelog.rev(n),
582 rev=self.repo.changelog.rev(n),
593 parent=self.siblings(cl.parents(n), cl.rev),
583 parent=self.siblings(cl.parents(n), cl.rev),
594 child=self.siblings(cl.children(n), cl.rev),
584 child=self.siblings(cl.children(n), cl.rev),
595 diff=diff)
585 diff=diff)
596
586
597 archive_specs = {
587 archive_specs = {
598 'bz2': ('application/x-tar', 'tbz2', '.tar.bz2', None),
588 'bz2': ('application/x-tar', 'tbz2', '.tar.bz2', None),
599 'gz': ('application/x-tar', 'tgz', '.tar.gz', None),
589 'gz': ('application/x-tar', 'tgz', '.tar.gz', None),
600 'zip': ('application/zip', 'zip', '.zip', None),
590 'zip': ('application/zip', 'zip', '.zip', None),
601 }
591 }
602
592
603 def archive(self, req, cnode, type_):
593 def archive(self, req, cnode, type_):
604 reponame = re.sub(r"\W+", "-", os.path.basename(self.reponame))
594 reponame = re.sub(r"\W+", "-", os.path.basename(self.reponame))
605 name = "%s-%s" % (reponame, short(cnode))
595 name = "%s-%s" % (reponame, short(cnode))
606 mimetype, artype, extension, encoding = self.archive_specs[type_]
596 mimetype, artype, extension, encoding = self.archive_specs[type_]
607 headers = [('Content-type', mimetype),
597 headers = [('Content-type', mimetype),
608 ('Content-disposition', 'attachment; filename=%s%s' %
598 ('Content-disposition', 'attachment; filename=%s%s' %
609 (name, extension))]
599 (name, extension))]
610 if encoding:
600 if encoding:
611 headers.append(('Content-encoding', encoding))
601 headers.append(('Content-encoding', encoding))
612 req.header(headers)
602 req.header(headers)
613 archival.archive(self.repo, req.out, cnode, artype, prefix=name)
603 archival.archive(self.repo, req.out, cnode, artype, prefix=name)
614
604
615 # add tags to things
605 # add tags to things
616 # tags -> list of changesets corresponding to tags
606 # tags -> list of changesets corresponding to tags
617 # find tag, changeset, file
607 # find tag, changeset, file
618
608
619 def cleanpath(self, path):
609 def cleanpath(self, path):
620 p = util.normpath(path)
610 p = util.normpath(path)
621 if p[:2] == "..":
611 if p[:2] == "..":
622 raise Exception("suspicious path")
612 raise Exception("suspicious path")
623 return p
613 return p
624
614
625 def run(self):
615 def run(self):
626 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
616 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
627 raise RuntimeError("This function is only intended to be called while running as a CGI script.")
617 raise RuntimeError("This function is only intended to be called while running as a CGI script.")
628 import mercurial.hgweb.wsgicgi as wsgicgi
618 import mercurial.hgweb.wsgicgi as wsgicgi
629 from request import wsgiapplication
619 from request import wsgiapplication
630 def make_web_app():
620 def make_web_app():
631 return self
621 return self
632 wsgicgi.launch(wsgiapplication(make_web_app))
622 wsgicgi.launch(wsgiapplication(make_web_app))
633
623
634 def run_wsgi(self, req):
624 def run_wsgi(self, req):
635 def header(**map):
625 def header(**map):
636 header_file = cStringIO.StringIO(''.join(self.t("header", **map)))
626 header_file = cStringIO.StringIO(''.join(self.t("header", **map)))
637 msg = mimetools.Message(header_file, 0)
627 msg = mimetools.Message(header_file, 0)
638 req.header(msg.items())
628 req.header(msg.items())
639 yield header_file.read()
629 yield header_file.read()
640
630
641 def rawfileheader(**map):
631 def rawfileheader(**map):
642 req.header([('Content-type', map['mimetype']),
632 req.header([('Content-type', map['mimetype']),
643 ('Content-disposition', 'filename=%s' % map['file']),
633 ('Content-disposition', 'filename=%s' % map['file']),
644 ('Content-length', str(len(map['raw'])))])
634 ('Content-length', str(len(map['raw'])))])
645 yield ''
635 yield ''
646
636
647 def footer(**map):
637 def footer(**map):
648 yield self.t("footer",
638 yield self.t("footer",
649 motd=self.repo.ui.config("web", "motd", ""),
639 motd=self.repo.ui.config("web", "motd", ""),
650 **map)
640 **map)
651
641
652 def expand_form(form):
642 def expand_form(form):
653 shortcuts = {
643 shortcuts = {
654 'cl': [('cmd', ['changelog']), ('rev', None)],
644 'cl': [('cmd', ['changelog']), ('rev', None)],
655 'sl': [('cmd', ['shortlog']), ('rev', None)],
645 'sl': [('cmd', ['shortlog']), ('rev', None)],
656 'cs': [('cmd', ['changeset']), ('node', None)],
646 'cs': [('cmd', ['changeset']), ('node', None)],
657 'f': [('cmd', ['file']), ('filenode', None)],
647 'f': [('cmd', ['file']), ('filenode', None)],
658 'fl': [('cmd', ['filelog']), ('filenode', None)],
648 'fl': [('cmd', ['filelog']), ('filenode', None)],
659 'fd': [('cmd', ['filediff']), ('node', None)],
649 'fd': [('cmd', ['filediff']), ('node', None)],
660 'fa': [('cmd', ['annotate']), ('filenode', None)],
650 'fa': [('cmd', ['annotate']), ('filenode', None)],
661 'mf': [('cmd', ['manifest']), ('manifest', None)],
651 'mf': [('cmd', ['manifest']), ('manifest', None)],
662 'ca': [('cmd', ['archive']), ('node', None)],
652 'ca': [('cmd', ['archive']), ('node', None)],
663 'tags': [('cmd', ['tags'])],
653 'tags': [('cmd', ['tags'])],
664 'tip': [('cmd', ['changeset']), ('node', ['tip'])],
654 'tip': [('cmd', ['changeset']), ('node', ['tip'])],
665 'static': [('cmd', ['static']), ('file', None)]
655 'static': [('cmd', ['static']), ('file', None)]
666 }
656 }
667
657
668 for k in shortcuts.iterkeys():
658 for k in shortcuts.iterkeys():
669 if form.has_key(k):
659 if form.has_key(k):
670 for name, value in shortcuts[k]:
660 for name, value in shortcuts[k]:
671 if value is None:
661 if value is None:
672 value = form[k]
662 value = form[k]
673 form[name] = value
663 form[name] = value
674 del form[k]
664 del form[k]
675
665
676 if form.has_key('manifest'):
666 if form.has_key('manifest'):
677 changeid = req.form['manifest'][0]
667 changeid = req.form['manifest'][0]
678 try:
668 try:
679 req.changectx = self.repo.changectx(changeid)
669 req.changectx = self.repo.changectx(changeid)
680 except hg.RepoError:
670 except hg.RepoError:
681 man = self.repo.manifest
671 man = self.repo.manifest
682 mn = man.lookup(changeid)
672 mn = man.lookup(changeid)
683 req.changectx = self.repo.changectx(man.linkrev(mn))
673 req.changectx = self.repo.changectx(man.linkrev(mn))
684
674
675 if form.has_key('filenode'):
676 changeid = req.form['filenode'][0]
677 path = self.cleanpath(req.form['file'][0])
678 try:
679 req.changectx = self.repo.changectx(changeid)
680 req.filectx = req.changectx.filectx(path)
681 except hg.RepoError:
682 req.filectx = self.repo.filectx(path, fileid=changeid)
683 req.changectx = req.filectx.changectx()
684
685 self.refresh()
685 self.refresh()
686
686
687 expand_form(req.form)
687 expand_form(req.form)
688
688
689 m = os.path.join(self.templatepath, "map")
689 m = os.path.join(self.templatepath, "map")
690 style = self.repo.ui.config("web", "style", "")
690 style = self.repo.ui.config("web", "style", "")
691 if req.form.has_key('style'):
691 if req.form.has_key('style'):
692 style = req.form['style'][0]
692 style = req.form['style'][0]
693 if style:
693 if style:
694 b = os.path.basename("map-" + style)
694 b = os.path.basename("map-" + style)
695 p = os.path.join(self.templatepath, b)
695 p = os.path.join(self.templatepath, b)
696 if os.path.isfile(p):
696 if os.path.isfile(p):
697 m = p
697 m = p
698
698
699 port = req.env["SERVER_PORT"]
699 port = req.env["SERVER_PORT"]
700 port = port != "80" and (":" + port) or ""
700 port = port != "80" and (":" + port) or ""
701 uri = req.env["REQUEST_URI"]
701 uri = req.env["REQUEST_URI"]
702 if "?" in uri:
702 if "?" in uri:
703 uri = uri.split("?")[0]
703 uri = uri.split("?")[0]
704 url = "http://%s%s%s" % (req.env["SERVER_NAME"], port, uri)
704 url = "http://%s%s%s" % (req.env["SERVER_NAME"], port, uri)
705 if not self.reponame:
705 if not self.reponame:
706 self.reponame = (self.repo.ui.config("web", "name")
706 self.reponame = (self.repo.ui.config("web", "name")
707 or uri.strip('/') or self.repo.root)
707 or uri.strip('/') or self.repo.root)
708
708
709 self.t = templater.templater(m, templater.common_filters,
709 self.t = templater.templater(m, templater.common_filters,
710 defaults={"url": url,
710 defaults={"url": url,
711 "repo": self.reponame,
711 "repo": self.reponame,
712 "header": header,
712 "header": header,
713 "footer": footer,
713 "footer": footer,
714 "rawfileheader": rawfileheader,
714 "rawfileheader": rawfileheader,
715 })
715 })
716
716
717 if not req.form.has_key('cmd'):
717 if not req.form.has_key('cmd'):
718 req.form['cmd'] = [self.t.cache['default'],]
718 req.form['cmd'] = [self.t.cache['default'],]
719
719
720 cmd = req.form['cmd'][0]
720 cmd = req.form['cmd'][0]
721
721
722 method = getattr(self, 'do_' + cmd, None)
722 method = getattr(self, 'do_' + cmd, None)
723 if method:
723 if method:
724 method(req)
724 method(req)
725 else:
725 else:
726 req.write(self.t("error"))
726 req.write(self.t("error"))
727
727
728 def stripes(self, parity):
728 def stripes(self, parity):
729 "make horizontal stripes for easier reading"
729 "make horizontal stripes for easier reading"
730 if self.stripecount:
730 if self.stripecount:
731 return (1 + parity / self.stripecount) & 1
731 return (1 + parity / self.stripecount) & 1
732 else:
732 else:
733 return 0
733 return 0
734
734
735 def do_changelog(self, req):
735 def do_changelog(self, req):
736 hi = self.repo.changelog.count() - 1
736 hi = self.repo.changelog.count() - 1
737 if req.form.has_key('rev'):
737 if req.form.has_key('rev'):
738 hi = req.form['rev'][0]
738 hi = req.form['rev'][0]
739 try:
739 try:
740 hi = self.repo.changelog.rev(self.repo.lookup(hi))
740 hi = self.repo.changelog.rev(self.repo.lookup(hi))
741 except hg.RepoError:
741 except hg.RepoError:
742 req.write(self.search(hi)) # XXX redirect to 404 page?
742 req.write(self.search(hi)) # XXX redirect to 404 page?
743 return
743 return
744
744
745 req.write(self.changelog(hi))
745 req.write(self.changelog(hi))
746
746
747 def do_shortlog(self, req):
747 def do_shortlog(self, req):
748 hi = self.repo.changelog.count() - 1
748 hi = self.repo.changelog.count() - 1
749 if req.form.has_key('rev'):
749 if req.form.has_key('rev'):
750 hi = req.form['rev'][0]
750 hi = req.form['rev'][0]
751 try:
751 try:
752 hi = self.repo.changelog.rev(self.repo.lookup(hi))
752 hi = self.repo.changelog.rev(self.repo.lookup(hi))
753 except hg.RepoError:
753 except hg.RepoError:
754 req.write(self.search(hi)) # XXX redirect to 404 page?
754 req.write(self.search(hi)) # XXX redirect to 404 page?
755 return
755 return
756
756
757 req.write(self.changelog(hi, shortlog = True))
757 req.write(self.changelog(hi, shortlog = True))
758
758
759 def do_changeset(self, req):
759 def do_changeset(self, req):
760 req.write(self.changeset(req.form['node'][0]))
760 req.write(self.changeset(req.form['node'][0]))
761
761
762 def do_manifest(self, req):
762 def do_manifest(self, req):
763 req.write(self.manifest(req.changectx,
763 req.write(self.manifest(req.changectx,
764 self.cleanpath(req.form['path'][0])))
764 self.cleanpath(req.form['path'][0])))
765
765
766 def do_tags(self, req):
766 def do_tags(self, req):
767 req.write(self.tags())
767 req.write(self.tags())
768
768
769 def do_summary(self, req):
769 def do_summary(self, req):
770 req.write(self.summary())
770 req.write(self.summary())
771
771
772 def do_filediff(self, req):
772 def do_filediff(self, req):
773 req.write(self.filediff(self.cleanpath(req.form['file'][0]),
773 req.write(self.filediff(self.cleanpath(req.form['file'][0]),
774 req.form['node'][0]))
774 req.form['node'][0]))
775
775
776 def do_file(self, req):
776 def do_file(self, req):
777 req.write(self.filerevision(self.cleanpath(req.form['file'][0]),
777 req.write(self.filerevision(req.filectx))
778 req.form['filenode'][0]))
779
778
780 def do_annotate(self, req):
779 def do_annotate(self, req):
781 req.write(self.fileannotate(self.cleanpath(req.form['file'][0]),
780 req.write(self.fileannotate(req.filectx))
782 req.form['filenode'][0]))
783
781
784 def do_filelog(self, req):
782 def do_filelog(self, req):
785 req.write(self.filelog(self.cleanpath(req.form['file'][0]),
783 req.write(self.filelog(req.filectx))
786 req.form['filenode'][0]))
787
784
788 def do_heads(self, req):
785 def do_heads(self, req):
789 resp = " ".join(map(hex, self.repo.heads())) + "\n"
786 resp = " ".join(map(hex, self.repo.heads())) + "\n"
790 req.httphdr("application/mercurial-0.1", length=len(resp))
787 req.httphdr("application/mercurial-0.1", length=len(resp))
791 req.write(resp)
788 req.write(resp)
792
789
793 def do_branches(self, req):
790 def do_branches(self, req):
794 nodes = []
791 nodes = []
795 if req.form.has_key('nodes'):
792 if req.form.has_key('nodes'):
796 nodes = map(bin, req.form['nodes'][0].split(" "))
793 nodes = map(bin, req.form['nodes'][0].split(" "))
797 resp = cStringIO.StringIO()
794 resp = cStringIO.StringIO()
798 for b in self.repo.branches(nodes):
795 for b in self.repo.branches(nodes):
799 resp.write(" ".join(map(hex, b)) + "\n")
796 resp.write(" ".join(map(hex, b)) + "\n")
800 resp = resp.getvalue()
797 resp = resp.getvalue()
801 req.httphdr("application/mercurial-0.1", length=len(resp))
798 req.httphdr("application/mercurial-0.1", length=len(resp))
802 req.write(resp)
799 req.write(resp)
803
800
804 def do_between(self, req):
801 def do_between(self, req):
805 if req.form.has_key('pairs'):
802 if req.form.has_key('pairs'):
806 pairs = [map(bin, p.split("-"))
803 pairs = [map(bin, p.split("-"))
807 for p in req.form['pairs'][0].split(" ")]
804 for p in req.form['pairs'][0].split(" ")]
808 resp = cStringIO.StringIO()
805 resp = cStringIO.StringIO()
809 for b in self.repo.between(pairs):
806 for b in self.repo.between(pairs):
810 resp.write(" ".join(map(hex, b)) + "\n")
807 resp.write(" ".join(map(hex, b)) + "\n")
811 resp = resp.getvalue()
808 resp = resp.getvalue()
812 req.httphdr("application/mercurial-0.1", length=len(resp))
809 req.httphdr("application/mercurial-0.1", length=len(resp))
813 req.write(resp)
810 req.write(resp)
814
811
815 def do_changegroup(self, req):
812 def do_changegroup(self, req):
816 req.httphdr("application/mercurial-0.1")
813 req.httphdr("application/mercurial-0.1")
817 nodes = []
814 nodes = []
818 if not self.allowpull:
815 if not self.allowpull:
819 return
816 return
820
817
821 if req.form.has_key('roots'):
818 if req.form.has_key('roots'):
822 nodes = map(bin, req.form['roots'][0].split(" "))
819 nodes = map(bin, req.form['roots'][0].split(" "))
823
820
824 z = zlib.compressobj()
821 z = zlib.compressobj()
825 f = self.repo.changegroup(nodes, 'serve')
822 f = self.repo.changegroup(nodes, 'serve')
826 while 1:
823 while 1:
827 chunk = f.read(4096)
824 chunk = f.read(4096)
828 if not chunk:
825 if not chunk:
829 break
826 break
830 req.write(z.compress(chunk))
827 req.write(z.compress(chunk))
831
828
832 req.write(z.flush())
829 req.write(z.flush())
833
830
834 def do_archive(self, req):
831 def do_archive(self, req):
835 changeset = self.repo.lookup(req.form['node'][0])
832 changeset = self.repo.lookup(req.form['node'][0])
836 type_ = req.form['type'][0]
833 type_ = req.form['type'][0]
837 allowed = self.repo.ui.configlist("web", "allow_archive")
834 allowed = self.repo.ui.configlist("web", "allow_archive")
838 if (type_ in self.archives and (type_ in allowed or
835 if (type_ in self.archives and (type_ in allowed or
839 self.repo.ui.configbool("web", "allow" + type_, False))):
836 self.repo.ui.configbool("web", "allow" + type_, False))):
840 self.archive(req, changeset, type_)
837 self.archive(req, changeset, type_)
841 return
838 return
842
839
843 req.write(self.t("error"))
840 req.write(self.t("error"))
844
841
845 def do_static(self, req):
842 def do_static(self, req):
846 fname = req.form['file'][0]
843 fname = req.form['file'][0]
847 static = self.repo.ui.config("web", "static",
844 static = self.repo.ui.config("web", "static",
848 os.path.join(self.templatepath,
845 os.path.join(self.templatepath,
849 "static"))
846 "static"))
850 req.write(staticfile(static, fname, req)
847 req.write(staticfile(static, fname, req)
851 or self.t("error", error="%r not found" % fname))
848 or self.t("error", error="%r not found" % fname))
852
849
853 def do_capabilities(self, req):
850 def do_capabilities(self, req):
854 caps = ['unbundle']
851 caps = ['unbundle']
855 if self.repo.ui.configbool('server', 'uncompressed'):
852 if self.repo.ui.configbool('server', 'uncompressed'):
856 caps.append('stream=%d' % self.repo.revlogversion)
853 caps.append('stream=%d' % self.repo.revlogversion)
857 resp = ' '.join(caps)
854 resp = ' '.join(caps)
858 req.httphdr("application/mercurial-0.1", length=len(resp))
855 req.httphdr("application/mercurial-0.1", length=len(resp))
859 req.write(resp)
856 req.write(resp)
860
857
861 def check_perm(self, req, op, default):
858 def check_perm(self, req, op, default):
862 '''check permission for operation based on user auth.
859 '''check permission for operation based on user auth.
863 return true if op allowed, else false.
860 return true if op allowed, else false.
864 default is policy to use if no config given.'''
861 default is policy to use if no config given.'''
865
862
866 user = req.env.get('REMOTE_USER')
863 user = req.env.get('REMOTE_USER')
867
864
868 deny = self.repo.ui.configlist('web', 'deny_' + op)
865 deny = self.repo.ui.configlist('web', 'deny_' + op)
869 if deny and (not user or deny == ['*'] or user in deny):
866 if deny and (not user or deny == ['*'] or user in deny):
870 return False
867 return False
871
868
872 allow = self.repo.ui.configlist('web', 'allow_' + op)
869 allow = self.repo.ui.configlist('web', 'allow_' + op)
873 return (allow and (allow == ['*'] or user in allow)) or default
870 return (allow and (allow == ['*'] or user in allow)) or default
874
871
875 def do_unbundle(self, req):
872 def do_unbundle(self, req):
876 def bail(response, headers={}):
873 def bail(response, headers={}):
877 length = int(req.env['CONTENT_LENGTH'])
874 length = int(req.env['CONTENT_LENGTH'])
878 for s in util.filechunkiter(req, limit=length):
875 for s in util.filechunkiter(req, limit=length):
879 # drain incoming bundle, else client will not see
876 # drain incoming bundle, else client will not see
880 # response when run outside cgi script
877 # response when run outside cgi script
881 pass
878 pass
882 req.httphdr("application/mercurial-0.1", headers=headers)
879 req.httphdr("application/mercurial-0.1", headers=headers)
883 req.write('0\n')
880 req.write('0\n')
884 req.write(response)
881 req.write(response)
885
882
886 # require ssl by default, auth info cannot be sniffed and
883 # require ssl by default, auth info cannot be sniffed and
887 # replayed
884 # replayed
888 ssl_req = self.repo.ui.configbool('web', 'push_ssl', True)
885 ssl_req = self.repo.ui.configbool('web', 'push_ssl', True)
889 if ssl_req:
886 if ssl_req:
890 if not req.env.get('HTTPS'):
887 if not req.env.get('HTTPS'):
891 bail(_('ssl required\n'))
888 bail(_('ssl required\n'))
892 return
889 return
893 proto = 'https'
890 proto = 'https'
894 else:
891 else:
895 proto = 'http'
892 proto = 'http'
896
893
897 # do not allow push unless explicitly allowed
894 # do not allow push unless explicitly allowed
898 if not self.check_perm(req, 'push', False):
895 if not self.check_perm(req, 'push', False):
899 bail(_('push not authorized\n'),
896 bail(_('push not authorized\n'),
900 headers={'status': '401 Unauthorized'})
897 headers={'status': '401 Unauthorized'})
901 return
898 return
902
899
903 req.httphdr("application/mercurial-0.1")
900 req.httphdr("application/mercurial-0.1")
904
901
905 their_heads = req.form['heads'][0].split(' ')
902 their_heads = req.form['heads'][0].split(' ')
906
903
907 def check_heads():
904 def check_heads():
908 heads = map(hex, self.repo.heads())
905 heads = map(hex, self.repo.heads())
909 return their_heads == [hex('force')] or their_heads == heads
906 return their_heads == [hex('force')] or their_heads == heads
910
907
911 # fail early if possible
908 # fail early if possible
912 if not check_heads():
909 if not check_heads():
913 bail(_('unsynced changes\n'))
910 bail(_('unsynced changes\n'))
914 return
911 return
915
912
916 # do not lock repo until all changegroup data is
913 # do not lock repo until all changegroup data is
917 # streamed. save to temporary file.
914 # streamed. save to temporary file.
918
915
919 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
916 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
920 fp = os.fdopen(fd, 'wb+')
917 fp = os.fdopen(fd, 'wb+')
921 try:
918 try:
922 length = int(req.env['CONTENT_LENGTH'])
919 length = int(req.env['CONTENT_LENGTH'])
923 for s in util.filechunkiter(req, limit=length):
920 for s in util.filechunkiter(req, limit=length):
924 fp.write(s)
921 fp.write(s)
925
922
926 lock = self.repo.lock()
923 lock = self.repo.lock()
927 try:
924 try:
928 if not check_heads():
925 if not check_heads():
929 req.write('0\n')
926 req.write('0\n')
930 req.write(_('unsynced changes\n'))
927 req.write(_('unsynced changes\n'))
931 return
928 return
932
929
933 fp.seek(0)
930 fp.seek(0)
934
931
935 # send addchangegroup output to client
932 # send addchangegroup output to client
936
933
937 old_stdout = sys.stdout
934 old_stdout = sys.stdout
938 sys.stdout = cStringIO.StringIO()
935 sys.stdout = cStringIO.StringIO()
939
936
940 try:
937 try:
941 url = 'remote:%s:%s' % (proto,
938 url = 'remote:%s:%s' % (proto,
942 req.env.get('REMOTE_HOST', ''))
939 req.env.get('REMOTE_HOST', ''))
943 ret = self.repo.addchangegroup(fp, 'serve', url)
940 ret = self.repo.addchangegroup(fp, 'serve', url)
944 finally:
941 finally:
945 val = sys.stdout.getvalue()
942 val = sys.stdout.getvalue()
946 sys.stdout = old_stdout
943 sys.stdout = old_stdout
947 req.write('%d\n' % ret)
944 req.write('%d\n' % ret)
948 req.write(val)
945 req.write(val)
949 finally:
946 finally:
950 lock.release()
947 lock.release()
951 finally:
948 finally:
952 fp.close()
949 fp.close()
953 os.unlink(tempname)
950 os.unlink(tempname)
954
951
955 def do_stream_out(self, req):
952 def do_stream_out(self, req):
956 req.httphdr("application/mercurial-0.1")
953 req.httphdr("application/mercurial-0.1")
957 streamclone.stream_out(self.repo, req)
954 streamclone.stream_out(self.repo, req)
@@ -1,45 +1,45
1 #header#
1 #header#
2 <title>#repo|escape#: Annotate</title>
2 <title>#repo|escape#: Annotate</title>
3 <link rel="alternate" type="application/rss+xml"
3 <link rel="alternate" type="application/rss+xml"
4 href="?cmd=changelog;style=rss" title="RSS feed for #repo|escape#">
4 href="?cmd=changelog;style=rss" title="RSS feed for #repo|escape#">
5 </head>
5 </head>
6 <body>
6 <body>
7
7
8 <div class="page_header">
8 <div class="page_header">
9 <a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a><a href="?cmd=summary;style=gitweb">#repo|escape#</a> / annotate
9 <a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a><a href="?cmd=summary;style=gitweb">#repo|escape#</a> / annotate
10 </div>
10 </div>
11
11
12 <div class="page_nav">
12 <div class="page_nav">
13 <a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=shortlog;style=gitweb">shortlog</a> | <a href="?cmd=changelog;style=gitweb">changelog</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">manifest</a> | <a href="?cmd=changeset;node=#node#;style=gitweb">changeset</a> | <a href="?cmd=file;file=#file|urlescape#;filenode=#filenode#;style=gitweb">file</a> | <a href="?cmd=filelog;file=#file|urlescape#;filenode=#filenode#;style=gitweb">revisions</a> | annotate | <a href="?cmd=annotate;file=#file|urlescape#;filenode=#filenode#;style=raw">raw</a><br/>
13 <a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=shortlog;style=gitweb">shortlog</a> | <a href="?cmd=changelog;style=gitweb">changelog</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">manifest</a> | <a href="?cmd=changeset;node=#node#;style=gitweb">changeset</a> | <a href="?cmd=file;file=#file|urlescape#;filenode=#node|short#;style=gitweb">file</a> | <a href="?cmd=filelog;file=#file|urlescape#;filenode=#node|short#;style=gitweb">revisions</a> | annotate | <a href="?cmd=annotate;file=#file|urlescape#;filenode=#node|short#;style=raw">raw</a><br/>
14 </div>
14 </div>
15
15
16 <div class="title">#file|escape#</div>
16 <div class="title">#file|escape#</div>
17
17
18 <table>
18 <table>
19 <tr>
19 <tr>
20 <td class="metatag">changeset #rev#:</td>
20 <td class="metatag">changeset #rev#:</td>
21 <td><a href="?cs=#node|short#;style=gitweb">#node|short#</a></td></tr>
21 <td><a href="?cs=#node|short#;style=gitweb">#node|short#</a></td></tr>
22 #rename%filerename#
22 #rename%filerename#
23 #parent%fileannotateparent#
23 #parent%fileannotateparent#
24 #child%fileannotatechild#
24 #child%fileannotatechild#
25 <tr>
25 <tr>
26 <td class="metatag">manifest:</td>
26 <td class="metatag">manifest:</td>
27 <td><a href="?mf=#node|short#;path=/;style=gitweb">#node|short#</a></td></tr>
27 <td><a href="?mf=#node|short#;path=/;style=gitweb">#node|short#</a></td></tr>
28 <tr>
28 <tr>
29 <td class="metatag">author:</td>
29 <td class="metatag">author:</td>
30 <td>#author|obfuscate#</td></tr>
30 <td>#author|obfuscate#</td></tr>
31 <tr>
31 <tr>
32 <td class="metatag">date:</td>
32 <td class="metatag">date:</td>
33 <td>#date|date# (#date|age# ago)</td></tr>
33 <td>#date|date# (#date|age# ago)</td></tr>
34 <tr>
34 <tr>
35 <td class="metatag">permissions:</td>
35 <td class="metatag">permissions:</td>
36 <td>#permissions|permissions#</td></tr>
36 <td>#permissions|permissions#</td></tr>
37 </table>
37 </table>
38
38
39 <div class="page_body">
39 <div class="page_body">
40 <table>
40 <table>
41 #annotate%annotateline#
41 #annotate%annotateline#
42 </table>
42 </table>
43 </div>
43 </div>
44
44
45 #footer#
45 #footer#
@@ -1,43 +1,43
1 #header#
1 #header#
2 <title>#repo|escape#: #file|escape# annotate</title>
2 <title>#repo|escape#: #file|escape# annotate</title>
3 </head>
3 </head>
4 <body>
4 <body>
5
5
6 <div class="buttons">
6 <div class="buttons">
7 <a href="?cl=#rev#">changelog</a>
7 <a href="?cl=#rev#">changelog</a>
8 <a href="?sl=#rev#">shortlog</a>
8 <a href="?sl=#rev#">shortlog</a>
9 <a href="?tags=">tags</a>
9 <a href="?tags=">tags</a>
10 <a href="?cs=#node|short#">changeset</a>
10 <a href="?cs=#node|short#">changeset</a>
11 <a href="?mf=#node|short#;path=#path|urlescape#">manifest</a>
11 <a href="?mf=#node|short#;path=#path|urlescape#">manifest</a>
12 <a href="?f=#filenode|short#;file=#file|urlescape#">file</a>
12 <a href="?f=#node|short#;file=#file|urlescape#">file</a>
13 <a href="?fl=#filenode|short#;file=#file|urlescape#">revisions</a>
13 <a href="?fl=#node|short#;file=#file|urlescape#">revisions</a>
14 <a href="?fa=#filenode|short#;file=#file|urlescape#;style=raw">raw</a>
14 <a href="?fa=#node|short#;file=#file|urlescape#;style=raw">raw</a>
15 </div>
15 </div>
16
16
17 <h2>Annotate #file|escape#</h2>
17 <h2>Annotate #file|escape#</h2>
18
18
19 <table>
19 <table>
20 <tr>
20 <tr>
21 <td class="metatag">changeset #rev#:</td>
21 <td class="metatag">changeset #rev#:</td>
22 <td><a href="?cs=#node|short#">#node|short#</a></td></tr>
22 <td><a href="?cs=#node|short#">#node|short#</a></td></tr>
23 #rename%filerename#
23 #rename%filerename#
24 #parent%fileannotateparent#
24 #parent%fileannotateparent#
25 #child%fileannotatechild#
25 #child%fileannotatechild#
26 <tr>
26 <tr>
27 <td class="metatag">author:</td>
27 <td class="metatag">author:</td>
28 <td>#author|obfuscate#</td></tr>
28 <td>#author|obfuscate#</td></tr>
29 <tr>
29 <tr>
30 <td class="metatag">date:</td>
30 <td class="metatag">date:</td>
31 <td>#date|date# (#date|age# ago)</td></tr>
31 <td>#date|date# (#date|age# ago)</td></tr>
32 <tr>
32 <tr>
33 <td class="metatag">permissions:</td>
33 <td class="metatag">permissions:</td>
34 <td>#permissions|permissions#</td></tr>
34 <td>#permissions|permissions#</td></tr>
35 </table>
35 </table>
36
36
37 <br/>
37 <br/>
38
38
39 <table cellspacing="0" cellpadding="0">
39 <table cellspacing="0" cellpadding="0">
40 #annotate%annotateline#
40 #annotate%annotateline#
41 </table>
41 </table>
42
42
43 #footer#
43 #footer#
@@ -1,34 +1,34
1 #header#
1 #header#
2 <title>#repo|escape#: #file|escape# diff</title>
2 <title>#repo|escape#: #file|escape# diff</title>
3 </head>
3 </head>
4 <body>
4 <body>
5
5
6 <div class="buttons">
6 <div class="buttons">
7 <a href="?cl=#rev#">changelog</a>
7 <a href="?cl=#rev#">changelog</a>
8 <a href="?sl=#rev#">shortlog</a>
8 <a href="?sl=#rev#">shortlog</a>
9 <a href="?tags=">tags</a>
9 <a href="?tags=">tags</a>
10 <a href="?cs=#node|short#">changeset</a>
10 <a href="?cs=#node|short#">changeset</a>
11 <a href="?f=#filenode|short#;file=#file|urlescape#">file</a>
11 <a href="?f=#node|short#;file=#file|urlescape#">file</a>
12 <a href="?fl=#filenode|short#;file=#file|urlescape#">revisions</a>
12 <a href="?fl=#node|short#;file=#file|urlescape#">revisions</a>
13 <a href="?fa=#filenode|short#;file=#file|urlescape#">annotate</a>
13 <a href="?fa=#node|short#;file=#file|urlescape#">annotate</a>
14 <a href="?fd=#node|short#;file=#file|urlescape#;style=raw">raw</a>
14 <a href="?fd=#node|short#;file=#file|urlescape#;style=raw">raw</a>
15 </div>
15 </div>
16
16
17 <h2>#file|escape#</h2>
17 <h2>#file|escape#</h2>
18
18
19 <table id="filediffEntry">
19 <table id="filediffEntry">
20 <tr>
20 <tr>
21 <th class="revision">revision #rev#:</th>
21 <th class="revision">revision #rev#:</th>
22 <td class="revision"><a href="?cs=#node|short#">#node|short#</a></td>
22 <td class="revision"><a href="?cs=#node|short#">#node|short#</a></td>
23 </tr>
23 </tr>
24 #parent%filediffparent#
24 #parent%filediffparent#
25 #child%filediffchild#
25 #child%filediffchild#
26 </table>
26 </table>
27
27
28 <div id="fileDiff">
28 <div id="fileDiff">
29 #diff#
29 #diff#
30 </div>
30 </div>
31
31
32 #footer#
32 #footer#
33
33
34
34
@@ -1,22 +1,22
1 #header#
1 #header#
2 <title>#repo|escape#: File revisions</title>
2 <title>#repo|escape#: File revisions</title>
3 <link rel="alternate" type="application/rss+xml"
3 <link rel="alternate" type="application/rss+xml"
4 href="?cmd=changelog;style=rss" title="RSS feed for #repo|escape#">
4 href="?cmd=changelog;style=rss" title="RSS feed for #repo|escape#">
5 </head>
5 </head>
6 <body>
6 <body>
7
7
8 <div class="page_header">
8 <div class="page_header">
9 <a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a><a href="?cmd=summary;style=gitweb">#repo|escape#</a> / file revisions
9 <a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a><a href="?cmd=summary;style=gitweb">#repo|escape#</a> / file revisions
10 </div>
10 </div>
11
11
12 <div class="page_nav">
12 <div class="page_nav">
13 <a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=shortlog;style=gitweb">shortlog</a> | <a href="?cmd=changelog;style=gitweb">changelog</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?cmd=file;file=#file|urlescape#;filenode=#filenode#;style=gitweb">file</a> | revisions | <a href="?cmd=annotate;file=#file|urlescape#;filenode=#filenode#;style=gitweb">annotate</a> | <a href="?fl=#filenode|short#;file=#file|urlescape#;style=rss">rss</a><br/>
13 <a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=shortlog;style=gitweb">shortlog</a> | <a href="?cmd=changelog;style=gitweb">changelog</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?cmd=file;file=#file|urlescape#;filenode=#node|short#;style=gitweb">file</a> | revisions | <a href="?cmd=annotate;file=#file|urlescape#;filenode=#node|short#;style=gitweb">annotate</a> | <a href="?fl=#node|short#;file=#file|urlescape#;style=rss">rss</a><br/>
14 </div>
14 </div>
15
15
16 <div class="title" >#file|urlescape#</div>
16 <div class="title" >#file|urlescape#</div>
17
17
18 <table>
18 <table>
19 #entries%filelogentry#
19 #entries%filelogentry#
20 </table>
20 </table>
21
21
22 #footer#
22 #footer#
@@ -1,22 +1,22
1 #header#
1 #header#
2 <title>#repo|escape#: #file|escape# history</title>
2 <title>#repo|escape#: #file|escape# history</title>
3 <link rel="alternate" type="application/rss+xml"
3 <link rel="alternate" type="application/rss+xml"
4 href="?fl=0;file=#file|urlescape#;style=rss" title="RSS feed for #repo|escape#:#file#">
4 href="?fl=0;file=#file|urlescape#;style=rss" title="RSS feed for #repo|escape#:#file#">
5 </head>
5 </head>
6 </head>
6 </head>
7 <body>
7 <body>
8
8
9 <div class="buttons">
9 <div class="buttons">
10 <a href="?cl=tip">changelog</a>
10 <a href="?cl=tip">changelog</a>
11 <a href="?sl=tip">shortlog</a>
11 <a href="?sl=tip">shortlog</a>
12 <a href="?tags=">tags</a>
12 <a href="?tags=">tags</a>
13 <a href="?f=#filenode|short#;file=#file|urlescape#">file</a>
13 <a href="?f=#node|short#;file=#file|urlescape#">file</a>
14 <a href="?fa=#filenode|short#;file=#file|urlescape#">annotate</a>
14 <a href="?fa=#node|short#;file=#file|urlescape#">annotate</a>
15 <a type="application/rss+xml" href="?fl=0;file=#file|urlescape#;style=rss">rss</a>
15 <a type="application/rss+xml" href="?fl=0;file=#file|urlescape#;style=rss">rss</a>
16 </div>
16 </div>
17
17
18 <h2>#file|escape# revision history</h2>
18 <h2>#file|escape# revision history</h2>
19
19
20 #entries%filelogentry#
20 #entries%filelogentry#
21
21
22 #footer#
22 #footer#
@@ -1,7 +1,7
1 <item>
1 <item>
2 <title>#desc|strip|firstline|strip|escape#</title>
2 <title>#desc|strip|firstline|strip|escape#</title>
3 <link>#url#?f=#filenode|short#;file=#file|urlescape#</link>
3 <link>#url#?f=#node|short#;file=#file|urlescape#</link>
4 <description><![CDATA[#desc|strip|escape|addbreaks#]]></description>
4 <description><![CDATA[#desc|strip|escape|addbreaks#]]></description>
5 <author>#author|obfuscate#</author>
5 <author>#author|obfuscate#</author>
6 <pubDate>#date|rfc822date#</pubDate>>
6 <pubDate>#date|rfc822date#</pubDate>>
7 </item>
7 </item>
@@ -1,25 +1,25
1 <table class="logEntry parity#parity#">
1 <table class="logEntry parity#parity#">
2 <tr>
2 <tr>
3 <th class="age">#date|age# ago:</th>
3 <th class="age">#date|age# ago:</th>
4 <th class="firstline"><a href="?cs=#node|short#">#desc|strip|firstline|escape#</a></th>
4 <th class="firstline"><a href="?cs=#node|short#">#desc|strip|firstline|escape#</a></th>
5 </tr>
5 </tr>
6 <tr>
6 <tr>
7 <th class="revision">revision #filerev#:</td>
7 <th class="revision">revision #filerev#:</td>
8 <td class="node">
8 <td class="node">
9 <a href="?f=#filenode|short#;file=#file|urlescape#">#filenode|short#</a>
9 <a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a>
10 <a href="?fd=#node|short#;file=#file|urlescape#">(diff)</a>
10 <a href="?fd=#node|short#;file=#file|urlescape#">(diff)</a>
11 <a href="?fa=#filenode|short#;file=#file|urlescape#">(annotate)</a>
11 <a href="?fa=#node|short#;file=#file|urlescape#">(annotate)</a>
12 </td>
12 </td>
13 </tr>
13 </tr>
14 #rename%filelogrename#
14 #rename%filelogrename#
15 <tr>
15 <tr>
16 <th class="author">author:</th>
16 <th class="author">author:</th>
17 <td class="author">#author|obfuscate#</td>
17 <td class="author">#author|obfuscate#</td>
18 </tr>
18 </tr>
19 <tr>
19 <tr>
20 <th class="date">date:</th>
20 <th class="date">date:</th>
21 <td class="date">#date|date#</td>
21 <td class="date">#date|date#</td>
22 </tr>
22 </tr>
23 </table>
23 </table>
24
24
25
25
@@ -1,43 +1,43
1 #header#
1 #header#
2 <title>#repo|escape#: File revision</title>
2 <title>#repo|escape#: File revision</title>
3 <link rel="alternate" type="application/rss+xml"
3 <link rel="alternate" type="application/rss+xml"
4 href="?cmd=changelog;style=rss" title="RSS feed for #repo|escape#">
4 href="?cmd=changelog;style=rss" title="RSS feed for #repo|escape#">
5 </head>
5 </head>
6 <body>
6 <body>
7
7
8 <div class="page_header">
8 <div class="page_header">
9 <a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a><a href="?cmd=summary;style=gitweb">#repo|escape#</a> / file revision
9 <a href="http://www.selenic.com/mercurial/" title="Mercurial"><div style="float:right;">Mercurial</div></a><a href="?cmd=summary;style=gitweb">#repo|escape#</a> / file revision
10 </div>
10 </div>
11
11
12 <div class="page_nav">
12 <div class="page_nav">
13 <a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=shortlog;style=gitweb">shortlog</a> | <a href="?cmd=changelog;style=gitweb">changelog</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">manifest</a> | <a href="?cmd=changeset;node=#node#;style=gitweb">changeset</a> | file | <a href="?cmd=filelog;file=#file|urlescape#;filenode=#filenode#;style=gitweb">revisions</a> | <a href="?cmd=annotate;file=#file|urlescape#;filenode=#filenode#;style=gitweb">annotate</a> | <a href="?cmd=file;file=#file|urlescape#;filenode=#filenode#;style=raw">raw</a><br/>
13 <a href="?cmd=summary;style=gitweb">summary</a> | <a href="?cmd=shortlog;style=gitweb">shortlog</a> | <a href="?cmd=changelog;style=gitweb">changelog</a> | <a href="?cmd=tags;style=gitweb">tags</a> | <a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">manifest</a> | <a href="?cmd=changeset;node=#node#;style=gitweb">changeset</a> | file | <a href="?cmd=filelog;file=#file|urlescape#;filenode=#node|short#;style=gitweb">revisions</a> | <a href="?cmd=annotate;file=#file|urlescape#;filenode=#node|short#;style=gitweb">annotate</a> | <a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=raw">raw</a><br/>
14 </div>
14 </div>
15
15
16 <div class="title">#file|escape#</div>
16 <div class="title">#file|escape#</div>
17
17
18 <table>
18 <table>
19 <tr>
19 <tr>
20 <td class="metatag">changeset #rev#:</td>
20 <td class="metatag">changeset #rev#:</td>
21 <td><a href="?cs=#node|short#;style=gitweb">#node|short#</a></td></tr>
21 <td><a href="?cs=#node|short#;style=gitweb">#node|short#</a></td></tr>
22 #rename%filerename#
22 #rename%filerename#
23 #parent%fileannotateparent#
23 #parent%fileannotateparent#
24 #child%fileannotatechild#
24 #child%fileannotatechild#
25 <tr>
25 <tr>
26 <td class="metatag">manifest:</td>
26 <td class="metatag">manifest:</td>
27 <td><a href="?mf=#node|short#;path=/;style=gitweb">#node|short#</a></td></tr>
27 <td><a href="?mf=#node|short#;path=/;style=gitweb">#node|short#</a></td></tr>
28 <tr>
28 <tr>
29 <td class="metatag">author:</td>
29 <td class="metatag">author:</td>
30 <td>#author|obfuscate#</td></tr>
30 <td>#author|obfuscate#</td></tr>
31 <tr>
31 <tr>
32 <td class="metatag">date:</td>
32 <td class="metatag">date:</td>
33 <td>#date|date# (#date|age# ago)</td></tr>
33 <td>#date|date# (#date|age# ago)</td></tr>
34 <tr>
34 <tr>
35 <td class="metatag">permissions:</td>
35 <td class="metatag">permissions:</td>
36 <td>#permissions|permissions#</td></tr>
36 <td>#permissions|permissions#</td></tr>
37 </table>
37 </table>
38
38
39 <div class="page_body">
39 <div class="page_body">
40 #text%fileline#
40 #text%fileline#
41 </div>
41 </div>
42
42
43 #footer#
43 #footer#
@@ -1,41 +1,41
1 #header#
1 #header#
2 <title>#repo|escape#:#file|escape#</title>
2 <title>#repo|escape#:#file|escape#</title>
3 </head>
3 </head>
4 <body>
4 <body>
5
5
6 <div class="buttons">
6 <div class="buttons">
7 <a href="?cl=#rev#">changelog</a>
7 <a href="?cl=#rev#">changelog</a>
8 <a href="?sl=#rev#">shortlog</a>
8 <a href="?sl=#rev#">shortlog</a>
9 <a href="?tags=">tags</a>
9 <a href="?tags=">tags</a>
10 <a href="?cs=#node|short#">changeset</a>
10 <a href="?cs=#node|short#">changeset</a>
11 <a href="?mf=#node|short#;path=#path|urlescape#">manifest</a>
11 <a href="?mf=#node|short#;path=#path|urlescape#">manifest</a>
12 <a href="?fl=#filenode|short#;file=#file|urlescape#">revisions</a>
12 <a href="?fl=#node|short#;file=#file|urlescape#">revisions</a>
13 <a href="?fa=#filenode|short#;file=#file|urlescape#">annotate</a>
13 <a href="?fa=#node|short#;file=#file|urlescape#">annotate</a>
14 <a href="?f=#filenode|short#;file=#file|urlescape#;style=raw">raw</a>
14 <a href="?f=#node|short#;file=#file|urlescape#;style=raw">raw</a>
15 </div>
15 </div>
16
16
17 <h2>#file|escape#</h2>
17 <h2>#file|escape#</h2>
18
18
19 <table>
19 <table>
20 <tr>
20 <tr>
21 <td class="metatag">changeset #rev#:</td>
21 <td class="metatag">changeset #rev#:</td>
22 <td><a href="?cs=#node|short#">#node|short#</a></td></tr>
22 <td><a href="?cs=#node|short#">#node|short#</a></td></tr>
23 #rename%filerename#
23 #rename%filerename#
24 #parent%filerevparent#
24 #parent%filerevparent#
25 #child%filerevchild#
25 #child%filerevchild#
26 <tr>
26 <tr>
27 <td class="metatag">author:</td>
27 <td class="metatag">author:</td>
28 <td>#author|obfuscate#</td></tr>
28 <td>#author|obfuscate#</td></tr>
29 <tr>
29 <tr>
30 <td class="metatag">date:</td>
30 <td class="metatag">date:</td>
31 <td>#date|date# (#date|age# ago)</td></tr>
31 <td>#date|date# (#date|age# ago)</td></tr>
32 <tr>
32 <tr>
33 <td class="metatag">permissions:</td>
33 <td class="metatag">permissions:</td>
34 <td>#permissions|permissions#</td></tr>
34 <td>#permissions|permissions#</td></tr>
35 </table>
35 </table>
36
36
37 <pre>
37 <pre>
38 #text%fileline#
38 #text%fileline#
39 </pre>
39 </pre>
40
40
41 #footer#
41 #footer#
@@ -1,53 +1,53
1 default = 'changelog'
1 default = 'changelog'
2 header = header.tmpl
2 header = header.tmpl
3 footer = footer.tmpl
3 footer = footer.tmpl
4 search = search.tmpl
4 search = search.tmpl
5 changelog = changelog.tmpl
5 changelog = changelog.tmpl
6 shortlog = shortlog.tmpl
6 shortlog = shortlog.tmpl
7 shortlogentry = shortlogentry.tmpl
7 shortlogentry = shortlogentry.tmpl
8 naventry = '<a href="?cl=#rev#">#label|escape#</a> '
8 naventry = '<a href="?cl=#rev#">#label|escape#</a> '
9 navshortentry = '<a href="?sl=#rev#">#label|escape#</a> '
9 navshortentry = '<a href="?sl=#rev#">#label|escape#</a> '
10 filedifflink = '<a href="?fd=#node|short#;file=#file|urlescape#">#file|escape#</a> '
10 filedifflink = '<a href="?fd=#node|short#;file=#file|urlescape#">#file|escape#</a> '
11 filenodelink = '<a href="?f=#filenode|short#;file=#file|urlescape#">#file|escape#</a> '
11 filenodelink = '<a href="?f=#node|short#;file=#file|urlescape#">#file|escape#</a> '
12 fileellipses = '...'
12 fileellipses = '...'
13 changelogentry = changelogentry.tmpl
13 changelogentry = changelogentry.tmpl
14 searchentry = changelogentry.tmpl
14 searchentry = changelogentry.tmpl
15 changeset = changeset.tmpl
15 changeset = changeset.tmpl
16 manifest = manifest.tmpl
16 manifest = manifest.tmpl
17 manifestdirentry = '<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt>&nbsp;<td><a href="?mf=#node|short#;path=#path|urlescape#">#basename|escape#/</a>'
17 manifestdirentry = '<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt>&nbsp;<td><a href="?mf=#node|short#;path=#path|urlescape#">#basename|escape#/</a>'
18 manifestfileentry = '<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt>&nbsp;<td><a href="?f=#filenode|short#;file=#file|urlescape#">#basename|escape#</a>'
18 manifestfileentry = '<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt>&nbsp;<td><a href="?f=#node|short#;file=#file|urlescape#">#basename|escape#</a>'
19 filerevision = filerevision.tmpl
19 filerevision = filerevision.tmpl
20 fileannotate = fileannotate.tmpl
20 fileannotate = fileannotate.tmpl
21 filediff = filediff.tmpl
21 filediff = filediff.tmpl
22 filelog = filelog.tmpl
22 filelog = filelog.tmpl
23 fileline = '<div class="parity#parity#"><span class="lineno">#linenumber#</span>#line|escape#</div>'
23 fileline = '<div class="parity#parity#"><span class="lineno">#linenumber#</span>#line|escape#</div>'
24 filelogentry = filelogentry.tmpl
24 filelogentry = filelogentry.tmpl
25 annotateline = '<tr class="parity#parity#"><td class="annotate"><a href="?fa=#filenode|short#;file=#file|urlescape#">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>'
25 annotateline = '<tr class="parity#parity#"><td class="annotate"><a href="?fa=#node|short#;file=#file|urlescape#">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>'
26 difflineplus = '<span class="plusline">#line|escape#</span>'
26 difflineplus = '<span class="plusline">#line|escape#</span>'
27 difflineminus = '<span class="minusline">#line|escape#</span>'
27 difflineminus = '<span class="minusline">#line|escape#</span>'
28 difflineat = '<span class="atline">#line|escape#</span>'
28 difflineat = '<span class="atline">#line|escape#</span>'
29 diffline = '#line|escape#'
29 diffline = '#line|escape#'
30 changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
30 changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
31 changesetparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
31 changesetparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
32 filerevparent = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
32 filerevparent = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
33 filerename = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#file|escape#@#node|short#</a></td></tr>'
33 filerename = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#file|escape#@#node|short#</a></td></tr>'
34 filelogrename = '<tr><th>base:</th><td><a href="?f=#node|short#;file=#file|urlescape#">#file|escape#@#node|short#</a></td></tr>'
34 filelogrename = '<tr><th>base:</th><td><a href="?f=#node|short#;file=#file|urlescape#">#file|escape#@#node|short#</a></td></tr>'
35 fileannotateparent = '<tr><td class="metatag">parent:</td><td><a href="?fa=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
35 fileannotateparent = '<tr><td class="metatag">parent:</td><td><a href="?fa=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
36 changesetchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
36 changesetchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
37 changelogchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
37 changelogchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
38 filerevchild = '<tr><td class="metatag">child:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
38 filerevchild = '<tr><td class="metatag">child:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
39 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="?fa=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
39 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="?fa=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
40 tags = tags.tmpl
40 tags = tags.tmpl
41 tagentry = '<li class="tagEntry parity#parity#"><tt class="node">#node#</tt> <a href="?cs=#node|short#">#tag|escape#</a></li>'
41 tagentry = '<li class="tagEntry parity#parity#"><tt class="node">#node#</tt> <a href="?cs=#node|short#">#tag|escape#</a></li>'
42 diffblock = '<pre class="parity#parity#">#lines#</pre>'
42 diffblock = '<pre class="parity#parity#">#lines#</pre>'
43 changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
43 changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
44 changesettag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
44 changesettag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
45 filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
45 filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
46 filelogparent = '<tr><th>parent #rev#:</th><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
46 filelogparent = '<tr><th>parent #rev#:</th><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
47 filediffchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
47 filediffchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
48 filelogchild = '<tr><th>child #rev#:</th><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
48 filelogchild = '<tr><th>child #rev#:</th><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
49 indexentry = '<tr class="parity#parity#"><td><a href="#url#">#name|escape#</a></td><td>#description#</td><td>#contact|obfuscate#</td><td class="age">#lastchange|age# ago</td><td class="indexlinks"><a href="#url#?cl=tip;style=rss">RSS</a> #archives%archiveentry#</td></tr>'
49 indexentry = '<tr class="parity#parity#"><td><a href="#url#">#name|escape#</a></td><td>#description#</td><td>#contact|obfuscate#</td><td class="age">#lastchange|age# ago</td><td class="indexlinks"><a href="#url#?cl=tip;style=rss">RSS</a> #archives%archiveentry#</td></tr>'
50 index = index.tmpl
50 index = index.tmpl
51 archiveentry = '<a href="#url#?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
51 archiveentry = '<a href="#url#?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
52 notfound = notfound.tmpl
52 notfound = notfound.tmpl
53 error = error.tmpl
53 error = error.tmpl
@@ -1,50 +1,50
1 default = 'summary'
1 default = 'summary'
2 header = header-gitweb.tmpl
2 header = header-gitweb.tmpl
3 footer = footer-gitweb.tmpl
3 footer = footer-gitweb.tmpl
4 search = search-gitweb.tmpl
4 search = search-gitweb.tmpl
5 changelog = changelog-gitweb.tmpl
5 changelog = changelog-gitweb.tmpl
6 summary = summary-gitweb.tmpl
6 summary = summary-gitweb.tmpl
7 error = error-gitweb.tmpl
7 error = error-gitweb.tmpl
8 naventry = '<a href="?cmd=changelog;rev=#rev#;style=gitweb">#label|escape#</a> '
8 naventry = '<a href="?cmd=changelog;rev=#rev#;style=gitweb">#label|escape#</a> '
9 navshortentry = '<a href="?cmd=shortlog;rev=#rev#;style=gitweb">#label|escape#</a> '
9 navshortentry = '<a href="?cmd=shortlog;rev=#rev#;style=gitweb">#label|escape#</a> '
10 filedifflink = '<a href="?cmd=filediff;node=#node#;file=#file|urlescape#;style=gitweb">#file|escape#</a> '
10 filedifflink = '<a href="?cmd=filediff;node=#node#;file=#file|urlescape#;style=gitweb">#file|escape#</a> '
11 filenodelink = '<tr class="parity#parity#"><td><a class="list" href="">#file|escape#</a></td><td></td><td class="link"><a href="?cmd=file;filenode=#filenode#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> | <!-- FIXME: <a href="?fd=#filenode|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?cmd=filelog;filenode=#filenode|short#;file=#file|urlescape#;style=gitweb">revisions</a></td></tr>'
11 filenodelink = '<tr class="parity#parity#"><td><a class="list" href="">#file|escape#</a></td><td></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">annotate</a> | <!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?cmd=filelog;filenode=#node|short#;file=#file|urlescape#;style=gitweb">revisions</a></td></tr>'
12 fileellipses = '...'
12 fileellipses = '...'
13 changelogentry = changelogentry-gitweb.tmpl
13 changelogentry = changelogentry-gitweb.tmpl
14 searchentry = changelogentry-gitweb.tmpl
14 searchentry = changelogentry-gitweb.tmpl
15 changeset = changeset-gitweb.tmpl
15 changeset = changeset-gitweb.tmpl
16 manifest = manifest-gitweb.tmpl
16 manifest = manifest-gitweb.tmpl
17 manifestdirentry = '<tr class="parity#parity#"><td style="font-family:monospace">drwxr-xr-x</td><td><a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">#basename|escape#/</a></td><td class="link"><a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">manifest</a></td></tr>'
17 manifestdirentry = '<tr class="parity#parity#"><td style="font-family:monospace">drwxr-xr-x</td><td><a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">#basename|escape#/</a></td><td class="link"><a href="?mf=#node|short#;path=#path|urlescape#;style=gitweb">manifest</a></td></tr>'
18 manifestfileentry = '<tr class="parity#parity#"><td style="font-family:monospace">#permissions|permissions#</td><td class="list"><a class="list" href="?f=#filenode|short#;file=#file|urlescape#;style=gitweb">#basename|escape#</a></td><td class="link"><a href="?f=#filenode|short#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fl=#filenode|short#;file=#file|urlescape#;style=gitweb">revisions</a> | <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a></td></tr>'
18 manifestfileentry = '<tr class="parity#parity#"><td style="font-family:monospace">#permissions|permissions#</td><td class="list"><a class="list" href="?f=#node|short#;file=#file|urlescape#;style=gitweb">#basename|escape#</a></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fl=#node|short#;file=#file|urlescape#;style=gitweb">revisions</a> | <a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">annotate</a></td></tr>'
19 filerevision = filerevision-gitweb.tmpl
19 filerevision = filerevision-gitweb.tmpl
20 fileannotate = fileannotate-gitweb.tmpl
20 fileannotate = fileannotate-gitweb.tmpl
21 filelog = filelog-gitweb.tmpl
21 filelog = filelog-gitweb.tmpl
22 fileline = '<div style="font-family:monospace" class="parity#parity#"><pre><span class="linenr"> #linenumber#</span> #line|escape#</pre></div>'
22 fileline = '<div style="font-family:monospace" class="parity#parity#"><pre><span class="linenr"> #linenumber#</span> #line|escape#</pre></div>'
23 annotateline = '<tr style="font-family:monospace" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>'
23 annotateline = '<tr style="font-family:monospace" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>'
24 difflineplus = '<div style="color:#008800;">#line|escape#</div>'
24 difflineplus = '<div style="color:#008800;">#line|escape#</div>'
25 difflineminus = '<div style="color:#cc0000;">#line|escape#</div>'
25 difflineminus = '<div style="color:#cc0000;">#line|escape#</div>'
26 difflineat = '<div style="color:#990099;">#line|escape#</div>'
26 difflineat = '<div style="color:#990099;">#line|escape#</div>'
27 diffline = '<div>#line|escape#</div>'
27 diffline = '<div>#line|escape#</div>'
28 changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
28 changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
29 changesetparent = '<tr><td>parent</td><td style="font-family:monospace"><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb">#node|short#</a></td></tr>'
29 changesetparent = '<tr><td>parent</td><td style="font-family:monospace"><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb">#node|short#</a></td></tr>'
30 filerevparent = '<tr><td class="metatag">parent:</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
30 filerevparent = '<tr><td class="metatag">parent:</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
31 filerename = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">#file|escape#@#node|short#</a></td></tr>'
31 filerename = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">#file|escape#@#node|short#</a></td></tr>'
32 filelogrename = '| <a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">base</a>'
32 filelogrename = '| <a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">base</a>'
33 fileannotateparent = '<tr><td class="metatag">parent:</td><td><a href="?cmd=annotate;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
33 fileannotateparent = '<tr><td class="metatag">parent:</td><td><a href="?cmd=annotate;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
34 changelogchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
34 changelogchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
35 changesetchild = '<tr><td>child</td><td style="font-family:monospace"><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb">#node|short#</a></td></tr>'
35 changesetchild = '<tr><td>child</td><td style="font-family:monospace"><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb">#node|short#</a></td></tr>'
36 filerevchild = '<tr><td class="metatag">child:</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
36 filerevchild = '<tr><td class="metatag">child:</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
37 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="?cmd=annotate;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
37 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="?cmd=annotate;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
38 tags = tags-gitweb.tmpl
38 tags = tags-gitweb.tmpl
39 tagentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#tag|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=changelog;rev=#node|short#;style=gitweb">changelog</a> | <a href="?mf=#node|short#;path=/;style=gitweb">manifest</a></td></tr>'
39 tagentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#tag|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=changelog;rev=#node|short#;style=gitweb">changelog</a> | <a href="?mf=#node|short#;path=/;style=gitweb">manifest</a></td></tr>'
40 diffblock = '<pre>#lines#</pre>'
40 diffblock = '<pre>#lines#</pre>'
41 changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
41 changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
42 changesettag = '<tr><td>tag</td><td>#tag|escape#</td></tr>'
42 changesettag = '<tr><td>tag</td><td>#tag|escape#</td></tr>'
43 filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
43 filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
44 filelogparent = '<tr><td align="right">parent #rev#:&nbsp;</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
44 filelogparent = '<tr><td align="right">parent #rev#:&nbsp;</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
45 filediffchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
45 filediffchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
46 filelogchild = '<tr><td align="right">child #rev#:&nbsp;</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
46 filelogchild = '<tr><td align="right">child #rev#:&nbsp;</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
47 shortlog = shortlog-gitweb.tmpl
47 shortlog = shortlog-gitweb.tmpl
48 shortlogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><i>#author#</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=manifest;manifest=#node|short#;path=/;style=gitweb">manifest</a></td></tr>'
48 shortlogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><i>#author#</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=manifest;manifest=#node|short#;path=/;style=gitweb">manifest</a></td></tr>'
49 filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> #rename%filelogrename#</td></tr>'
49 filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?fa=#node|short#;file=#file|urlescape#;style=gitweb">annotate</a> #rename%filelogrename#</td></tr>'
50 archiveentry = ' | <a href="?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
50 archiveentry = ' | <a href="?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
General Comments 0
You need to be logged in to leave comments. Login now