##// END OF EJS Templates
hgweb: add display of bookmarks for changelog and changeset
Alexander Solovyov -
r13596:270f57d3 stable
parent child Browse files
Show More
@@ -1,784 +1,789 b''
1 #
1 #
2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import os, mimetypes, re, cgi, copy
8 import os, mimetypes, re, cgi, copy
9 import webutil
9 import webutil
10 from mercurial import error, encoding, archival, templater, templatefilters
10 from mercurial import error, encoding, archival, templater, templatefilters
11 from mercurial.node import short, hex
11 from mercurial.node import short, hex
12 from mercurial.util import binary
12 from mercurial.util import binary
13 from common import paritygen, staticfile, get_contact, ErrorResponse
13 from common import paritygen, staticfile, get_contact, ErrorResponse
14 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
14 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
15 from mercurial import graphmod
15 from mercurial import graphmod
16 from mercurial import help as helpmod
16 from mercurial import help as helpmod
17 from mercurial.i18n import _
17 from mercurial.i18n import _
18
18
19 # __all__ is populated with the allowed commands. Be sure to add to it if
19 # __all__ is populated with the allowed commands. Be sure to add to it if
20 # you're adding a new command, or the new command won't work.
20 # you're adding a new command, or the new command won't work.
21
21
22 __all__ = [
22 __all__ = [
23 'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev',
23 'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev',
24 'manifest', 'tags', 'branches', 'summary', 'filediff', 'diff', 'annotate',
24 'manifest', 'tags', 'branches', 'summary', 'filediff', 'diff', 'annotate',
25 'filelog', 'archive', 'static', 'graph', 'help',
25 'filelog', 'archive', 'static', 'graph', 'help',
26 ]
26 ]
27
27
28 def log(web, req, tmpl):
28 def log(web, req, tmpl):
29 if 'file' in req.form and req.form['file'][0]:
29 if 'file' in req.form and req.form['file'][0]:
30 return filelog(web, req, tmpl)
30 return filelog(web, req, tmpl)
31 else:
31 else:
32 return changelog(web, req, tmpl)
32 return changelog(web, req, tmpl)
33
33
34 def rawfile(web, req, tmpl):
34 def rawfile(web, req, tmpl):
35 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
35 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
36 if not path:
36 if not path:
37 content = manifest(web, req, tmpl)
37 content = manifest(web, req, tmpl)
38 req.respond(HTTP_OK, web.ctype)
38 req.respond(HTTP_OK, web.ctype)
39 return content
39 return content
40
40
41 try:
41 try:
42 fctx = webutil.filectx(web.repo, req)
42 fctx = webutil.filectx(web.repo, req)
43 except error.LookupError, inst:
43 except error.LookupError, inst:
44 try:
44 try:
45 content = manifest(web, req, tmpl)
45 content = manifest(web, req, tmpl)
46 req.respond(HTTP_OK, web.ctype)
46 req.respond(HTTP_OK, web.ctype)
47 return content
47 return content
48 except ErrorResponse:
48 except ErrorResponse:
49 raise inst
49 raise inst
50
50
51 path = fctx.path()
51 path = fctx.path()
52 text = fctx.data()
52 text = fctx.data()
53 mt = mimetypes.guess_type(path)[0]
53 mt = mimetypes.guess_type(path)[0]
54 if mt is None:
54 if mt is None:
55 mt = binary(text) and 'application/octet-stream' or 'text/plain'
55 mt = binary(text) and 'application/octet-stream' or 'text/plain'
56 if mt.startswith('text/'):
56 if mt.startswith('text/'):
57 mt += '; charset="%s"' % encoding.encoding
57 mt += '; charset="%s"' % encoding.encoding
58
58
59 req.respond(HTTP_OK, mt, path, len(text))
59 req.respond(HTTP_OK, mt, path, len(text))
60 return [text]
60 return [text]
61
61
62 def _filerevision(web, tmpl, fctx):
62 def _filerevision(web, tmpl, fctx):
63 f = fctx.path()
63 f = fctx.path()
64 text = fctx.data()
64 text = fctx.data()
65 parity = paritygen(web.stripecount)
65 parity = paritygen(web.stripecount)
66
66
67 if binary(text):
67 if binary(text):
68 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
68 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
69 text = '(binary:%s)' % mt
69 text = '(binary:%s)' % mt
70
70
71 def lines():
71 def lines():
72 for lineno, t in enumerate(text.splitlines(True)):
72 for lineno, t in enumerate(text.splitlines(True)):
73 yield {"line": t,
73 yield {"line": t,
74 "lineid": "l%d" % (lineno + 1),
74 "lineid": "l%d" % (lineno + 1),
75 "linenumber": "% 6d" % (lineno + 1),
75 "linenumber": "% 6d" % (lineno + 1),
76 "parity": parity.next()}
76 "parity": parity.next()}
77
77
78 return tmpl("filerevision",
78 return tmpl("filerevision",
79 file=f,
79 file=f,
80 path=webutil.up(f),
80 path=webutil.up(f),
81 text=lines(),
81 text=lines(),
82 rev=fctx.rev(),
82 rev=fctx.rev(),
83 node=hex(fctx.node()),
83 node=hex(fctx.node()),
84 author=fctx.user(),
84 author=fctx.user(),
85 date=fctx.date(),
85 date=fctx.date(),
86 desc=fctx.description(),
86 desc=fctx.description(),
87 branch=webutil.nodebranchnodefault(fctx),
87 branch=webutil.nodebranchnodefault(fctx),
88 parent=webutil.parents(fctx),
88 parent=webutil.parents(fctx),
89 child=webutil.children(fctx),
89 child=webutil.children(fctx),
90 rename=webutil.renamelink(fctx),
90 rename=webutil.renamelink(fctx),
91 permissions=fctx.manifest().flags(f))
91 permissions=fctx.manifest().flags(f))
92
92
93 def file(web, req, tmpl):
93 def file(web, req, tmpl):
94 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
94 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
95 if not path:
95 if not path:
96 return manifest(web, req, tmpl)
96 return manifest(web, req, tmpl)
97 try:
97 try:
98 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
98 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
99 except error.LookupError, inst:
99 except error.LookupError, inst:
100 try:
100 try:
101 return manifest(web, req, tmpl)
101 return manifest(web, req, tmpl)
102 except ErrorResponse:
102 except ErrorResponse:
103 raise inst
103 raise inst
104
104
105 def _search(web, req, tmpl):
105 def _search(web, req, tmpl):
106
106
107 query = req.form['rev'][0]
107 query = req.form['rev'][0]
108 revcount = web.maxchanges
108 revcount = web.maxchanges
109 if 'revcount' in req.form:
109 if 'revcount' in req.form:
110 revcount = int(req.form.get('revcount', [revcount])[0])
110 revcount = int(req.form.get('revcount', [revcount])[0])
111 tmpl.defaults['sessionvars']['revcount'] = revcount
111 tmpl.defaults['sessionvars']['revcount'] = revcount
112
112
113 lessvars = copy.copy(tmpl.defaults['sessionvars'])
113 lessvars = copy.copy(tmpl.defaults['sessionvars'])
114 lessvars['revcount'] = revcount / 2
114 lessvars['revcount'] = revcount / 2
115 lessvars['rev'] = query
115 lessvars['rev'] = query
116 morevars = copy.copy(tmpl.defaults['sessionvars'])
116 morevars = copy.copy(tmpl.defaults['sessionvars'])
117 morevars['revcount'] = revcount * 2
117 morevars['revcount'] = revcount * 2
118 morevars['rev'] = query
118 morevars['rev'] = query
119
119
120 def changelist(**map):
120 def changelist(**map):
121 count = 0
121 count = 0
122 qw = query.lower().split()
122 qw = query.lower().split()
123
123
124 def revgen():
124 def revgen():
125 for i in xrange(len(web.repo) - 1, 0, -100):
125 for i in xrange(len(web.repo) - 1, 0, -100):
126 l = []
126 l = []
127 for j in xrange(max(0, i - 100), i + 1):
127 for j in xrange(max(0, i - 100), i + 1):
128 ctx = web.repo[j]
128 ctx = web.repo[j]
129 l.append(ctx)
129 l.append(ctx)
130 l.reverse()
130 l.reverse()
131 for e in l:
131 for e in l:
132 yield e
132 yield e
133
133
134 for ctx in revgen():
134 for ctx in revgen():
135 miss = 0
135 miss = 0
136 for q in qw:
136 for q in qw:
137 if not (q in ctx.user().lower() or
137 if not (q in ctx.user().lower() or
138 q in ctx.description().lower() or
138 q in ctx.description().lower() or
139 q in " ".join(ctx.files()).lower()):
139 q in " ".join(ctx.files()).lower()):
140 miss = 1
140 miss = 1
141 break
141 break
142 if miss:
142 if miss:
143 continue
143 continue
144
144
145 count += 1
145 count += 1
146 n = ctx.node()
146 n = ctx.node()
147 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
147 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
148 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
148 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
149
149
150 yield tmpl('searchentry',
150 yield tmpl('searchentry',
151 parity=parity.next(),
151 parity=parity.next(),
152 author=ctx.user(),
152 author=ctx.user(),
153 parent=webutil.parents(ctx),
153 parent=webutil.parents(ctx),
154 child=webutil.children(ctx),
154 child=webutil.children(ctx),
155 changelogtag=showtags,
155 changelogtag=showtags,
156 desc=ctx.description(),
156 desc=ctx.description(),
157 date=ctx.date(),
157 date=ctx.date(),
158 files=files,
158 files=files,
159 rev=ctx.rev(),
159 rev=ctx.rev(),
160 node=hex(n),
160 node=hex(n),
161 tags=webutil.nodetagsdict(web.repo, n),
161 tags=webutil.nodetagsdict(web.repo, n),
162 inbranch=webutil.nodeinbranch(web.repo, ctx),
162 inbranch=webutil.nodeinbranch(web.repo, ctx),
163 branches=webutil.nodebranchdict(web.repo, ctx))
163 branches=webutil.nodebranchdict(web.repo, ctx))
164
164
165 if count >= revcount:
165 if count >= revcount:
166 break
166 break
167
167
168 tip = web.repo['tip']
168 tip = web.repo['tip']
169 parity = paritygen(web.stripecount)
169 parity = paritygen(web.stripecount)
170
170
171 return tmpl('search', query=query, node=tip.hex(),
171 return tmpl('search', query=query, node=tip.hex(),
172 entries=changelist, archives=web.archivelist("tip"),
172 entries=changelist, archives=web.archivelist("tip"),
173 morevars=morevars, lessvars=lessvars)
173 morevars=morevars, lessvars=lessvars)
174
174
175 def changelog(web, req, tmpl, shortlog=False):
175 def changelog(web, req, tmpl, shortlog=False):
176
176
177 if 'node' in req.form:
177 if 'node' in req.form:
178 ctx = webutil.changectx(web.repo, req)
178 ctx = webutil.changectx(web.repo, req)
179 else:
179 else:
180 if 'rev' in req.form:
180 if 'rev' in req.form:
181 hi = req.form['rev'][0]
181 hi = req.form['rev'][0]
182 else:
182 else:
183 hi = len(web.repo) - 1
183 hi = len(web.repo) - 1
184 try:
184 try:
185 ctx = web.repo[hi]
185 ctx = web.repo[hi]
186 except error.RepoError:
186 except error.RepoError:
187 return _search(web, req, tmpl) # XXX redirect to 404 page?
187 return _search(web, req, tmpl) # XXX redirect to 404 page?
188
188
189 def changelist(limit=0, **map):
189 def changelist(limit=0, **map):
190 l = [] # build a list in forward order for efficiency
190 l = [] # build a list in forward order for efficiency
191 for i in xrange(start, end):
191 for i in xrange(start, end):
192 ctx = web.repo[i]
192 ctx = web.repo[i]
193 n = ctx.node()
193 n = ctx.node()
194 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
194 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
195 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
195 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
196
196
197 l.insert(0, {"parity": parity.next(),
197 l.insert(0, {"parity": parity.next(),
198 "author": ctx.user(),
198 "author": ctx.user(),
199 "parent": webutil.parents(ctx, i - 1),
199 "parent": webutil.parents(ctx, i - 1),
200 "child": webutil.children(ctx, i + 1),
200 "child": webutil.children(ctx, i + 1),
201 "changelogtag": showtags,
201 "changelogtag": showtags,
202 "desc": ctx.description(),
202 "desc": ctx.description(),
203 "date": ctx.date(),
203 "date": ctx.date(),
204 "files": files,
204 "files": files,
205 "rev": i,
205 "rev": i,
206 "node": hex(n),
206 "node": hex(n),
207 "tags": webutil.nodetagsdict(web.repo, n),
207 "tags": webutil.nodetagsdict(web.repo, n),
208 "bookmarks": webutil.nodebookmarksdict(web.repo, n),
208 "inbranch": webutil.nodeinbranch(web.repo, ctx),
209 "inbranch": webutil.nodeinbranch(web.repo, ctx),
209 "branches": webutil.nodebranchdict(web.repo, ctx)
210 "branches": webutil.nodebranchdict(web.repo, ctx)
210 })
211 })
211
212
212 if limit > 0:
213 if limit > 0:
213 l = l[:limit]
214 l = l[:limit]
214
215
215 for e in l:
216 for e in l:
216 yield e
217 yield e
217
218
218 revcount = shortlog and web.maxshortchanges or web.maxchanges
219 revcount = shortlog and web.maxshortchanges or web.maxchanges
219 if 'revcount' in req.form:
220 if 'revcount' in req.form:
220 revcount = int(req.form.get('revcount', [revcount])[0])
221 revcount = int(req.form.get('revcount', [revcount])[0])
221 tmpl.defaults['sessionvars']['revcount'] = revcount
222 tmpl.defaults['sessionvars']['revcount'] = revcount
222
223
223 lessvars = copy.copy(tmpl.defaults['sessionvars'])
224 lessvars = copy.copy(tmpl.defaults['sessionvars'])
224 lessvars['revcount'] = revcount / 2
225 lessvars['revcount'] = revcount / 2
225 morevars = copy.copy(tmpl.defaults['sessionvars'])
226 morevars = copy.copy(tmpl.defaults['sessionvars'])
226 morevars['revcount'] = revcount * 2
227 morevars['revcount'] = revcount * 2
227
228
228 count = len(web.repo)
229 count = len(web.repo)
229 pos = ctx.rev()
230 pos = ctx.rev()
230 start = max(0, pos - revcount + 1)
231 start = max(0, pos - revcount + 1)
231 end = min(count, start + revcount)
232 end = min(count, start + revcount)
232 pos = end - 1
233 pos = end - 1
233 parity = paritygen(web.stripecount, offset=start - end)
234 parity = paritygen(web.stripecount, offset=start - end)
234
235
235 changenav = webutil.revnavgen(pos, revcount, count, web.repo.changectx)
236 changenav = webutil.revnavgen(pos, revcount, count, web.repo.changectx)
236
237
237 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
238 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
238 node=hex(ctx.node()), rev=pos, changesets=count,
239 node=hex(ctx.node()), rev=pos, changesets=count,
239 entries=lambda **x: changelist(limit=0,**x),
240 entries=lambda **x: changelist(limit=0,**x),
240 latestentry=lambda **x: changelist(limit=1,**x),
241 latestentry=lambda **x: changelist(limit=1,**x),
241 archives=web.archivelist("tip"), revcount=revcount,
242 archives=web.archivelist("tip"), revcount=revcount,
242 morevars=morevars, lessvars=lessvars)
243 morevars=morevars, lessvars=lessvars)
243
244
244 def shortlog(web, req, tmpl):
245 def shortlog(web, req, tmpl):
245 return changelog(web, req, tmpl, shortlog = True)
246 return changelog(web, req, tmpl, shortlog = True)
246
247
247 def changeset(web, req, tmpl):
248 def changeset(web, req, tmpl):
248 ctx = webutil.changectx(web.repo, req)
249 ctx = webutil.changectx(web.repo, req)
249 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
250 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
251 showbookmarks = webutil.showbookmark(web.repo, tmpl, 'changesetbookmark',
252 ctx.node())
250 showbranch = webutil.nodebranchnodefault(ctx)
253 showbranch = webutil.nodebranchnodefault(ctx)
251
254
252 files = []
255 files = []
253 parity = paritygen(web.stripecount)
256 parity = paritygen(web.stripecount)
254 for f in ctx.files():
257 for f in ctx.files():
255 template = f in ctx and 'filenodelink' or 'filenolink'
258 template = f in ctx and 'filenodelink' or 'filenolink'
256 files.append(tmpl(template,
259 files.append(tmpl(template,
257 node=ctx.hex(), file=f,
260 node=ctx.hex(), file=f,
258 parity=parity.next()))
261 parity=parity.next()))
259
262
260 parity = paritygen(web.stripecount)
263 parity = paritygen(web.stripecount)
261 style = web.config('web', 'style', 'paper')
264 style = web.config('web', 'style', 'paper')
262 if 'style' in req.form:
265 if 'style' in req.form:
263 style = req.form['style'][0]
266 style = req.form['style'][0]
264
267
265 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity, style)
268 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity, style)
266 return tmpl('changeset',
269 return tmpl('changeset',
267 diff=diffs,
270 diff=diffs,
268 rev=ctx.rev(),
271 rev=ctx.rev(),
269 node=ctx.hex(),
272 node=ctx.hex(),
270 parent=webutil.parents(ctx),
273 parent=webutil.parents(ctx),
271 child=webutil.children(ctx),
274 child=webutil.children(ctx),
272 changesettag=showtags,
275 changesettag=showtags,
276 changesetbookmark=showbookmarks,
273 changesetbranch=showbranch,
277 changesetbranch=showbranch,
274 author=ctx.user(),
278 author=ctx.user(),
275 desc=ctx.description(),
279 desc=ctx.description(),
276 date=ctx.date(),
280 date=ctx.date(),
277 files=files,
281 files=files,
278 archives=web.archivelist(ctx.hex()),
282 archives=web.archivelist(ctx.hex()),
279 tags=webutil.nodetagsdict(web.repo, ctx.node()),
283 tags=webutil.nodetagsdict(web.repo, ctx.node()),
284 bookmarks=webutil.nodebookmarksdict(web.repo, ctx.node()),
280 branch=webutil.nodebranchnodefault(ctx),
285 branch=webutil.nodebranchnodefault(ctx),
281 inbranch=webutil.nodeinbranch(web.repo, ctx),
286 inbranch=webutil.nodeinbranch(web.repo, ctx),
282 branches=webutil.nodebranchdict(web.repo, ctx))
287 branches=webutil.nodebranchdict(web.repo, ctx))
283
288
284 rev = changeset
289 rev = changeset
285
290
286 def manifest(web, req, tmpl):
291 def manifest(web, req, tmpl):
287 ctx = webutil.changectx(web.repo, req)
292 ctx = webutil.changectx(web.repo, req)
288 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
293 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
289 mf = ctx.manifest()
294 mf = ctx.manifest()
290 node = ctx.node()
295 node = ctx.node()
291
296
292 files = {}
297 files = {}
293 dirs = {}
298 dirs = {}
294 parity = paritygen(web.stripecount)
299 parity = paritygen(web.stripecount)
295
300
296 if path and path[-1] != "/":
301 if path and path[-1] != "/":
297 path += "/"
302 path += "/"
298 l = len(path)
303 l = len(path)
299 abspath = "/" + path
304 abspath = "/" + path
300
305
301 for f, n in mf.iteritems():
306 for f, n in mf.iteritems():
302 if f[:l] != path:
307 if f[:l] != path:
303 continue
308 continue
304 remain = f[l:]
309 remain = f[l:]
305 elements = remain.split('/')
310 elements = remain.split('/')
306 if len(elements) == 1:
311 if len(elements) == 1:
307 files[remain] = f
312 files[remain] = f
308 else:
313 else:
309 h = dirs # need to retain ref to dirs (root)
314 h = dirs # need to retain ref to dirs (root)
310 for elem in elements[0:-1]:
315 for elem in elements[0:-1]:
311 if elem not in h:
316 if elem not in h:
312 h[elem] = {}
317 h[elem] = {}
313 h = h[elem]
318 h = h[elem]
314 if len(h) > 1:
319 if len(h) > 1:
315 break
320 break
316 h[None] = None # denotes files present
321 h[None] = None # denotes files present
317
322
318 if mf and not files and not dirs:
323 if mf and not files and not dirs:
319 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
324 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
320
325
321 def filelist(**map):
326 def filelist(**map):
322 for f in sorted(files):
327 for f in sorted(files):
323 full = files[f]
328 full = files[f]
324
329
325 fctx = ctx.filectx(full)
330 fctx = ctx.filectx(full)
326 yield {"file": full,
331 yield {"file": full,
327 "parity": parity.next(),
332 "parity": parity.next(),
328 "basename": f,
333 "basename": f,
329 "date": fctx.date(),
334 "date": fctx.date(),
330 "size": fctx.size(),
335 "size": fctx.size(),
331 "permissions": mf.flags(full)}
336 "permissions": mf.flags(full)}
332
337
333 def dirlist(**map):
338 def dirlist(**map):
334 for d in sorted(dirs):
339 for d in sorted(dirs):
335
340
336 emptydirs = []
341 emptydirs = []
337 h = dirs[d]
342 h = dirs[d]
338 while isinstance(h, dict) and len(h) == 1:
343 while isinstance(h, dict) and len(h) == 1:
339 k, v = h.items()[0]
344 k, v = h.items()[0]
340 if v:
345 if v:
341 emptydirs.append(k)
346 emptydirs.append(k)
342 h = v
347 h = v
343
348
344 path = "%s%s" % (abspath, d)
349 path = "%s%s" % (abspath, d)
345 yield {"parity": parity.next(),
350 yield {"parity": parity.next(),
346 "path": path,
351 "path": path,
347 "emptydirs": "/".join(emptydirs),
352 "emptydirs": "/".join(emptydirs),
348 "basename": d}
353 "basename": d}
349
354
350 return tmpl("manifest",
355 return tmpl("manifest",
351 rev=ctx.rev(),
356 rev=ctx.rev(),
352 node=hex(node),
357 node=hex(node),
353 path=abspath,
358 path=abspath,
354 up=webutil.up(abspath),
359 up=webutil.up(abspath),
355 upparity=parity.next(),
360 upparity=parity.next(),
356 fentries=filelist,
361 fentries=filelist,
357 dentries=dirlist,
362 dentries=dirlist,
358 archives=web.archivelist(hex(node)),
363 archives=web.archivelist(hex(node)),
359 tags=webutil.nodetagsdict(web.repo, node),
364 tags=webutil.nodetagsdict(web.repo, node),
360 inbranch=webutil.nodeinbranch(web.repo, ctx),
365 inbranch=webutil.nodeinbranch(web.repo, ctx),
361 branches=webutil.nodebranchdict(web.repo, ctx))
366 branches=webutil.nodebranchdict(web.repo, ctx))
362
367
363 def tags(web, req, tmpl):
368 def tags(web, req, tmpl):
364 i = web.repo.tagslist()
369 i = web.repo.tagslist()
365 i.reverse()
370 i.reverse()
366 parity = paritygen(web.stripecount)
371 parity = paritygen(web.stripecount)
367
372
368 def entries(notip=False, limit=0, **map):
373 def entries(notip=False, limit=0, **map):
369 count = 0
374 count = 0
370 for k, n in i:
375 for k, n in i:
371 if notip and k == "tip":
376 if notip and k == "tip":
372 continue
377 continue
373 if limit > 0 and count >= limit:
378 if limit > 0 and count >= limit:
374 continue
379 continue
375 count = count + 1
380 count = count + 1
376 yield {"parity": parity.next(),
381 yield {"parity": parity.next(),
377 "tag": k,
382 "tag": k,
378 "date": web.repo[n].date(),
383 "date": web.repo[n].date(),
379 "node": hex(n)}
384 "node": hex(n)}
380
385
381 return tmpl("tags",
386 return tmpl("tags",
382 node=hex(web.repo.changelog.tip()),
387 node=hex(web.repo.changelog.tip()),
383 entries=lambda **x: entries(False, 0, **x),
388 entries=lambda **x: entries(False, 0, **x),
384 entriesnotip=lambda **x: entries(True, 0, **x),
389 entriesnotip=lambda **x: entries(True, 0, **x),
385 latestentry=lambda **x: entries(True, 1, **x))
390 latestentry=lambda **x: entries(True, 1, **x))
386
391
387 def branches(web, req, tmpl):
392 def branches(web, req, tmpl):
388 tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems())
393 tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems())
389 heads = web.repo.heads()
394 heads = web.repo.heads()
390 parity = paritygen(web.stripecount)
395 parity = paritygen(web.stripecount)
391 sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev())
396 sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev())
392
397
393 def entries(limit, **map):
398 def entries(limit, **map):
394 count = 0
399 count = 0
395 for ctx in sorted(tips, key=sortkey, reverse=True):
400 for ctx in sorted(tips, key=sortkey, reverse=True):
396 if limit > 0 and count >= limit:
401 if limit > 0 and count >= limit:
397 return
402 return
398 count += 1
403 count += 1
399 if ctx.node() not in heads:
404 if ctx.node() not in heads:
400 status = 'inactive'
405 status = 'inactive'
401 elif not web.repo.branchheads(ctx.branch()):
406 elif not web.repo.branchheads(ctx.branch()):
402 status = 'closed'
407 status = 'closed'
403 else:
408 else:
404 status = 'open'
409 status = 'open'
405 yield {'parity': parity.next(),
410 yield {'parity': parity.next(),
406 'branch': ctx.branch(),
411 'branch': ctx.branch(),
407 'status': status,
412 'status': status,
408 'node': ctx.hex(),
413 'node': ctx.hex(),
409 'date': ctx.date()}
414 'date': ctx.date()}
410
415
411 return tmpl('branches', node=hex(web.repo.changelog.tip()),
416 return tmpl('branches', node=hex(web.repo.changelog.tip()),
412 entries=lambda **x: entries(0, **x),
417 entries=lambda **x: entries(0, **x),
413 latestentry=lambda **x: entries(1, **x))
418 latestentry=lambda **x: entries(1, **x))
414
419
415 def summary(web, req, tmpl):
420 def summary(web, req, tmpl):
416 i = web.repo.tagslist()
421 i = web.repo.tagslist()
417 i.reverse()
422 i.reverse()
418
423
419 def tagentries(**map):
424 def tagentries(**map):
420 parity = paritygen(web.stripecount)
425 parity = paritygen(web.stripecount)
421 count = 0
426 count = 0
422 for k, n in i:
427 for k, n in i:
423 if k == "tip": # skip tip
428 if k == "tip": # skip tip
424 continue
429 continue
425
430
426 count += 1
431 count += 1
427 if count > 10: # limit to 10 tags
432 if count > 10: # limit to 10 tags
428 break
433 break
429
434
430 yield tmpl("tagentry",
435 yield tmpl("tagentry",
431 parity=parity.next(),
436 parity=parity.next(),
432 tag=k,
437 tag=k,
433 node=hex(n),
438 node=hex(n),
434 date=web.repo[n].date())
439 date=web.repo[n].date())
435
440
436 def branches(**map):
441 def branches(**map):
437 parity = paritygen(web.stripecount)
442 parity = paritygen(web.stripecount)
438
443
439 b = web.repo.branchtags()
444 b = web.repo.branchtags()
440 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
445 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
441 for r, n, t in sorted(l):
446 for r, n, t in sorted(l):
442 yield {'parity': parity.next(),
447 yield {'parity': parity.next(),
443 'branch': t,
448 'branch': t,
444 'node': hex(n),
449 'node': hex(n),
445 'date': web.repo[n].date()}
450 'date': web.repo[n].date()}
446
451
447 def changelist(**map):
452 def changelist(**map):
448 parity = paritygen(web.stripecount, offset=start - end)
453 parity = paritygen(web.stripecount, offset=start - end)
449 l = [] # build a list in forward order for efficiency
454 l = [] # build a list in forward order for efficiency
450 for i in xrange(start, end):
455 for i in xrange(start, end):
451 ctx = web.repo[i]
456 ctx = web.repo[i]
452 n = ctx.node()
457 n = ctx.node()
453 hn = hex(n)
458 hn = hex(n)
454
459
455 l.insert(0, tmpl(
460 l.insert(0, tmpl(
456 'shortlogentry',
461 'shortlogentry',
457 parity=parity.next(),
462 parity=parity.next(),
458 author=ctx.user(),
463 author=ctx.user(),
459 desc=ctx.description(),
464 desc=ctx.description(),
460 date=ctx.date(),
465 date=ctx.date(),
461 rev=i,
466 rev=i,
462 node=hn,
467 node=hn,
463 tags=webutil.nodetagsdict(web.repo, n),
468 tags=webutil.nodetagsdict(web.repo, n),
464 inbranch=webutil.nodeinbranch(web.repo, ctx),
469 inbranch=webutil.nodeinbranch(web.repo, ctx),
465 branches=webutil.nodebranchdict(web.repo, ctx)))
470 branches=webutil.nodebranchdict(web.repo, ctx)))
466
471
467 yield l
472 yield l
468
473
469 tip = web.repo['tip']
474 tip = web.repo['tip']
470 count = len(web.repo)
475 count = len(web.repo)
471 start = max(0, count - web.maxchanges)
476 start = max(0, count - web.maxchanges)
472 end = min(count, start + web.maxchanges)
477 end = min(count, start + web.maxchanges)
473
478
474 return tmpl("summary",
479 return tmpl("summary",
475 desc=web.config("web", "description", "unknown"),
480 desc=web.config("web", "description", "unknown"),
476 owner=get_contact(web.config) or "unknown",
481 owner=get_contact(web.config) or "unknown",
477 lastchange=tip.date(),
482 lastchange=tip.date(),
478 tags=tagentries,
483 tags=tagentries,
479 branches=branches,
484 branches=branches,
480 shortlog=changelist,
485 shortlog=changelist,
481 node=tip.hex(),
486 node=tip.hex(),
482 archives=web.archivelist("tip"))
487 archives=web.archivelist("tip"))
483
488
484 def filediff(web, req, tmpl):
489 def filediff(web, req, tmpl):
485 fctx, ctx = None, None
490 fctx, ctx = None, None
486 try:
491 try:
487 fctx = webutil.filectx(web.repo, req)
492 fctx = webutil.filectx(web.repo, req)
488 except LookupError:
493 except LookupError:
489 ctx = webutil.changectx(web.repo, req)
494 ctx = webutil.changectx(web.repo, req)
490 path = webutil.cleanpath(web.repo, req.form['file'][0])
495 path = webutil.cleanpath(web.repo, req.form['file'][0])
491 if path not in ctx.files():
496 if path not in ctx.files():
492 raise
497 raise
493
498
494 if fctx is not None:
499 if fctx is not None:
495 n = fctx.node()
500 n = fctx.node()
496 path = fctx.path()
501 path = fctx.path()
497 else:
502 else:
498 n = ctx.node()
503 n = ctx.node()
499 # path already defined in except clause
504 # path already defined in except clause
500
505
501 parity = paritygen(web.stripecount)
506 parity = paritygen(web.stripecount)
502 style = web.config('web', 'style', 'paper')
507 style = web.config('web', 'style', 'paper')
503 if 'style' in req.form:
508 if 'style' in req.form:
504 style = req.form['style'][0]
509 style = req.form['style'][0]
505
510
506 diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity, style)
511 diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity, style)
507 rename = fctx and webutil.renamelink(fctx) or []
512 rename = fctx and webutil.renamelink(fctx) or []
508 ctx = fctx and fctx or ctx
513 ctx = fctx and fctx or ctx
509 return tmpl("filediff",
514 return tmpl("filediff",
510 file=path,
515 file=path,
511 node=hex(n),
516 node=hex(n),
512 rev=ctx.rev(),
517 rev=ctx.rev(),
513 date=ctx.date(),
518 date=ctx.date(),
514 desc=ctx.description(),
519 desc=ctx.description(),
515 author=ctx.user(),
520 author=ctx.user(),
516 rename=rename,
521 rename=rename,
517 branch=webutil.nodebranchnodefault(ctx),
522 branch=webutil.nodebranchnodefault(ctx),
518 parent=webutil.parents(ctx),
523 parent=webutil.parents(ctx),
519 child=webutil.children(ctx),
524 child=webutil.children(ctx),
520 diff=diffs)
525 diff=diffs)
521
526
522 diff = filediff
527 diff = filediff
523
528
524 def annotate(web, req, tmpl):
529 def annotate(web, req, tmpl):
525 fctx = webutil.filectx(web.repo, req)
530 fctx = webutil.filectx(web.repo, req)
526 f = fctx.path()
531 f = fctx.path()
527 parity = paritygen(web.stripecount)
532 parity = paritygen(web.stripecount)
528
533
529 def annotate(**map):
534 def annotate(**map):
530 last = None
535 last = None
531 if binary(fctx.data()):
536 if binary(fctx.data()):
532 mt = (mimetypes.guess_type(fctx.path())[0]
537 mt = (mimetypes.guess_type(fctx.path())[0]
533 or 'application/octet-stream')
538 or 'application/octet-stream')
534 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
539 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
535 '(binary:%s)' % mt)])
540 '(binary:%s)' % mt)])
536 else:
541 else:
537 lines = enumerate(fctx.annotate(follow=True, linenumber=True))
542 lines = enumerate(fctx.annotate(follow=True, linenumber=True))
538 for lineno, ((f, targetline), l) in lines:
543 for lineno, ((f, targetline), l) in lines:
539 fnode = f.filenode()
544 fnode = f.filenode()
540
545
541 if last != fnode:
546 if last != fnode:
542 last = fnode
547 last = fnode
543
548
544 yield {"parity": parity.next(),
549 yield {"parity": parity.next(),
545 "node": hex(f.node()),
550 "node": hex(f.node()),
546 "rev": f.rev(),
551 "rev": f.rev(),
547 "author": f.user(),
552 "author": f.user(),
548 "desc": f.description(),
553 "desc": f.description(),
549 "file": f.path(),
554 "file": f.path(),
550 "targetline": targetline,
555 "targetline": targetline,
551 "line": l,
556 "line": l,
552 "lineid": "l%d" % (lineno + 1),
557 "lineid": "l%d" % (lineno + 1),
553 "linenumber": "% 6d" % (lineno + 1),
558 "linenumber": "% 6d" % (lineno + 1),
554 "revdate": f.date()}
559 "revdate": f.date()}
555
560
556 return tmpl("fileannotate",
561 return tmpl("fileannotate",
557 file=f,
562 file=f,
558 annotate=annotate,
563 annotate=annotate,
559 path=webutil.up(f),
564 path=webutil.up(f),
560 rev=fctx.rev(),
565 rev=fctx.rev(),
561 node=hex(fctx.node()),
566 node=hex(fctx.node()),
562 author=fctx.user(),
567 author=fctx.user(),
563 date=fctx.date(),
568 date=fctx.date(),
564 desc=fctx.description(),
569 desc=fctx.description(),
565 rename=webutil.renamelink(fctx),
570 rename=webutil.renamelink(fctx),
566 branch=webutil.nodebranchnodefault(fctx),
571 branch=webutil.nodebranchnodefault(fctx),
567 parent=webutil.parents(fctx),
572 parent=webutil.parents(fctx),
568 child=webutil.children(fctx),
573 child=webutil.children(fctx),
569 permissions=fctx.manifest().flags(f))
574 permissions=fctx.manifest().flags(f))
570
575
571 def filelog(web, req, tmpl):
576 def filelog(web, req, tmpl):
572
577
573 try:
578 try:
574 fctx = webutil.filectx(web.repo, req)
579 fctx = webutil.filectx(web.repo, req)
575 f = fctx.path()
580 f = fctx.path()
576 fl = fctx.filelog()
581 fl = fctx.filelog()
577 except error.LookupError:
582 except error.LookupError:
578 f = webutil.cleanpath(web.repo, req.form['file'][0])
583 f = webutil.cleanpath(web.repo, req.form['file'][0])
579 fl = web.repo.file(f)
584 fl = web.repo.file(f)
580 numrevs = len(fl)
585 numrevs = len(fl)
581 if not numrevs: # file doesn't exist at all
586 if not numrevs: # file doesn't exist at all
582 raise
587 raise
583 rev = webutil.changectx(web.repo, req).rev()
588 rev = webutil.changectx(web.repo, req).rev()
584 first = fl.linkrev(0)
589 first = fl.linkrev(0)
585 if rev < first: # current rev is from before file existed
590 if rev < first: # current rev is from before file existed
586 raise
591 raise
587 frev = numrevs - 1
592 frev = numrevs - 1
588 while fl.linkrev(frev) > rev:
593 while fl.linkrev(frev) > rev:
589 frev -= 1
594 frev -= 1
590 fctx = web.repo.filectx(f, fl.linkrev(frev))
595 fctx = web.repo.filectx(f, fl.linkrev(frev))
591
596
592 revcount = web.maxshortchanges
597 revcount = web.maxshortchanges
593 if 'revcount' in req.form:
598 if 'revcount' in req.form:
594 revcount = int(req.form.get('revcount', [revcount])[0])
599 revcount = int(req.form.get('revcount', [revcount])[0])
595 tmpl.defaults['sessionvars']['revcount'] = revcount
600 tmpl.defaults['sessionvars']['revcount'] = revcount
596
601
597 lessvars = copy.copy(tmpl.defaults['sessionvars'])
602 lessvars = copy.copy(tmpl.defaults['sessionvars'])
598 lessvars['revcount'] = revcount / 2
603 lessvars['revcount'] = revcount / 2
599 morevars = copy.copy(tmpl.defaults['sessionvars'])
604 morevars = copy.copy(tmpl.defaults['sessionvars'])
600 morevars['revcount'] = revcount * 2
605 morevars['revcount'] = revcount * 2
601
606
602 count = fctx.filerev() + 1
607 count = fctx.filerev() + 1
603 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
608 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
604 end = min(count, start + revcount) # last rev on this page
609 end = min(count, start + revcount) # last rev on this page
605 parity = paritygen(web.stripecount, offset=start - end)
610 parity = paritygen(web.stripecount, offset=start - end)
606
611
607 def entries(limit=0, **map):
612 def entries(limit=0, **map):
608 l = []
613 l = []
609
614
610 repo = web.repo
615 repo = web.repo
611 for i in xrange(start, end):
616 for i in xrange(start, end):
612 iterfctx = fctx.filectx(i)
617 iterfctx = fctx.filectx(i)
613
618
614 l.insert(0, {"parity": parity.next(),
619 l.insert(0, {"parity": parity.next(),
615 "filerev": i,
620 "filerev": i,
616 "file": f,
621 "file": f,
617 "node": hex(iterfctx.node()),
622 "node": hex(iterfctx.node()),
618 "author": iterfctx.user(),
623 "author": iterfctx.user(),
619 "date": iterfctx.date(),
624 "date": iterfctx.date(),
620 "rename": webutil.renamelink(iterfctx),
625 "rename": webutil.renamelink(iterfctx),
621 "parent": webutil.parents(iterfctx),
626 "parent": webutil.parents(iterfctx),
622 "child": webutil.children(iterfctx),
627 "child": webutil.children(iterfctx),
623 "desc": iterfctx.description(),
628 "desc": iterfctx.description(),
624 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
629 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
625 "branch": webutil.nodebranchnodefault(iterfctx),
630 "branch": webutil.nodebranchnodefault(iterfctx),
626 "inbranch": webutil.nodeinbranch(repo, iterfctx),
631 "inbranch": webutil.nodeinbranch(repo, iterfctx),
627 "branches": webutil.nodebranchdict(repo, iterfctx)})
632 "branches": webutil.nodebranchdict(repo, iterfctx)})
628
633
629 if limit > 0:
634 if limit > 0:
630 l = l[:limit]
635 l = l[:limit]
631
636
632 for e in l:
637 for e in l:
633 yield e
638 yield e
634
639
635 nodefunc = lambda x: fctx.filectx(fileid=x)
640 nodefunc = lambda x: fctx.filectx(fileid=x)
636 nav = webutil.revnavgen(end - 1, revcount, count, nodefunc)
641 nav = webutil.revnavgen(end - 1, revcount, count, nodefunc)
637 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
642 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
638 entries=lambda **x: entries(limit=0, **x),
643 entries=lambda **x: entries(limit=0, **x),
639 latestentry=lambda **x: entries(limit=1, **x),
644 latestentry=lambda **x: entries(limit=1, **x),
640 revcount=revcount, morevars=morevars, lessvars=lessvars)
645 revcount=revcount, morevars=morevars, lessvars=lessvars)
641
646
642 def archive(web, req, tmpl):
647 def archive(web, req, tmpl):
643 type_ = req.form.get('type', [None])[0]
648 type_ = req.form.get('type', [None])[0]
644 allowed = web.configlist("web", "allow_archive")
649 allowed = web.configlist("web", "allow_archive")
645 key = req.form['node'][0]
650 key = req.form['node'][0]
646
651
647 if type_ not in web.archives:
652 if type_ not in web.archives:
648 msg = 'Unsupported archive type: %s' % type_
653 msg = 'Unsupported archive type: %s' % type_
649 raise ErrorResponse(HTTP_NOT_FOUND, msg)
654 raise ErrorResponse(HTTP_NOT_FOUND, msg)
650
655
651 if not ((type_ in allowed or
656 if not ((type_ in allowed or
652 web.configbool("web", "allow" + type_, False))):
657 web.configbool("web", "allow" + type_, False))):
653 msg = 'Archive type not allowed: %s' % type_
658 msg = 'Archive type not allowed: %s' % type_
654 raise ErrorResponse(HTTP_FORBIDDEN, msg)
659 raise ErrorResponse(HTTP_FORBIDDEN, msg)
655
660
656 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
661 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
657 cnode = web.repo.lookup(key)
662 cnode = web.repo.lookup(key)
658 arch_version = key
663 arch_version = key
659 if cnode == key or key == 'tip':
664 if cnode == key or key == 'tip':
660 arch_version = short(cnode)
665 arch_version = short(cnode)
661 name = "%s-%s" % (reponame, arch_version)
666 name = "%s-%s" % (reponame, arch_version)
662 mimetype, artype, extension, encoding = web.archive_specs[type_]
667 mimetype, artype, extension, encoding = web.archive_specs[type_]
663 headers = [
668 headers = [
664 ('Content-Type', mimetype),
669 ('Content-Type', mimetype),
665 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
670 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
666 ]
671 ]
667 if encoding:
672 if encoding:
668 headers.append(('Content-Encoding', encoding))
673 headers.append(('Content-Encoding', encoding))
669 req.header(headers)
674 req.header(headers)
670 req.respond(HTTP_OK)
675 req.respond(HTTP_OK)
671 archival.archive(web.repo, req, cnode, artype, prefix=name)
676 archival.archive(web.repo, req, cnode, artype, prefix=name)
672 return []
677 return []
673
678
674
679
675 def static(web, req, tmpl):
680 def static(web, req, tmpl):
676 fname = req.form['file'][0]
681 fname = req.form['file'][0]
677 # a repo owner may set web.static in .hg/hgrc to get any file
682 # a repo owner may set web.static in .hg/hgrc to get any file
678 # readable by the user running the CGI script
683 # readable by the user running the CGI script
679 static = web.config("web", "static", None, untrusted=False)
684 static = web.config("web", "static", None, untrusted=False)
680 if not static:
685 if not static:
681 tp = web.templatepath or templater.templatepath()
686 tp = web.templatepath or templater.templatepath()
682 if isinstance(tp, str):
687 if isinstance(tp, str):
683 tp = [tp]
688 tp = [tp]
684 static = [os.path.join(p, 'static') for p in tp]
689 static = [os.path.join(p, 'static') for p in tp]
685 return [staticfile(static, fname, req)]
690 return [staticfile(static, fname, req)]
686
691
687 def graph(web, req, tmpl):
692 def graph(web, req, tmpl):
688
693
689 rev = webutil.changectx(web.repo, req).rev()
694 rev = webutil.changectx(web.repo, req).rev()
690 bg_height = 39
695 bg_height = 39
691 revcount = web.maxshortchanges
696 revcount = web.maxshortchanges
692 if 'revcount' in req.form:
697 if 'revcount' in req.form:
693 revcount = int(req.form.get('revcount', [revcount])[0])
698 revcount = int(req.form.get('revcount', [revcount])[0])
694 tmpl.defaults['sessionvars']['revcount'] = revcount
699 tmpl.defaults['sessionvars']['revcount'] = revcount
695
700
696 lessvars = copy.copy(tmpl.defaults['sessionvars'])
701 lessvars = copy.copy(tmpl.defaults['sessionvars'])
697 lessvars['revcount'] = revcount / 2
702 lessvars['revcount'] = revcount / 2
698 morevars = copy.copy(tmpl.defaults['sessionvars'])
703 morevars = copy.copy(tmpl.defaults['sessionvars'])
699 morevars['revcount'] = revcount * 2
704 morevars['revcount'] = revcount * 2
700
705
701 max_rev = len(web.repo) - 1
706 max_rev = len(web.repo) - 1
702 revcount = min(max_rev, revcount)
707 revcount = min(max_rev, revcount)
703 revnode = web.repo.changelog.node(rev)
708 revnode = web.repo.changelog.node(rev)
704 revnode_hex = hex(revnode)
709 revnode_hex = hex(revnode)
705 uprev = min(max_rev, rev + revcount)
710 uprev = min(max_rev, rev + revcount)
706 downrev = max(0, rev - revcount)
711 downrev = max(0, rev - revcount)
707 count = len(web.repo)
712 count = len(web.repo)
708 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
713 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
709
714
710 dag = graphmod.revisions(web.repo, rev, downrev)
715 dag = graphmod.revisions(web.repo, rev, downrev)
711 tree = list(graphmod.colored(dag))
716 tree = list(graphmod.colored(dag))
712 canvasheight = (len(tree) + 1) * bg_height - 27
717 canvasheight = (len(tree) + 1) * bg_height - 27
713 data = []
718 data = []
714 for (id, type, ctx, vtx, edges) in tree:
719 for (id, type, ctx, vtx, edges) in tree:
715 if type != graphmod.CHANGESET:
720 if type != graphmod.CHANGESET:
716 continue
721 continue
717 node = short(ctx.node())
722 node = short(ctx.node())
718 age = templatefilters.age(ctx.date())
723 age = templatefilters.age(ctx.date())
719 desc = templatefilters.firstline(ctx.description())
724 desc = templatefilters.firstline(ctx.description())
720 desc = cgi.escape(templatefilters.nonempty(desc))
725 desc = cgi.escape(templatefilters.nonempty(desc))
721 user = cgi.escape(templatefilters.person(ctx.user()))
726 user = cgi.escape(templatefilters.person(ctx.user()))
722 branch = ctx.branch()
727 branch = ctx.branch()
723 branch = branch, web.repo.branchtags().get(branch) == ctx.node()
728 branch = branch, web.repo.branchtags().get(branch) == ctx.node()
724 data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
729 data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(), ctx.bookmarks()))
725
730
726 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
731 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
727 lessvars=lessvars, morevars=morevars, downrev=downrev,
732 lessvars=lessvars, morevars=morevars, downrev=downrev,
728 canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
733 canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
729 node=revnode_hex, changenav=changenav)
734 node=revnode_hex, changenav=changenav)
730
735
731 def _getdoc(e):
736 def _getdoc(e):
732 doc = e[0].__doc__
737 doc = e[0].__doc__
733 if doc:
738 if doc:
734 doc = doc.split('\n')[0]
739 doc = doc.split('\n')[0]
735 else:
740 else:
736 doc = _('(no help text available)')
741 doc = _('(no help text available)')
737 return doc
742 return doc
738
743
739 def help(web, req, tmpl):
744 def help(web, req, tmpl):
740 from mercurial import commands # avoid cycle
745 from mercurial import commands # avoid cycle
741
746
742 topicname = req.form.get('node', [None])[0]
747 topicname = req.form.get('node', [None])[0]
743 if not topicname:
748 if not topicname:
744 topic = []
749 topic = []
745
750
746 def topics(**map):
751 def topics(**map):
747 for entries, summary, _ in helpmod.helptable:
752 for entries, summary, _ in helpmod.helptable:
748 entries = sorted(entries, key=len)
753 entries = sorted(entries, key=len)
749 yield {'topic': entries[-1], 'summary': summary}
754 yield {'topic': entries[-1], 'summary': summary}
750
755
751 early, other = [], []
756 early, other = [], []
752 primary = lambda s: s.split('|')[0]
757 primary = lambda s: s.split('|')[0]
753 for c, e in commands.table.iteritems():
758 for c, e in commands.table.iteritems():
754 doc = _getdoc(e)
759 doc = _getdoc(e)
755 if 'DEPRECATED' in doc or c.startswith('debug'):
760 if 'DEPRECATED' in doc or c.startswith('debug'):
756 continue
761 continue
757 cmd = primary(c)
762 cmd = primary(c)
758 if cmd.startswith('^'):
763 if cmd.startswith('^'):
759 early.append((cmd[1:], doc))
764 early.append((cmd[1:], doc))
760 else:
765 else:
761 other.append((cmd, doc))
766 other.append((cmd, doc))
762
767
763 early.sort()
768 early.sort()
764 other.sort()
769 other.sort()
765
770
766 def earlycommands(**map):
771 def earlycommands(**map):
767 for c, doc in early:
772 for c, doc in early:
768 yield {'topic': c, 'summary': doc}
773 yield {'topic': c, 'summary': doc}
769
774
770 def othercommands(**map):
775 def othercommands(**map):
771 for c, doc in other:
776 for c, doc in other:
772 yield {'topic': c, 'summary': doc}
777 yield {'topic': c, 'summary': doc}
773
778
774 return tmpl('helptopics', topics=topics, earlycommands=earlycommands,
779 return tmpl('helptopics', topics=topics, earlycommands=earlycommands,
775 othercommands=othercommands, title='Index')
780 othercommands=othercommands, title='Index')
776
781
777 u = webutil.wsgiui()
782 u = webutil.wsgiui()
778 u.pushbuffer()
783 u.pushbuffer()
779 try:
784 try:
780 commands.help_(u, topicname)
785 commands.help_(u, topicname)
781 except error.UnknownCommand:
786 except error.UnknownCommand:
782 raise ErrorResponse(HTTP_NOT_FOUND)
787 raise ErrorResponse(HTTP_NOT_FOUND)
783 doc = u.popbuffer()
788 doc = u.popbuffer()
784 return tmpl('help', topic=topicname, doc=doc)
789 return tmpl('help', topic=topicname, doc=doc)
@@ -1,226 +1,233 b''
1 # hgweb/webutil.py - utility library for the web interface.
1 # hgweb/webutil.py - utility library for the web interface.
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-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 import os, copy
9 import os, copy
10 from mercurial import match, patch, util, error, ui
10 from mercurial import match, patch, util, error, ui
11 from mercurial.node import hex, nullid
11 from mercurial.node import hex, nullid
12
12
13 def up(p):
13 def up(p):
14 if p[0] != "/":
14 if p[0] != "/":
15 p = "/" + p
15 p = "/" + p
16 if p[-1] == "/":
16 if p[-1] == "/":
17 p = p[:-1]
17 p = p[:-1]
18 up = os.path.dirname(p)
18 up = os.path.dirname(p)
19 if up == "/":
19 if up == "/":
20 return "/"
20 return "/"
21 return up + "/"
21 return up + "/"
22
22
23 def revnavgen(pos, pagelen, limit, nodefunc):
23 def revnavgen(pos, pagelen, limit, nodefunc):
24 def seq(factor, limit=None):
24 def seq(factor, limit=None):
25 if limit:
25 if limit:
26 yield limit
26 yield limit
27 if limit >= 20 and limit <= 40:
27 if limit >= 20 and limit <= 40:
28 yield 50
28 yield 50
29 else:
29 else:
30 yield 1 * factor
30 yield 1 * factor
31 yield 3 * factor
31 yield 3 * factor
32 for f in seq(factor * 10):
32 for f in seq(factor * 10):
33 yield f
33 yield f
34
34
35 navbefore = []
35 navbefore = []
36 navafter = []
36 navafter = []
37
37
38 last = 0
38 last = 0
39 for f in seq(1, pagelen):
39 for f in seq(1, pagelen):
40 if f < pagelen or f <= last:
40 if f < pagelen or f <= last:
41 continue
41 continue
42 if f > limit:
42 if f > limit:
43 break
43 break
44 last = f
44 last = f
45 if pos + f < limit:
45 if pos + f < limit:
46 navafter.append(("+%d" % f, hex(nodefunc(pos + f).node())))
46 navafter.append(("+%d" % f, hex(nodefunc(pos + f).node())))
47 if pos - f >= 0:
47 if pos - f >= 0:
48 navbefore.insert(0, ("-%d" % f, hex(nodefunc(pos - f).node())))
48 navbefore.insert(0, ("-%d" % f, hex(nodefunc(pos - f).node())))
49
49
50 navafter.append(("tip", "tip"))
50 navafter.append(("tip", "tip"))
51 try:
51 try:
52 navbefore.insert(0, ("(0)", hex(nodefunc('0').node())))
52 navbefore.insert(0, ("(0)", hex(nodefunc('0').node())))
53 except error.RepoError:
53 except error.RepoError:
54 pass
54 pass
55
55
56 def gen(l):
56 def gen(l):
57 def f(**map):
57 def f(**map):
58 for label, node in l:
58 for label, node in l:
59 yield {"label": label, "node": node}
59 yield {"label": label, "node": node}
60 return f
60 return f
61
61
62 return (dict(before=gen(navbefore), after=gen(navafter)),)
62 return (dict(before=gen(navbefore), after=gen(navafter)),)
63
63
64 def _siblings(siblings=[], hiderev=None):
64 def _siblings(siblings=[], hiderev=None):
65 siblings = [s for s in siblings if s.node() != nullid]
65 siblings = [s for s in siblings if s.node() != nullid]
66 if len(siblings) == 1 and siblings[0].rev() == hiderev:
66 if len(siblings) == 1 and siblings[0].rev() == hiderev:
67 return
67 return
68 for s in siblings:
68 for s in siblings:
69 d = {'node': hex(s.node()), 'rev': s.rev()}
69 d = {'node': hex(s.node()), 'rev': s.rev()}
70 d['user'] = s.user()
70 d['user'] = s.user()
71 d['date'] = s.date()
71 d['date'] = s.date()
72 d['description'] = s.description()
72 d['description'] = s.description()
73 d['branch'] = s.branch()
73 d['branch'] = s.branch()
74 if hasattr(s, 'path'):
74 if hasattr(s, 'path'):
75 d['file'] = s.path()
75 d['file'] = s.path()
76 yield d
76 yield d
77
77
78 def parents(ctx, hide=None):
78 def parents(ctx, hide=None):
79 return _siblings(ctx.parents(), hide)
79 return _siblings(ctx.parents(), hide)
80
80
81 def children(ctx, hide=None):
81 def children(ctx, hide=None):
82 return _siblings(ctx.children(), hide)
82 return _siblings(ctx.children(), hide)
83
83
84 def renamelink(fctx):
84 def renamelink(fctx):
85 r = fctx.renamed()
85 r = fctx.renamed()
86 if r:
86 if r:
87 return [dict(file=r[0], node=hex(r[1]))]
87 return [dict(file=r[0], node=hex(r[1]))]
88 return []
88 return []
89
89
90 def nodetagsdict(repo, node):
90 def nodetagsdict(repo, node):
91 return [{"name": i} for i in repo.nodetags(node)]
91 return [{"name": i} for i in repo.nodetags(node)]
92
92
93 def nodebookmarksdict(repo, node):
94 return [{"name": i} for i in repo.nodebookmarks(node)]
95
93 def nodebranchdict(repo, ctx):
96 def nodebranchdict(repo, ctx):
94 branches = []
97 branches = []
95 branch = ctx.branch()
98 branch = ctx.branch()
96 # If this is an empty repo, ctx.node() == nullid,
99 # If this is an empty repo, ctx.node() == nullid,
97 # ctx.branch() == 'default', but branchtags() is
100 # ctx.branch() == 'default', but branchtags() is
98 # an empty dict. Using dict.get avoids a traceback.
101 # an empty dict. Using dict.get avoids a traceback.
99 if repo.branchtags().get(branch) == ctx.node():
102 if repo.branchtags().get(branch) == ctx.node():
100 branches.append({"name": branch})
103 branches.append({"name": branch})
101 return branches
104 return branches
102
105
103 def nodeinbranch(repo, ctx):
106 def nodeinbranch(repo, ctx):
104 branches = []
107 branches = []
105 branch = ctx.branch()
108 branch = ctx.branch()
106 if branch != 'default' and repo.branchtags().get(branch) != ctx.node():
109 if branch != 'default' and repo.branchtags().get(branch) != ctx.node():
107 branches.append({"name": branch})
110 branches.append({"name": branch})
108 return branches
111 return branches
109
112
110 def nodebranchnodefault(ctx):
113 def nodebranchnodefault(ctx):
111 branches = []
114 branches = []
112 branch = ctx.branch()
115 branch = ctx.branch()
113 if branch != 'default':
116 if branch != 'default':
114 branches.append({"name": branch})
117 branches.append({"name": branch})
115 return branches
118 return branches
116
119
117 def showtag(repo, tmpl, t1, node=nullid, **args):
120 def showtag(repo, tmpl, t1, node=nullid, **args):
118 for t in repo.nodetags(node):
121 for t in repo.nodetags(node):
119 yield tmpl(t1, tag=t, **args)
122 yield tmpl(t1, tag=t, **args)
120
123
124 def showbookmark(repo, tmpl, t1, node=nullid, **args):
125 for t in repo.nodebookmarks(node):
126 yield tmpl(t1, bookmark=t, **args)
127
121 def cleanpath(repo, path):
128 def cleanpath(repo, path):
122 path = path.lstrip('/')
129 path = path.lstrip('/')
123 return util.canonpath(repo.root, '', path)
130 return util.canonpath(repo.root, '', path)
124
131
125 def changectx(repo, req):
132 def changectx(repo, req):
126 changeid = "tip"
133 changeid = "tip"
127 if 'node' in req.form:
134 if 'node' in req.form:
128 changeid = req.form['node'][0]
135 changeid = req.form['node'][0]
129 elif 'manifest' in req.form:
136 elif 'manifest' in req.form:
130 changeid = req.form['manifest'][0]
137 changeid = req.form['manifest'][0]
131
138
132 try:
139 try:
133 ctx = repo[changeid]
140 ctx = repo[changeid]
134 except error.RepoError:
141 except error.RepoError:
135 man = repo.manifest
142 man = repo.manifest
136 ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
143 ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
137
144
138 return ctx
145 return ctx
139
146
140 def filectx(repo, req):
147 def filectx(repo, req):
141 path = cleanpath(repo, req.form['file'][0])
148 path = cleanpath(repo, req.form['file'][0])
142 if 'node' in req.form:
149 if 'node' in req.form:
143 changeid = req.form['node'][0]
150 changeid = req.form['node'][0]
144 else:
151 else:
145 changeid = req.form['filenode'][0]
152 changeid = req.form['filenode'][0]
146 try:
153 try:
147 fctx = repo[changeid][path]
154 fctx = repo[changeid][path]
148 except error.RepoError:
155 except error.RepoError:
149 fctx = repo.filectx(path, fileid=changeid)
156 fctx = repo.filectx(path, fileid=changeid)
150
157
151 return fctx
158 return fctx
152
159
153 def listfilediffs(tmpl, files, node, max):
160 def listfilediffs(tmpl, files, node, max):
154 for f in files[:max]:
161 for f in files[:max]:
155 yield tmpl('filedifflink', node=hex(node), file=f)
162 yield tmpl('filedifflink', node=hex(node), file=f)
156 if len(files) > max:
163 if len(files) > max:
157 yield tmpl('fileellipses')
164 yield tmpl('fileellipses')
158
165
159 def diffs(repo, tmpl, ctx, files, parity, style):
166 def diffs(repo, tmpl, ctx, files, parity, style):
160
167
161 def countgen():
168 def countgen():
162 start = 1
169 start = 1
163 while True:
170 while True:
164 yield start
171 yield start
165 start += 1
172 start += 1
166
173
167 blockcount = countgen()
174 blockcount = countgen()
168 def prettyprintlines(diff):
175 def prettyprintlines(diff):
169 blockno = blockcount.next()
176 blockno = blockcount.next()
170 for lineno, l in enumerate(diff.splitlines(True)):
177 for lineno, l in enumerate(diff.splitlines(True)):
171 lineno = "%d.%d" % (blockno, lineno + 1)
178 lineno = "%d.%d" % (blockno, lineno + 1)
172 if l.startswith('+'):
179 if l.startswith('+'):
173 ltype = "difflineplus"
180 ltype = "difflineplus"
174 elif l.startswith('-'):
181 elif l.startswith('-'):
175 ltype = "difflineminus"
182 ltype = "difflineminus"
176 elif l.startswith('@'):
183 elif l.startswith('@'):
177 ltype = "difflineat"
184 ltype = "difflineat"
178 else:
185 else:
179 ltype = "diffline"
186 ltype = "diffline"
180 yield tmpl(ltype,
187 yield tmpl(ltype,
181 line=l,
188 line=l,
182 lineid="l%s" % lineno,
189 lineid="l%s" % lineno,
183 linenumber="% 8s" % lineno)
190 linenumber="% 8s" % lineno)
184
191
185 if files:
192 if files:
186 m = match.exact(repo.root, repo.getcwd(), files)
193 m = match.exact(repo.root, repo.getcwd(), files)
187 else:
194 else:
188 m = match.always(repo.root, repo.getcwd())
195 m = match.always(repo.root, repo.getcwd())
189
196
190 diffopts = patch.diffopts(repo.ui, untrusted=True)
197 diffopts = patch.diffopts(repo.ui, untrusted=True)
191 parents = ctx.parents()
198 parents = ctx.parents()
192 node1 = parents and parents[0].node() or nullid
199 node1 = parents and parents[0].node() or nullid
193 node2 = ctx.node()
200 node2 = ctx.node()
194
201
195 block = []
202 block = []
196 for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
203 for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
197 if chunk.startswith('diff') and block:
204 if chunk.startswith('diff') and block:
198 yield tmpl('diffblock', parity=parity.next(),
205 yield tmpl('diffblock', parity=parity.next(),
199 lines=prettyprintlines(''.join(block)))
206 lines=prettyprintlines(''.join(block)))
200 block = []
207 block = []
201 if chunk.startswith('diff') and style != 'raw':
208 if chunk.startswith('diff') and style != 'raw':
202 chunk = ''.join(chunk.splitlines(True)[1:])
209 chunk = ''.join(chunk.splitlines(True)[1:])
203 block.append(chunk)
210 block.append(chunk)
204 yield tmpl('diffblock', parity=parity.next(),
211 yield tmpl('diffblock', parity=parity.next(),
205 lines=prettyprintlines(''.join(block)))
212 lines=prettyprintlines(''.join(block)))
206
213
207 class sessionvars(object):
214 class sessionvars(object):
208 def __init__(self, vars, start='?'):
215 def __init__(self, vars, start='?'):
209 self.start = start
216 self.start = start
210 self.vars = vars
217 self.vars = vars
211 def __getitem__(self, key):
218 def __getitem__(self, key):
212 return self.vars[key]
219 return self.vars[key]
213 def __setitem__(self, key, value):
220 def __setitem__(self, key, value):
214 self.vars[key] = value
221 self.vars[key] = value
215 def __copy__(self):
222 def __copy__(self):
216 return sessionvars(copy.copy(self.vars), self.start)
223 return sessionvars(copy.copy(self.vars), self.start)
217 def __iter__(self):
224 def __iter__(self):
218 separator = self.start
225 separator = self.start
219 for key, value in self.vars.iteritems():
226 for key, value in self.vars.iteritems():
220 yield {'name': key, 'value': str(value), 'separator': separator}
227 yield {'name': key, 'value': str(value), 'separator': separator}
221 separator = '&'
228 separator = '&'
222
229
223 class wsgiui(ui.ui):
230 class wsgiui(ui.ui):
224 # default termwidth breaks under mod_wsgi
231 # default termwidth breaks under mod_wsgi
225 def termwidth(self):
232 def termwidth(self):
226 return 80
233 return 80
@@ -1,74 +1,74 b''
1 {header}
1 {header}
2 <title>{repo|escape}: {node|short}</title>
2 <title>{repo|escape}: {node|short}</title>
3 </head>
3 </head>
4 <body>
4 <body>
5 <div class="container">
5 <div class="container">
6 <div class="menu">
6 <div class="menu">
7 <div class="logo">
7 <div class="logo">
8 <a href="http://mercurial.selenic.com/">
8 <a href="http://mercurial.selenic.com/">
9 <img src="{staticurl}hglogo.png" alt="mercurial" /></a>
9 <img src="{staticurl}hglogo.png" alt="mercurial" /></a>
10 </div>
10 </div>
11 <ul>
11 <ul>
12 <li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
12 <li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
13 <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
13 <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
14 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
14 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
15 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
15 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
16 </ul>
16 </ul>
17 <ul>
17 <ul>
18 <li class="active">changeset</li>
18 <li class="active">changeset</li>
19 <li><a href="{url}raw-rev/{node|short}{sessionvars%urlparameter}">raw</a></li>
19 <li><a href="{url}raw-rev/{node|short}{sessionvars%urlparameter}">raw</a></li>
20 <li><a href="{url}file/{node|short}{sessionvars%urlparameter}">browse</a></li>
20 <li><a href="{url}file/{node|short}{sessionvars%urlparameter}">browse</a></li>
21 </ul>
21 </ul>
22 <ul>
22 <ul>
23 {archives%archiveentry}
23 {archives%archiveentry}
24 </ul>
24 </ul>
25 <ul>
25 <ul>
26 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
26 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
27 </ul>
27 </ul>
28 </div>
28 </div>
29
29
30 <div class="main">
30 <div class="main">
31
31
32 <h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
32 <h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
33 <h3>changeset {rev}:{node|short} {changesetbranch%changelogbranchname} {changesettag}</h3>
33 <h3>changeset {rev}:{node|short} {changesetbranch%changelogbranchname} {changesettag} {changesetbookmark}</h3>
34
34
35 <form class="search" action="{url}log">
35 <form class="search" action="{url}log">
36 {sessionvars%hiddenformentry}
36 {sessionvars%hiddenformentry}
37 <p><input name="rev" id="search1" type="text" size="30" /></p>
37 <p><input name="rev" id="search1" type="text" size="30" /></p>
38 <div id="hint">find changesets by author, revision,
38 <div id="hint">find changesets by author, revision,
39 files, or words in the commit message</div>
39 files, or words in the commit message</div>
40 </form>
40 </form>
41
41
42 <div class="description">{desc|strip|escape|addbreaks|nonempty}</div>
42 <div class="description">{desc|strip|escape|addbreaks|nonempty}</div>
43
43
44 <table id="changesetEntry">
44 <table id="changesetEntry">
45 <tr>
45 <tr>
46 <th class="author">author</th>
46 <th class="author">author</th>
47 <td class="author">{author|obfuscate}</td>
47 <td class="author">{author|obfuscate}</td>
48 </tr>
48 </tr>
49 <tr>
49 <tr>
50 <th class="date">date</th>
50 <th class="date">date</th>
51 <td class="date">{date|date} ({date|age})</td></tr>
51 <td class="date">{date|date} ({date|age})</td></tr>
52 <tr>
52 <tr>
53 <th class="author">parents</th>
53 <th class="author">parents</th>
54 <td class="author">{parent%changesetparent}</td>
54 <td class="author">{parent%changesetparent}</td>
55 </tr>
55 </tr>
56 <tr>
56 <tr>
57 <th class="author">children</th>
57 <th class="author">children</th>
58 <td class="author">{child%changesetchild}</td>
58 <td class="author">{child%changesetchild}</td>
59 </tr>
59 </tr>
60 <tr>
60 <tr>
61 <th class="files">files</th>
61 <th class="files">files</th>
62 <td class="files">{files}</td>
62 <td class="files">{files}</td>
63 </tr>
63 </tr>
64 </table>
64 </table>
65
65
66 <div class="overflow">
66 <div class="overflow">
67 <div class="sourcefirst"> line diff</div>
67 <div class="sourcefirst"> line diff</div>
68
68
69 {diff}
69 {diff}
70 </div>
70 </div>
71
71
72 </div>
72 </div>
73 </div>
73 </div>
74 {footer}
74 {footer}
@@ -1,135 +1,141 b''
1 {header}
1 {header}
2 <title>{repo|escape}: revision graph</title>
2 <title>{repo|escape}: revision graph</title>
3 <link rel="alternate" type="application/atom+xml"
3 <link rel="alternate" type="application/atom+xml"
4 href="{url}atom-log" title="Atom feed for {repo|escape}: log" />
4 href="{url}atom-log" title="Atom feed for {repo|escape}: log" />
5 <link rel="alternate" type="application/rss+xml"
5 <link rel="alternate" type="application/rss+xml"
6 href="{url}rss-log" title="RSS feed for {repo|escape}: log" />
6 href="{url}rss-log" title="RSS feed for {repo|escape}: log" />
7 <!--[if IE]><script type="text/javascript" src="{staticurl}excanvas.js"></script><![endif]-->
7 <!--[if IE]><script type="text/javascript" src="{staticurl}excanvas.js"></script><![endif]-->
8 </head>
8 </head>
9 <body>
9 <body>
10
10
11 <div class="container">
11 <div class="container">
12 <div class="menu">
12 <div class="menu">
13 <div class="logo">
13 <div class="logo">
14 <a href="http://mercurial.selenic.com/">
14 <a href="http://mercurial.selenic.com/">
15 <img src="{staticurl}hglogo.png" alt="mercurial" /></a>
15 <img src="{staticurl}hglogo.png" alt="mercurial" /></a>
16 </div>
16 </div>
17 <ul>
17 <ul>
18 <li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
18 <li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
19 <li class="active">graph</li>
19 <li class="active">graph</li>
20 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
20 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
21 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
21 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
22 </ul>
22 </ul>
23 <ul>
23 <ul>
24 <li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
24 <li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
25 <li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
25 <li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
26 </ul>
26 </ul>
27 <ul>
27 <ul>
28 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
28 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
29 </ul>
29 </ul>
30 </div>
30 </div>
31
31
32 <div class="main">
32 <div class="main">
33 <h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
33 <h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
34 <h3>graph</h3>
34 <h3>graph</h3>
35
35
36 <form class="search" action="{url}log">
36 <form class="search" action="{url}log">
37 {sessionvars%hiddenformentry}
37 {sessionvars%hiddenformentry}
38 <p><input name="rev" id="search1" type="text" size="30" /></p>
38 <p><input name="rev" id="search1" type="text" size="30" /></p>
39 <div id="hint">find changesets by author, revision,
39 <div id="hint">find changesets by author, revision,
40 files, or words in the commit message</div>
40 files, or words in the commit message</div>
41 </form>
41 </form>
42
42
43 <div class="navigate">
43 <div class="navigate">
44 <a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
44 <a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
45 <a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
45 <a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
46 | rev {rev}: {changenav%navgraph}
46 | rev {rev}: {changenav%navgraph}
47 </div>
47 </div>
48
48
49 <noscript><p>The revision graph only works with JavaScript-enabled browsers.</p></noscript>
49 <noscript><p>The revision graph only works with JavaScript-enabled browsers.</p></noscript>
50
50
51 <div id="wrapper">
51 <div id="wrapper">
52 <ul id="nodebgs"></ul>
52 <ul id="nodebgs"></ul>
53 <canvas id="graph" width="224" height="{canvasheight}"></canvas>
53 <canvas id="graph" width="224" height="{canvasheight}"></canvas>
54 <ul id="graphnodes"></ul>
54 <ul id="graphnodes"></ul>
55 </div>
55 </div>
56
56
57 <script type="text/javascript" src="{staticurl}graph.js"></script>
57 <script type="text/javascript" src="{staticurl}graph.js"></script>
58 <script type="text/javascript">
58 <script type="text/javascript">
59 <!-- hide script content
59 <!-- hide script content
60
60
61 var data = {jsdata|json};
61 var data = {jsdata|json};
62 var graph = new Graph();
62 var graph = new Graph();
63 graph.scale({bg_height});
63 graph.scale({bg_height});
64
64
65 graph.edge = function(x0, y0, x1, y1, color) \{
65 graph.edge = function(x0, y0, x1, y1, color) \{
66
66
67 this.setColor(color, 0.0, 0.65);
67 this.setColor(color, 0.0, 0.65);
68 this.ctx.beginPath();
68 this.ctx.beginPath();
69 this.ctx.moveTo(x0, y0);
69 this.ctx.moveTo(x0, y0);
70 this.ctx.lineTo(x1, y1);
70 this.ctx.lineTo(x1, y1);
71 this.ctx.stroke();
71 this.ctx.stroke();
72
72
73 }
73 }
74
74
75 var revlink = '<li style="_STYLE"><span class="desc">';
75 var revlink = '<li style="_STYLE"><span class="desc">';
76 revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
76 revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
77 revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
77 revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
78
78
79 graph.vertex = function(x, y, color, parity, cur) \{
79 graph.vertex = function(x, y, color, parity, cur) \{
80
80
81 this.ctx.beginPath();
81 this.ctx.beginPath();
82 color = this.setColor(color, 0.25, 0.75);
82 color = this.setColor(color, 0.25, 0.75);
83 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
83 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
84 this.ctx.fill();
84 this.ctx.fill();
85
85
86 var bg = '<li class="bg parity' + parity + '"></li>';
86 var bg = '<li class="bg parity' + parity + '"></li>';
87 var left = (this.columns + 1) * this.bg_height;
87 var left = (this.columns + 1) * this.bg_height;
88 var nstyle = 'padding-left: ' + left + 'px;';
88 var nstyle = 'padding-left: ' + left + 'px;';
89 var item = revlink.replace(/_STYLE/, nstyle);
89 var item = revlink.replace(/_STYLE/, nstyle);
90 item = item.replace(/_PARITY/, 'parity' + parity);
90 item = item.replace(/_PARITY/, 'parity' + parity);
91 item = item.replace(/_NODEID/, cur[0]);
91 item = item.replace(/_NODEID/, cur[0]);
92 item = item.replace(/_NODEID/, cur[0]);
92 item = item.replace(/_NODEID/, cur[0]);
93 item = item.replace(/_DESC/, cur[3]);
93 item = item.replace(/_DESC/, cur[3]);
94 item = item.replace(/_USER/, cur[4]);
94 item = item.replace(/_USER/, cur[4]);
95 item = item.replace(/_DATE/, cur[5]);
95 item = item.replace(/_DATE/, cur[5]);
96
96
97 var tagspan = '';
97 var tagspan = '';
98 if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) \{
98 if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) \{
99 tagspan = '<span class="logtags">';
99 tagspan = '<span class="logtags">';
100 if (cur[6][1]) \{
100 if (cur[6][1]) \{
101 tagspan += '<span class="branchhead" title="' + cur[6][0] + '">';
101 tagspan += '<span class="branchhead" title="' + cur[6][0] + '">';
102 tagspan += cur[6][0] + '</span> ';
102 tagspan += cur[6][0] + '</span> ';
103 } else if (!cur[6][1] && cur[6][0] != 'default') \{
103 } else if (!cur[6][1] && cur[6][0] != 'default') \{
104 tagspan += '<span class="branchname" title="' + cur[6][0] + '">';
104 tagspan += '<span class="branchname" title="' + cur[6][0] + '">';
105 tagspan += cur[6][0] + '</span> ';
105 tagspan += cur[6][0] + '</span> ';
106 }
106 }
107 if (cur[7].length) \{
107 if (cur[7].length) \{
108 for (var t in cur[7]) \{
108 for (var t in cur[7]) \{
109 var tag = cur[7][t];
109 var tag = cur[7][t];
110 tagspan += '<span class="tag">' + tag + '</span> ';
110 tagspan += '<span class="tag">' + tag + '</span> ';
111 }
111 }
112 }
112 }
113 if (cur[8].length) \{
114 for (var b in cur[8]) \{
115 var bookmark = cur[8][b];
116 tagspan += '<span class="tag">' + bookmark + '</span> ';
117 }
118 }
113 tagspan += '</span>';
119 tagspan += '</span>';
114 }
120 }
115
121
116 item = item.replace(/_TAGS/, tagspan);
122 item = item.replace(/_TAGS/, tagspan);
117 return [bg, item];
123 return [bg, item];
118
124
119 }
125 }
120
126
121 graph.render(data);
127 graph.render(data);
122
128
123 // stop hiding script -->
129 // stop hiding script -->
124 </script>
130 </script>
125
131
126 <div class="navigate">
132 <div class="navigate">
127 <a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
133 <a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
128 <a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
134 <a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
129 | rev {rev}: {changenav%navgraph}
135 | rev {rev}: {changenav%navgraph}
130 </div>
136 </div>
131
137
132 </div>
138 </div>
133 </div>
139 </div>
134
140
135 {footer}
141 {footer}
@@ -1,200 +1,201 b''
1 default = 'shortlog'
1 default = 'shortlog'
2
2
3 mimetype = 'text/html; charset={encoding}'
3 mimetype = 'text/html; charset={encoding}'
4 header = header.tmpl
4 header = header.tmpl
5 footer = footer.tmpl
5 footer = footer.tmpl
6 search = search.tmpl
6 search = search.tmpl
7
7
8 changelog = shortlog.tmpl
8 changelog = shortlog.tmpl
9 shortlog = shortlog.tmpl
9 shortlog = shortlog.tmpl
10 shortlogentry = shortlogentry.tmpl
10 shortlogentry = shortlogentry.tmpl
11 graph = graph.tmpl
11 graph = graph.tmpl
12 help = help.tmpl
12 help = help.tmpl
13 helptopics = helptopics.tmpl
13 helptopics = helptopics.tmpl
14
14
15 helpentry = '<tr><td><a href="{url}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
15 helpentry = '<tr><td><a href="{url}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
16
16
17 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
17 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
18 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
18 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
19 navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
19 navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
20 filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
20 filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
21 filedifflink = '<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
21 filedifflink = '<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
22 filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
22 filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
23 filenolink = '{file|escape} '
23 filenolink = '{file|escape} '
24 fileellipses = '...'
24 fileellipses = '...'
25 changelogentry = shortlogentry.tmpl
25 changelogentry = shortlogentry.tmpl
26 searchentry = shortlogentry.tmpl
26 searchentry = shortlogentry.tmpl
27 changeset = changeset.tmpl
27 changeset = changeset.tmpl
28 manifest = manifest.tmpl
28 manifest = manifest.tmpl
29
29
30 nav = '{before%naventry} {after%naventry}'
30 nav = '{before%naventry} {after%naventry}'
31 navshort = '{before%navshortentry}{after%navshortentry}'
31 navshort = '{before%navshortentry}{after%navshortentry}'
32 navgraph = '{before%navgraphentry}{after%navgraphentry}'
32 navgraph = '{before%navgraphentry}{after%navgraphentry}'
33 filenav = '{before%filenaventry}{after%filenaventry}'
33 filenav = '{before%filenaventry}{after%filenaventry}'
34
34
35 direntry = '
35 direntry = '
36 <tr class="fileline parity{parity}">
36 <tr class="fileline parity{parity}">
37 <td class="name">
37 <td class="name">
38 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">
38 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">
39 <img src="{staticurl}coal-folder.png" alt="dir."/> {basename|escape}/
39 <img src="{staticurl}coal-folder.png" alt="dir."/> {basename|escape}/
40 </a>
40 </a>
41 <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">
41 <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">
42 {emptydirs|escape}
42 {emptydirs|escape}
43 </a>
43 </a>
44 </td>
44 </td>
45 <td class="size"></td>
45 <td class="size"></td>
46 <td class="permissions">drwxr-xr-x</td>
46 <td class="permissions">drwxr-xr-x</td>
47 </tr>'
47 </tr>'
48
48
49 fileentry = '
49 fileentry = '
50 <tr class="fileline parity{parity}">
50 <tr class="fileline parity{parity}">
51 <td class="filename">
51 <td class="filename">
52 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
52 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
53 <img src="{staticurl}coal-file.png" alt="file"/> {basename|escape}
53 <img src="{staticurl}coal-file.png" alt="file"/> {basename|escape}
54 </a>
54 </a>
55 </td>
55 </td>
56 <td class="size">{size}</td>
56 <td class="size">{size}</td>
57 <td class="permissions">{permissions|permissions}</td>
57 <td class="permissions">{permissions|permissions}</td>
58 </tr>'
58 </tr>'
59
59
60 filerevision = filerevision.tmpl
60 filerevision = filerevision.tmpl
61 fileannotate = fileannotate.tmpl
61 fileannotate = fileannotate.tmpl
62 filediff = filediff.tmpl
62 filediff = filediff.tmpl
63 filelog = filelog.tmpl
63 filelog = filelog.tmpl
64 fileline = '
64 fileline = '
65 <div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
65 <div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
66 filelogentry = filelogentry.tmpl
66 filelogentry = filelogentry.tmpl
67
67
68 annotateline = '
68 annotateline = '
69 <tr class="parity{parity}">
69 <tr class="parity{parity}">
70 <td class="annotate">
70 <td class="annotate">
71 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#{targetline}"
71 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#{targetline}"
72 title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
72 title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
73 </td>
73 </td>
74 <td class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</td>
74 <td class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</td>
75 </tr>'
75 </tr>'
76
76
77 diffblock = '<div class="source bottomline parity{parity}"><pre>{lines}</pre></div>'
77 diffblock = '<div class="source bottomline parity{parity}"><pre>{lines}</pre></div>'
78 difflineplus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="plusline">{line|escape}</span>'
78 difflineplus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="plusline">{line|escape}</span>'
79 difflineminus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="minusline">{line|escape}</span>'
79 difflineminus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="minusline">{line|escape}</span>'
80 difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
80 difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
81 diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
81 diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
82
82
83 changelogparent = '
83 changelogparent = '
84 <tr>
84 <tr>
85 <th class="parent">parent {rev}:</th>
85 <th class="parent">parent {rev}:</th>
86 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
86 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
87 </tr>'
87 </tr>'
88
88
89 changesetparent = '<a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a> '
89 changesetparent = '<a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a> '
90
90
91 filerevparent = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a> '
91 filerevparent = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a> '
92 filerevchild = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a> '
92 filerevchild = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a> '
93
93
94 filerename = '{file|escape}@'
94 filerename = '{file|escape}@'
95 filelogrename = '
95 filelogrename = '
96 <tr>
96 <tr>
97 <th>base:</th>
97 <th>base:</th>
98 <td>
98 <td>
99 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
99 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
100 {file|escape}@{node|short}
100 {file|escape}@{node|short}
101 </a>
101 </a>
102 </td>
102 </td>
103 </tr>'
103 </tr>'
104 fileannotateparent = '
104 fileannotateparent = '
105 <tr>
105 <tr>
106 <td class="metatag">parent:</td>
106 <td class="metatag">parent:</td>
107 <td>
107 <td>
108 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
108 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
109 {rename%filerename}{node|short}
109 {rename%filerename}{node|short}
110 </a>
110 </a>
111 </td>
111 </td>
112 </tr>'
112 </tr>'
113 changesetchild = ' <a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>'
113 changesetchild = ' <a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>'
114 changelogchild = '
114 changelogchild = '
115 <tr>
115 <tr>
116 <th class="child">child</th>
116 <th class="child">child</th>
117 <td class="child">
117 <td class="child">
118 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
118 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
119 {node|short}
119 {node|short}
120 </a>
120 </a>
121 </td>
121 </td>
122 </tr>'
122 </tr>'
123 fileannotatechild = '
123 fileannotatechild = '
124 <tr>
124 <tr>
125 <td class="metatag">child:</td>
125 <td class="metatag">child:</td>
126 <td>
126 <td>
127 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
127 <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
128 {node|short}
128 {node|short}
129 </a>
129 </a>
130 </td>
130 </td>
131 </tr>'
131 </tr>'
132 tags = tags.tmpl
132 tags = tags.tmpl
133 tagentry = '
133 tagentry = '
134 <tr class="tagEntry parity{parity}">
134 <tr class="tagEntry parity{parity}">
135 <td>
135 <td>
136 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
136 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">
137 {tag|escape}
137 {tag|escape}
138 </a>
138 </a>
139 </td>
139 </td>
140 <td class="node">
140 <td class="node">
141 {node|short}
141 {node|short}
142 </td>
142 </td>
143 </tr>'
143 </tr>'
144 branches = branches.tmpl
144 branches = branches.tmpl
145 branchentry = '
145 branchentry = '
146 <tr class="tagEntry parity{parity}">
146 <tr class="tagEntry parity{parity}">
147 <td>
147 <td>
148 <a href="{url}shortlog/{node|short}{sessionvars%urlparameter}" class="{status}">
148 <a href="{url}shortlog/{node|short}{sessionvars%urlparameter}" class="{status}">
149 {branch|escape}
149 {branch|escape}
150 </a>
150 </a>
151 </td>
151 </td>
152 <td class="node">
152 <td class="node">
153 {node|short}
153 {node|short}
154 </td>
154 </td>
155 </tr>'
155 </tr>'
156 changelogtag = '<span class="tag">{name|escape}</span> '
156 changelogtag = '<span class="tag">{name|escape}</span> '
157 changesettag = '<span class="tag">{tag|escape}</span> '
157 changesettag = '<span class="tag">{tag|escape}</span> '
158 changesetbookmark = '<span class="tag">{bookmark|escape}</span> '
158 changelogbranchhead = '<span class="branchhead">{name|escape}</span> '
159 changelogbranchhead = '<span class="branchhead">{name|escape}</span> '
159 changelogbranchname = '<span class="branchname">{name|escape}</span> '
160 changelogbranchname = '<span class="branchname">{name|escape}</span> '
160
161
161 filediffparent = '
162 filediffparent = '
162 <tr>
163 <tr>
163 <th class="parent">parent {rev}:</th>
164 <th class="parent">parent {rev}:</th>
164 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
165 <td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
165 </tr>'
166 </tr>'
166 filelogparent = '
167 filelogparent = '
167 <tr>
168 <tr>
168 <th>parent {rev}:</th>
169 <th>parent {rev}:</th>
169 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
170 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
170 </tr>'
171 </tr>'
171 filediffchild = '
172 filediffchild = '
172 <tr>
173 <tr>
173 <th class="child">child {rev}:</th>
174 <th class="child">child {rev}:</th>
174 <td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
175 <td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
175 </td>
176 </td>
176 </tr>'
177 </tr>'
177 filelogchild = '
178 filelogchild = '
178 <tr>
179 <tr>
179 <th>child {rev}:</th>
180 <th>child {rev}:</th>
180 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
181 <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
181 </tr>'
182 </tr>'
182
183
183 indexentry = '
184 indexentry = '
184 <tr class="parity{parity}">
185 <tr class="parity{parity}">
185 <td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td>
186 <td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td>
186 <td>{description}</td>
187 <td>{description}</td>
187 <td>{contact|obfuscate}</td>
188 <td>{contact|obfuscate}</td>
188 <td class="age">{lastchange|age}</td>
189 <td class="age">{lastchange|age}</td>
189 <td class="indexlinks">{archives%indexarchiveentry}</td>
190 <td class="indexlinks">{archives%indexarchiveentry}</td>
190 </tr>\n'
191 </tr>\n'
191 indexarchiveentry = '<a href="{url}archive/{node|short}{extension|urlescape}">&nbsp;&darr;{type|escape}</a>'
192 indexarchiveentry = '<a href="{url}archive/{node|short}{extension|urlescape}">&nbsp;&darr;{type|escape}</a>'
192 index = index.tmpl
193 index = index.tmpl
193 archiveentry = '
194 archiveentry = '
194 <li>
195 <li>
195 <a href="{url}archive/{node|short}{extension|urlescape}">{type|escape}</a>
196 <a href="{url}archive/{node|short}{extension|urlescape}">{type|escape}</a>
196 </li>'
197 </li>'
197 notfound = notfound.tmpl
198 notfound = notfound.tmpl
198 error = error.tmpl
199 error = error.tmpl
199 urlparameter = '{separator}{name}={value|urlescape}'
200 urlparameter = '{separator}{name}={value|urlescape}'
200 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
201 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
@@ -1,5 +1,5 b''
1 <tr class="parity{parity}">
1 <tr class="parity{parity}">
2 <td class="age">{age(date)}</td>
2 <td class="age">{age(date)}</td>
3 <td class="author">{author|person}</td>
3 <td class="author">{author|person}</td>
4 <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags % '<span class="tag">{name|escape}</span> '}</td>
4 <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags % '<span class="tag">{name|escape}</span> '}{bookmarks % '<span class="tag">{name|escape}</span> '}</td>
5 </tr>
5 </tr>
@@ -1,1077 +1,1078 b''
1 An attempt at more fully testing the hgweb web interface.
1 An attempt at more fully testing the hgweb web interface.
2 The following things are tested elsewhere and are therefore omitted:
2 The following things are tested elsewhere and are therefore omitted:
3 - archive, tested in test-archive
3 - archive, tested in test-archive
4 - unbundle, tested in test-push-http
4 - unbundle, tested in test-push-http
5 - changegroupsubset, tested in test-pull
5 - changegroupsubset, tested in test-pull
6
6
7 Set up the repo
7 Set up the repo
8
8
9 $ hg init test
9 $ hg init test
10 $ cd test
10 $ cd test
11 $ mkdir da
11 $ mkdir da
12 $ echo foo > da/foo
12 $ echo foo > da/foo
13 $ echo foo > foo
13 $ echo foo > foo
14 $ hg ci -Ambase
14 $ hg ci -Ambase
15 adding da/foo
15 adding da/foo
16 adding foo
16 adding foo
17 $ hg tag 1.0
17 $ hg tag 1.0
18 $ hg bookmark something
18 $ echo another > foo
19 $ echo another > foo
19 $ hg branch stable
20 $ hg branch stable
20 marked working directory as branch stable
21 marked working directory as branch stable
21 $ hg ci -Ambranch
22 $ hg ci -Ambranch
22 $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
23 $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
23 $ cat hg.pid >> $DAEMON_PIDS
24 $ cat hg.pid >> $DAEMON_PIDS
24
25
25 Logs and changes
26 Logs and changes
26
27
27 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom'
28 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom'
28 200 Script output follows
29 200 Script output follows
29
30
30 <?xml version="1.0" encoding="ascii"?>
31 <?xml version="1.0" encoding="ascii"?>
31 <feed xmlns="http://www.w3.org/2005/Atom">
32 <feed xmlns="http://www.w3.org/2005/Atom">
32 <!-- Changelog -->
33 <!-- Changelog -->
33 <id>http://*:$HGPORT/</id> (glob)
34 <id>http://*:$HGPORT/</id> (glob)
34 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
35 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
35 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
36 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
36 <title>test Changelog</title>
37 <title>test Changelog</title>
37 <updated>1970-01-01T00:00:00+00:00</updated>
38 <updated>1970-01-01T00:00:00+00:00</updated>
38
39
39 <entry>
40 <entry>
40 <title>branch</title>
41 <title>branch</title>
41 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
42 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
42 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
43 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
43 <author>
44 <author>
44 <name>test</name>
45 <name>test</name>
45 <email>&#116;&#101;&#115;&#116;</email>
46 <email>&#116;&#101;&#115;&#116;</email>
46 </author>
47 </author>
47 <updated>1970-01-01T00:00:00+00:00</updated>
48 <updated>1970-01-01T00:00:00+00:00</updated>
48 <published>1970-01-01T00:00:00+00:00</published>
49 <published>1970-01-01T00:00:00+00:00</published>
49 <content type="xhtml">
50 <content type="xhtml">
50 <div xmlns="http://www.w3.org/1999/xhtml">
51 <div xmlns="http://www.w3.org/1999/xhtml">
51 <pre xml:space="preserve">branch</pre>
52 <pre xml:space="preserve">branch</pre>
52 </div>
53 </div>
53 </content>
54 </content>
54 </entry>
55 </entry>
55 <entry>
56 <entry>
56 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
57 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
57 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
58 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
58 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
59 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
59 <author>
60 <author>
60 <name>test</name>
61 <name>test</name>
61 <email>&#116;&#101;&#115;&#116;</email>
62 <email>&#116;&#101;&#115;&#116;</email>
62 </author>
63 </author>
63 <updated>1970-01-01T00:00:00+00:00</updated>
64 <updated>1970-01-01T00:00:00+00:00</updated>
64 <published>1970-01-01T00:00:00+00:00</published>
65 <published>1970-01-01T00:00:00+00:00</published>
65 <content type="xhtml">
66 <content type="xhtml">
66 <div xmlns="http://www.w3.org/1999/xhtml">
67 <div xmlns="http://www.w3.org/1999/xhtml">
67 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
68 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
68 </div>
69 </div>
69 </content>
70 </content>
70 </entry>
71 </entry>
71 <entry>
72 <entry>
72 <title>base</title>
73 <title>base</title>
73 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
74 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
74 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
75 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
75 <author>
76 <author>
76 <name>test</name>
77 <name>test</name>
77 <email>&#116;&#101;&#115;&#116;</email>
78 <email>&#116;&#101;&#115;&#116;</email>
78 </author>
79 </author>
79 <updated>1970-01-01T00:00:00+00:00</updated>
80 <updated>1970-01-01T00:00:00+00:00</updated>
80 <published>1970-01-01T00:00:00+00:00</published>
81 <published>1970-01-01T00:00:00+00:00</published>
81 <content type="xhtml">
82 <content type="xhtml">
82 <div xmlns="http://www.w3.org/1999/xhtml">
83 <div xmlns="http://www.w3.org/1999/xhtml">
83 <pre xml:space="preserve">base</pre>
84 <pre xml:space="preserve">base</pre>
84 </div>
85 </div>
85 </content>
86 </content>
86 </entry>
87 </entry>
87
88
88 </feed>
89 </feed>
89 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom'
90 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom'
90 200 Script output follows
91 200 Script output follows
91
92
92 <?xml version="1.0" encoding="ascii"?>
93 <?xml version="1.0" encoding="ascii"?>
93 <feed xmlns="http://www.w3.org/2005/Atom">
94 <feed xmlns="http://www.w3.org/2005/Atom">
94 <!-- Changelog -->
95 <!-- Changelog -->
95 <id>http://*:$HGPORT/</id> (glob)
96 <id>http://*:$HGPORT/</id> (glob)
96 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
97 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
97 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
98 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
98 <title>test Changelog</title>
99 <title>test Changelog</title>
99 <updated>1970-01-01T00:00:00+00:00</updated>
100 <updated>1970-01-01T00:00:00+00:00</updated>
100
101
101 <entry>
102 <entry>
102 <title>branch</title>
103 <title>branch</title>
103 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
104 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
104 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
105 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
105 <author>
106 <author>
106 <name>test</name>
107 <name>test</name>
107 <email>&#116;&#101;&#115;&#116;</email>
108 <email>&#116;&#101;&#115;&#116;</email>
108 </author>
109 </author>
109 <updated>1970-01-01T00:00:00+00:00</updated>
110 <updated>1970-01-01T00:00:00+00:00</updated>
110 <published>1970-01-01T00:00:00+00:00</published>
111 <published>1970-01-01T00:00:00+00:00</published>
111 <content type="xhtml">
112 <content type="xhtml">
112 <div xmlns="http://www.w3.org/1999/xhtml">
113 <div xmlns="http://www.w3.org/1999/xhtml">
113 <pre xml:space="preserve">branch</pre>
114 <pre xml:space="preserve">branch</pre>
114 </div>
115 </div>
115 </content>
116 </content>
116 </entry>
117 </entry>
117 <entry>
118 <entry>
118 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
119 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
119 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
120 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
120 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
121 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
121 <author>
122 <author>
122 <name>test</name>
123 <name>test</name>
123 <email>&#116;&#101;&#115;&#116;</email>
124 <email>&#116;&#101;&#115;&#116;</email>
124 </author>
125 </author>
125 <updated>1970-01-01T00:00:00+00:00</updated>
126 <updated>1970-01-01T00:00:00+00:00</updated>
126 <published>1970-01-01T00:00:00+00:00</published>
127 <published>1970-01-01T00:00:00+00:00</published>
127 <content type="xhtml">
128 <content type="xhtml">
128 <div xmlns="http://www.w3.org/1999/xhtml">
129 <div xmlns="http://www.w3.org/1999/xhtml">
129 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
130 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
130 </div>
131 </div>
131 </content>
132 </content>
132 </entry>
133 </entry>
133 <entry>
134 <entry>
134 <title>base</title>
135 <title>base</title>
135 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
136 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
136 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
137 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
137 <author>
138 <author>
138 <name>test</name>
139 <name>test</name>
139 <email>&#116;&#101;&#115;&#116;</email>
140 <email>&#116;&#101;&#115;&#116;</email>
140 </author>
141 </author>
141 <updated>1970-01-01T00:00:00+00:00</updated>
142 <updated>1970-01-01T00:00:00+00:00</updated>
142 <published>1970-01-01T00:00:00+00:00</published>
143 <published>1970-01-01T00:00:00+00:00</published>
143 <content type="xhtml">
144 <content type="xhtml">
144 <div xmlns="http://www.w3.org/1999/xhtml">
145 <div xmlns="http://www.w3.org/1999/xhtml">
145 <pre xml:space="preserve">base</pre>
146 <pre xml:space="preserve">base</pre>
146 </div>
147 </div>
147 </content>
148 </content>
148 </entry>
149 </entry>
149
150
150 </feed>
151 </feed>
151 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom'
152 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom'
152 200 Script output follows
153 200 Script output follows
153
154
154 <?xml version="1.0" encoding="ascii"?>
155 <?xml version="1.0" encoding="ascii"?>
155 <feed xmlns="http://www.w3.org/2005/Atom">
156 <feed xmlns="http://www.w3.org/2005/Atom">
156 <id>http://*:$HGPORT/atom-log/tip/foo</id> (glob)
157 <id>http://*:$HGPORT/atom-log/tip/foo</id> (glob)
157 <link rel="self" href="http://*:$HGPORT/atom-log/tip/foo"/> (glob)
158 <link rel="self" href="http://*:$HGPORT/atom-log/tip/foo"/> (glob)
158 <title>test: foo history</title>
159 <title>test: foo history</title>
159 <updated>1970-01-01T00:00:00+00:00</updated>
160 <updated>1970-01-01T00:00:00+00:00</updated>
160
161
161 <entry>
162 <entry>
162 <title>base</title>
163 <title>base</title>
163 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
164 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
164 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
165 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
165 <author>
166 <author>
166 <name>test</name>
167 <name>test</name>
167 <email>&#116;&#101;&#115;&#116;</email>
168 <email>&#116;&#101;&#115;&#116;</email>
168 </author>
169 </author>
169 <updated>1970-01-01T00:00:00+00:00</updated>
170 <updated>1970-01-01T00:00:00+00:00</updated>
170 <published>1970-01-01T00:00:00+00:00</published>
171 <published>1970-01-01T00:00:00+00:00</published>
171 <content type="xhtml">
172 <content type="xhtml">
172 <div xmlns="http://www.w3.org/1999/xhtml">
173 <div xmlns="http://www.w3.org/1999/xhtml">
173 <pre xml:space="preserve">base</pre>
174 <pre xml:space="preserve">base</pre>
174 </div>
175 </div>
175 </content>
176 </content>
176 </entry>
177 </entry>
177
178
178 </feed>
179 </feed>
179 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/'
180 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/'
180 200 Script output follows
181 200 Script output follows
181
182
182 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
183 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
183 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
184 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
184 <head>
185 <head>
185 <link rel="icon" href="/static/hgicon.png" type="image/png" />
186 <link rel="icon" href="/static/hgicon.png" type="image/png" />
186 <meta name="robots" content="index, nofollow" />
187 <meta name="robots" content="index, nofollow" />
187 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
188 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
188
189
189 <title>test: log</title>
190 <title>test: log</title>
190 <link rel="alternate" type="application/atom+xml"
191 <link rel="alternate" type="application/atom+xml"
191 href="/atom-log" title="Atom feed for test" />
192 href="/atom-log" title="Atom feed for test" />
192 <link rel="alternate" type="application/rss+xml"
193 <link rel="alternate" type="application/rss+xml"
193 href="/rss-log" title="RSS feed for test" />
194 href="/rss-log" title="RSS feed for test" />
194 </head>
195 </head>
195 <body>
196 <body>
196
197
197 <div class="container">
198 <div class="container">
198 <div class="menu">
199 <div class="menu">
199 <div class="logo">
200 <div class="logo">
200 <a href="http://mercurial.selenic.com/">
201 <a href="http://mercurial.selenic.com/">
201 <img src="/static/hglogo.png" alt="mercurial" /></a>
202 <img src="/static/hglogo.png" alt="mercurial" /></a>
202 </div>
203 </div>
203 <ul>
204 <ul>
204 <li class="active">log</li>
205 <li class="active">log</li>
205 <li><a href="/graph/1d22e65f027e">graph</a></li>
206 <li><a href="/graph/1d22e65f027e">graph</a></li>
206 <li><a href="/tags">tags</a></li>
207 <li><a href="/tags">tags</a></li>
207 <li><a href="/branches">branches</a></li>
208 <li><a href="/branches">branches</a></li>
208 </ul>
209 </ul>
209 <ul>
210 <ul>
210 <li><a href="/rev/1d22e65f027e">changeset</a></li>
211 <li><a href="/rev/1d22e65f027e">changeset</a></li>
211 <li><a href="/file/1d22e65f027e">browse</a></li>
212 <li><a href="/file/1d22e65f027e">browse</a></li>
212 </ul>
213 </ul>
213 <ul>
214 <ul>
214
215
215 </ul>
216 </ul>
216 <ul>
217 <ul>
217 <li><a href="/help">help</a></li>
218 <li><a href="/help">help</a></li>
218 </ul>
219 </ul>
219 </div>
220 </div>
220
221
221 <div class="main">
222 <div class="main">
222 <h2><a href="/">test</a></h2>
223 <h2><a href="/">test</a></h2>
223 <h3>log</h3>
224 <h3>log</h3>
224
225
225 <form class="search" action="/log">
226 <form class="search" action="/log">
226
227
227 <p><input name="rev" id="search1" type="text" size="30" /></p>
228 <p><input name="rev" id="search1" type="text" size="30" /></p>
228 <div id="hint">find changesets by author, revision,
229 <div id="hint">find changesets by author, revision,
229 files, or words in the commit message</div>
230 files, or words in the commit message</div>
230 </form>
231 </form>
231
232
232 <div class="navigate">
233 <div class="navigate">
233 <a href="/shortlog/2?revcount=30">less</a>
234 <a href="/shortlog/2?revcount=30">less</a>
234 <a href="/shortlog/2?revcount=120">more</a>
235 <a href="/shortlog/2?revcount=120">more</a>
235 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
236 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
236 </div>
237 </div>
237
238
238 <table class="bigtable">
239 <table class="bigtable">
239 <tr>
240 <tr>
240 <th class="age">age</th>
241 <th class="age">age</th>
241 <th class="author">author</th>
242 <th class="author">author</th>
242 <th class="description">description</th>
243 <th class="description">description</th>
243 </tr>
244 </tr>
244 <tr class="parity0">
245 <tr class="parity0">
245 <td class="age">1970-01-01</td>
246 <td class="age">1970-01-01</td>
246 <td class="author">test</td>
247 <td class="author">test</td>
247 <td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> <span class="tag">tip</span> </td>
248 <td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> <span class="tag">tip</span> <span class="tag">something</span> </td>
248 </tr>
249 </tr>
249 <tr class="parity1">
250 <tr class="parity1">
250 <td class="age">1970-01-01</td>
251 <td class="age">1970-01-01</td>
251 <td class="author">test</td>
252 <td class="author">test</td>
252 <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
253 <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
253 </tr>
254 </tr>
254 <tr class="parity0">
255 <tr class="parity0">
255 <td class="age">1970-01-01</td>
256 <td class="age">1970-01-01</td>
256 <td class="author">test</td>
257 <td class="author">test</td>
257 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> </td>
258 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> </td>
258 </tr>
259 </tr>
259
260
260 </table>
261 </table>
261
262
262 <div class="navigate">
263 <div class="navigate">
263 <a href="/shortlog/2?revcount=30">less</a>
264 <a href="/shortlog/2?revcount=30">less</a>
264 <a href="/shortlog/2?revcount=120">more</a>
265 <a href="/shortlog/2?revcount=120">more</a>
265 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
266 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
266 </div>
267 </div>
267
268
268 </div>
269 </div>
269 </div>
270 </div>
270
271
271
272
272
273
273 </body>
274 </body>
274 </html>
275 </html>
275
276
276 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/'
277 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/'
277 200 Script output follows
278 200 Script output follows
278
279
279 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
280 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
280 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
281 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
281 <head>
282 <head>
282 <link rel="icon" href="/static/hgicon.png" type="image/png" />
283 <link rel="icon" href="/static/hgicon.png" type="image/png" />
283 <meta name="robots" content="index, nofollow" />
284 <meta name="robots" content="index, nofollow" />
284 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
285 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
285
286
286 <title>test: 2ef0ac749a14</title>
287 <title>test: 2ef0ac749a14</title>
287 </head>
288 </head>
288 <body>
289 <body>
289 <div class="container">
290 <div class="container">
290 <div class="menu">
291 <div class="menu">
291 <div class="logo">
292 <div class="logo">
292 <a href="http://mercurial.selenic.com/">
293 <a href="http://mercurial.selenic.com/">
293 <img src="/static/hglogo.png" alt="mercurial" /></a>
294 <img src="/static/hglogo.png" alt="mercurial" /></a>
294 </div>
295 </div>
295 <ul>
296 <ul>
296 <li><a href="/shortlog/2ef0ac749a14">log</a></li>
297 <li><a href="/shortlog/2ef0ac749a14">log</a></li>
297 <li><a href="/graph/2ef0ac749a14">graph</a></li>
298 <li><a href="/graph/2ef0ac749a14">graph</a></li>
298 <li><a href="/tags">tags</a></li>
299 <li><a href="/tags">tags</a></li>
299 <li><a href="/branches">branches</a></li>
300 <li><a href="/branches">branches</a></li>
300 </ul>
301 </ul>
301 <ul>
302 <ul>
302 <li class="active">changeset</li>
303 <li class="active">changeset</li>
303 <li><a href="/raw-rev/2ef0ac749a14">raw</a></li>
304 <li><a href="/raw-rev/2ef0ac749a14">raw</a></li>
304 <li><a href="/file/2ef0ac749a14">browse</a></li>
305 <li><a href="/file/2ef0ac749a14">browse</a></li>
305 </ul>
306 </ul>
306 <ul>
307 <ul>
307
308
308 </ul>
309 </ul>
309 <ul>
310 <ul>
310 <li><a href="/help">help</a></li>
311 <li><a href="/help">help</a></li>
311 </ul>
312 </ul>
312 </div>
313 </div>
313
314
314 <div class="main">
315 <div class="main">
315
316
316 <h2><a href="/">test</a></h2>
317 <h2><a href="/">test</a></h2>
317 <h3>changeset 0:2ef0ac749a14 <span class="tag">1.0</span> </h3>
318 <h3>changeset 0:2ef0ac749a14 <span class="tag">1.0</span> </h3>
318
319
319 <form class="search" action="/log">
320 <form class="search" action="/log">
320
321
321 <p><input name="rev" id="search1" type="text" size="30" /></p>
322 <p><input name="rev" id="search1" type="text" size="30" /></p>
322 <div id="hint">find changesets by author, revision,
323 <div id="hint">find changesets by author, revision,
323 files, or words in the commit message</div>
324 files, or words in the commit message</div>
324 </form>
325 </form>
325
326
326 <div class="description">base</div>
327 <div class="description">base</div>
327
328
328 <table id="changesetEntry">
329 <table id="changesetEntry">
329 <tr>
330 <tr>
330 <th class="author">author</th>
331 <th class="author">author</th>
331 <td class="author">&#116;&#101;&#115;&#116;</td>
332 <td class="author">&#116;&#101;&#115;&#116;</td>
332 </tr>
333 </tr>
333 <tr>
334 <tr>
334 <th class="date">date</th>
335 <th class="date">date</th>
335 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
336 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
336 <tr>
337 <tr>
337 <th class="author">parents</th>
338 <th class="author">parents</th>
338 <td class="author"></td>
339 <td class="author"></td>
339 </tr>
340 </tr>
340 <tr>
341 <tr>
341 <th class="author">children</th>
342 <th class="author">children</th>
342 <td class="author"> <a href="/rev/a4f92ed23982">a4f92ed23982</a></td>
343 <td class="author"> <a href="/rev/a4f92ed23982">a4f92ed23982</a></td>
343 </tr>
344 </tr>
344 <tr>
345 <tr>
345 <th class="files">files</th>
346 <th class="files">files</th>
346 <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td>
347 <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td>
347 </tr>
348 </tr>
348 </table>
349 </table>
349
350
350 <div class="overflow">
351 <div class="overflow">
351 <div class="sourcefirst"> line diff</div>
352 <div class="sourcefirst"> line diff</div>
352
353
353 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
354 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
354 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ b/da/foo Thu Jan 01 00:00:00 1970 +0000
355 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ b/da/foo Thu Jan 01 00:00:00 1970 +0000
355 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
356 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
356 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+foo
357 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+foo
357 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
358 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
358 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/foo Thu Jan 01 00:00:00 1970 +0000
359 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/foo Thu Jan 01 00:00:00 1970 +0000
359 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
360 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
360 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+foo
361 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+foo
361 </span></pre></div>
362 </span></pre></div>
362 </div>
363 </div>
363
364
364 </div>
365 </div>
365 </div>
366 </div>
366
367
367
368
368 </body>
369 </body>
369 </html>
370 </html>
370
371
371 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw'
372 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw'
372 200 Script output follows
373 200 Script output follows
373
374
374
375
375 # HG changeset patch
376 # HG changeset patch
376 # User test
377 # User test
377 # Date 0 0
378 # Date 0 0
378 # Node ID a4f92ed23982be056b9852de5dfe873eaac7f0de
379 # Node ID a4f92ed23982be056b9852de5dfe873eaac7f0de
379 # Parent 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
380 # Parent 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
380 Added tag 1.0 for changeset 2ef0ac749a14
381 Added tag 1.0 for changeset 2ef0ac749a14
381
382
382 diff -r 2ef0ac749a14 -r a4f92ed23982 .hgtags
383 diff -r 2ef0ac749a14 -r a4f92ed23982 .hgtags
383 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
384 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
384 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
385 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
385 @@ -0,0 +1,1 @@
386 @@ -0,0 +1,1 @@
386 +2ef0ac749a14e4f57a5a822464a0902c6f7f448f 1.0
387 +2ef0ac749a14e4f57a5a822464a0902c6f7f448f 1.0
387
388
388 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base'
389 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base'
389 200 Script output follows
390 200 Script output follows
390
391
391 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
392 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
392 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
393 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
393 <head>
394 <head>
394 <link rel="icon" href="/static/hgicon.png" type="image/png" />
395 <link rel="icon" href="/static/hgicon.png" type="image/png" />
395 <meta name="robots" content="index, nofollow" />
396 <meta name="robots" content="index, nofollow" />
396 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
397 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
397
398
398 <title>test: searching for base</title>
399 <title>test: searching for base</title>
399 </head>
400 </head>
400 <body>
401 <body>
401
402
402 <div class="container">
403 <div class="container">
403 <div class="menu">
404 <div class="menu">
404 <div class="logo">
405 <div class="logo">
405 <a href="http://mercurial.selenic.com/">
406 <a href="http://mercurial.selenic.com/">
406 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
407 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
407 </div>
408 </div>
408 <ul>
409 <ul>
409 <li><a href="/shortlog">log</a></li>
410 <li><a href="/shortlog">log</a></li>
410 <li><a href="/graph">graph</a></li>
411 <li><a href="/graph">graph</a></li>
411 <li><a href="/tags">tags</a></li>
412 <li><a href="/tags">tags</a></li>
412 <li><a href="/branches">branches</a></li>
413 <li><a href="/branches">branches</a></li>
413 <li><a href="/help">help</a></li>
414 <li><a href="/help">help</a></li>
414 </ul>
415 </ul>
415 </div>
416 </div>
416
417
417 <div class="main">
418 <div class="main">
418 <h2><a href="/">test</a></h2>
419 <h2><a href="/">test</a></h2>
419 <h3>searching for 'base'</h3>
420 <h3>searching for 'base'</h3>
420
421
421 <form class="search" action="/log">
422 <form class="search" action="/log">
422
423
423 <p><input name="rev" id="search1" type="text" size="30"></p>
424 <p><input name="rev" id="search1" type="text" size="30"></p>
424 <div id="hint">find changesets by author, revision,
425 <div id="hint">find changesets by author, revision,
425 files, or words in the commit message</div>
426 files, or words in the commit message</div>
426 </form>
427 </form>
427
428
428 <div class="navigate">
429 <div class="navigate">
429 <a href="/search/?rev=base&revcount=5">less</a>
430 <a href="/search/?rev=base&revcount=5">less</a>
430 <a href="/search/?rev=base&revcount=20">more</a>
431 <a href="/search/?rev=base&revcount=20">more</a>
431 </div>
432 </div>
432
433
433 <table class="bigtable">
434 <table class="bigtable">
434 <tr>
435 <tr>
435 <th class="age">age</th>
436 <th class="age">age</th>
436 <th class="author">author</th>
437 <th class="author">author</th>
437 <th class="description">description</th>
438 <th class="description">description</th>
438 </tr>
439 </tr>
439 <tr class="parity0">
440 <tr class="parity0">
440 <td class="age">1970-01-01</td>
441 <td class="age">1970-01-01</td>
441 <td class="author">test</td>
442 <td class="author">test</td>
442 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> </td>
443 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> </td>
443 </tr>
444 </tr>
444
445
445 </table>
446 </table>
446
447
447 <div class="navigate">
448 <div class="navigate">
448 <a href="/search/?rev=base&revcount=5">less</a>
449 <a href="/search/?rev=base&revcount=5">less</a>
449 <a href="/search/?rev=base&revcount=20">more</a>
450 <a href="/search/?rev=base&revcount=20">more</a>
450 </div>
451 </div>
451
452
452 </div>
453 </div>
453 </div>
454 </div>
454
455
455
456
456
457
457 </body>
458 </body>
458 </html>
459 </html>
459
460
460
461
461 File-related
462 File-related
462
463
463 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw'
464 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw'
464 200 Script output follows
465 200 Script output follows
465
466
466 foo
467 foo
467 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw'
468 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw'
468 200 Script output follows
469 200 Script output follows
469
470
470
471
471 test@0: foo
472 test@0: foo
472
473
473
474
474
475
475
476
476 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw'
477 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw'
477 200 Script output follows
478 200 Script output follows
478
479
479
480
480 drwxr-xr-x da
481 drwxr-xr-x da
481 -rw-r--r-- 45 .hgtags
482 -rw-r--r-- 45 .hgtags
482 -rw-r--r-- 4 foo
483 -rw-r--r-- 4 foo
483
484
484
485
485 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo'
486 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo'
486 200 Script output follows
487 200 Script output follows
487
488
488 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
489 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
489 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
490 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
490 <head>
491 <head>
491 <link rel="icon" href="/static/hgicon.png" type="image/png" />
492 <link rel="icon" href="/static/hgicon.png" type="image/png" />
492 <meta name="robots" content="index, nofollow" />
493 <meta name="robots" content="index, nofollow" />
493 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
494 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
494
495
495 <title>test: a4f92ed23982 foo</title>
496 <title>test: a4f92ed23982 foo</title>
496 </head>
497 </head>
497 <body>
498 <body>
498
499
499 <div class="container">
500 <div class="container">
500 <div class="menu">
501 <div class="menu">
501 <div class="logo">
502 <div class="logo">
502 <a href="http://mercurial.selenic.com/">
503 <a href="http://mercurial.selenic.com/">
503 <img src="/static/hglogo.png" alt="mercurial" /></a>
504 <img src="/static/hglogo.png" alt="mercurial" /></a>
504 </div>
505 </div>
505 <ul>
506 <ul>
506 <li><a href="/shortlog/a4f92ed23982">log</a></li>
507 <li><a href="/shortlog/a4f92ed23982">log</a></li>
507 <li><a href="/graph/a4f92ed23982">graph</a></li>
508 <li><a href="/graph/a4f92ed23982">graph</a></li>
508 <li><a href="/tags">tags</a></li>
509 <li><a href="/tags">tags</a></li>
509 <li><a href="/branches">branches</a></li>
510 <li><a href="/branches">branches</a></li>
510 </ul>
511 </ul>
511 <ul>
512 <ul>
512 <li><a href="/rev/a4f92ed23982">changeset</a></li>
513 <li><a href="/rev/a4f92ed23982">changeset</a></li>
513 <li><a href="/file/a4f92ed23982/">browse</a></li>
514 <li><a href="/file/a4f92ed23982/">browse</a></li>
514 </ul>
515 </ul>
515 <ul>
516 <ul>
516 <li class="active">file</li>
517 <li class="active">file</li>
517 <li><a href="/file/tip/foo">latest</a></li>
518 <li><a href="/file/tip/foo">latest</a></li>
518 <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
519 <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
519 <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
520 <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
520 <li><a href="/log/a4f92ed23982/foo">file log</a></li>
521 <li><a href="/log/a4f92ed23982/foo">file log</a></li>
521 <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
522 <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
522 </ul>
523 </ul>
523 <ul>
524 <ul>
524 <li><a href="/help">help</a></li>
525 <li><a href="/help">help</a></li>
525 </ul>
526 </ul>
526 </div>
527 </div>
527
528
528 <div class="main">
529 <div class="main">
529 <h2><a href="/">test</a></h2>
530 <h2><a href="/">test</a></h2>
530 <h3>view foo @ 1:a4f92ed23982</h3>
531 <h3>view foo @ 1:a4f92ed23982</h3>
531
532
532 <form class="search" action="/log">
533 <form class="search" action="/log">
533
534
534 <p><input name="rev" id="search1" type="text" size="30" /></p>
535 <p><input name="rev" id="search1" type="text" size="30" /></p>
535 <div id="hint">find changesets by author, revision,
536 <div id="hint">find changesets by author, revision,
536 files, or words in the commit message</div>
537 files, or words in the commit message</div>
537 </form>
538 </form>
538
539
539 <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
540 <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
540
541
541 <table id="changesetEntry">
542 <table id="changesetEntry">
542 <tr>
543 <tr>
543 <th class="author">author</th>
544 <th class="author">author</th>
544 <td class="author">&#116;&#101;&#115;&#116;</td>
545 <td class="author">&#116;&#101;&#115;&#116;</td>
545 </tr>
546 </tr>
546 <tr>
547 <tr>
547 <th class="date">date</th>
548 <th class="date">date</th>
548 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
549 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
549 </tr>
550 </tr>
550 <tr>
551 <tr>
551 <th class="author">parents</th>
552 <th class="author">parents</th>
552 <td class="author"></td>
553 <td class="author"></td>
553 </tr>
554 </tr>
554 <tr>
555 <tr>
555 <th class="author">children</th>
556 <th class="author">children</th>
556 <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
557 <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
557 </tr>
558 </tr>
558
559
559 </table>
560 </table>
560
561
561 <div class="overflow">
562 <div class="overflow">
562 <div class="sourcefirst"> line source</div>
563 <div class="sourcefirst"> line source</div>
563
564
564 <div class="parity0 source"><a href="#l1" id="l1"> 1</a> foo
565 <div class="parity0 source"><a href="#l1" id="l1"> 1</a> foo
565 </div>
566 </div>
566 <div class="sourcelast"></div>
567 <div class="sourcelast"></div>
567 </div>
568 </div>
568 </div>
569 </div>
569 </div>
570 </div>
570
571
571
572
572
573
573 </body>
574 </body>
574 </html>
575 </html>
575
576
576 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
577 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
577 200 Script output follows
578 200 Script output follows
578
579
579
580
580 diff -r 000000000000 -r a4f92ed23982 foo
581 diff -r 000000000000 -r a4f92ed23982 foo
581 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
582 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
582 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
583 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
583 @@ -0,0 +1,1 @@
584 @@ -0,0 +1,1 @@
584 +foo
585 +foo
585
586
586
587
587
588
588
589
589
590
590 Overviews
591 Overviews
591
592
592 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
593 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
593 200 Script output follows
594 200 Script output follows
594
595
595 tip 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
596 tip 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
596 1.0 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
597 1.0 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
597 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
598 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
598 200 Script output follows
599 200 Script output follows
599
600
600 stable 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe open
601 stable 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe open
601 default a4f92ed23982be056b9852de5dfe873eaac7f0de inactive
602 default a4f92ed23982be056b9852de5dfe873eaac7f0de inactive
602 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
603 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
603 200 Script output follows
604 200 Script output follows
604
605
605 <?xml version="1.0" encoding="ascii"?>
606 <?xml version="1.0" encoding="ascii"?>
606 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
607 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
607 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
608 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
608 <head>
609 <head>
609 <link rel="icon" href="/static/hgicon.png" type="image/png" />
610 <link rel="icon" href="/static/hgicon.png" type="image/png" />
610 <meta name="robots" content="index, nofollow"/>
611 <meta name="robots" content="index, nofollow"/>
611 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
612 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
612
613
613
614
614 <title>test: Summary</title>
615 <title>test: Summary</title>
615 <link rel="alternate" type="application/atom+xml"
616 <link rel="alternate" type="application/atom+xml"
616 href="/atom-log" title="Atom feed for test"/>
617 href="/atom-log" title="Atom feed for test"/>
617 <link rel="alternate" type="application/rss+xml"
618 <link rel="alternate" type="application/rss+xml"
618 href="/rss-log" title="RSS feed for test"/>
619 href="/rss-log" title="RSS feed for test"/>
619 </head>
620 </head>
620 <body>
621 <body>
621
622
622 <div class="page_header">
623 <div class="page_header">
623 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / summary
624 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / summary
624
625
625 <form action="/log">
626 <form action="/log">
626 <input type="hidden" name="style" value="gitweb" />
627 <input type="hidden" name="style" value="gitweb" />
627 <div class="search">
628 <div class="search">
628 <input type="text" name="rev" />
629 <input type="text" name="rev" />
629 </div>
630 </div>
630 </form>
631 </form>
631 </div>
632 </div>
632
633
633 <div class="page_nav">
634 <div class="page_nav">
634 summary |
635 summary |
635 <a href="/shortlog?style=gitweb">shortlog</a> |
636 <a href="/shortlog?style=gitweb">shortlog</a> |
636 <a href="/log?style=gitweb">changelog</a> |
637 <a href="/log?style=gitweb">changelog</a> |
637 <a href="/graph?style=gitweb">graph</a> |
638 <a href="/graph?style=gitweb">graph</a> |
638 <a href="/tags?style=gitweb">tags</a> |
639 <a href="/tags?style=gitweb">tags</a> |
639 <a href="/branches?style=gitweb">branches</a> |
640 <a href="/branches?style=gitweb">branches</a> |
640 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
641 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
641 <a href="/help?style=gitweb">help</a>
642 <a href="/help?style=gitweb">help</a>
642 <br/>
643 <br/>
643 </div>
644 </div>
644
645
645 <div class="title">&nbsp;</div>
646 <div class="title">&nbsp;</div>
646 <table cellspacing="0">
647 <table cellspacing="0">
647 <tr><td>description</td><td>unknown</td></tr>
648 <tr><td>description</td><td>unknown</td></tr>
648 <tr><td>owner</td><td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td></tr>
649 <tr><td>owner</td><td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td></tr>
649 <tr><td>last change</td><td>Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
650 <tr><td>last change</td><td>Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
650 </table>
651 </table>
651
652
652 <div><a class="title" href="/shortlog?style=gitweb">changes</a></div>
653 <div><a class="title" href="/shortlog?style=gitweb">changes</a></div>
653 <table cellspacing="0">
654 <table cellspacing="0">
654
655
655 <tr class="parity0">
656 <tr class="parity0">
656 <td class="age"><i>1970-01-01</i></td>
657 <td class="age"><i>1970-01-01</i></td>
657 <td><i>test</i></td>
658 <td><i>test</i></td>
658 <td>
659 <td>
659 <a class="list" href="/rev/1d22e65f027e?style=gitweb">
660 <a class="list" href="/rev/1d22e65f027e?style=gitweb">
660 <b>branch</b>
661 <b>branch</b>
661 <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> </span>
662 <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> </span>
662 </a>
663 </a>
663 </td>
664 </td>
664 <td class="link" nowrap>
665 <td class="link" nowrap>
665 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
666 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
666 <a href="/file/1d22e65f027e?style=gitweb">files</a>
667 <a href="/file/1d22e65f027e?style=gitweb">files</a>
667 </td>
668 </td>
668 </tr>
669 </tr>
669 <tr class="parity1">
670 <tr class="parity1">
670 <td class="age"><i>1970-01-01</i></td>
671 <td class="age"><i>1970-01-01</i></td>
671 <td><i>test</i></td>
672 <td><i>test</i></td>
672 <td>
673 <td>
673 <a class="list" href="/rev/a4f92ed23982?style=gitweb">
674 <a class="list" href="/rev/a4f92ed23982?style=gitweb">
674 <b>Added tag 1.0 for changeset 2ef0ac749a14</b>
675 <b>Added tag 1.0 for changeset 2ef0ac749a14</b>
675 <span class="logtags"><span class="branchtag" title="default">default</span> </span>
676 <span class="logtags"><span class="branchtag" title="default">default</span> </span>
676 </a>
677 </a>
677 </td>
678 </td>
678 <td class="link" nowrap>
679 <td class="link" nowrap>
679 <a href="/rev/a4f92ed23982?style=gitweb">changeset</a> |
680 <a href="/rev/a4f92ed23982?style=gitweb">changeset</a> |
680 <a href="/file/a4f92ed23982?style=gitweb">files</a>
681 <a href="/file/a4f92ed23982?style=gitweb">files</a>
681 </td>
682 </td>
682 </tr>
683 </tr>
683 <tr class="parity0">
684 <tr class="parity0">
684 <td class="age"><i>1970-01-01</i></td>
685 <td class="age"><i>1970-01-01</i></td>
685 <td><i>test</i></td>
686 <td><i>test</i></td>
686 <td>
687 <td>
687 <a class="list" href="/rev/2ef0ac749a14?style=gitweb">
688 <a class="list" href="/rev/2ef0ac749a14?style=gitweb">
688 <b>base</b>
689 <b>base</b>
689 <span class="logtags"><span class="tagtag" title="1.0">1.0</span> </span>
690 <span class="logtags"><span class="tagtag" title="1.0">1.0</span> </span>
690 </a>
691 </a>
691 </td>
692 </td>
692 <td class="link" nowrap>
693 <td class="link" nowrap>
693 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
694 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
694 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
695 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
695 </td>
696 </td>
696 </tr>
697 </tr>
697 <tr class="light"><td colspan="4"><a class="list" href="/shortlog?style=gitweb">...</a></td></tr>
698 <tr class="light"><td colspan="4"><a class="list" href="/shortlog?style=gitweb">...</a></td></tr>
698 </table>
699 </table>
699
700
700 <div><a class="title" href="/tags?style=gitweb">tags</a></div>
701 <div><a class="title" href="/tags?style=gitweb">tags</a></div>
701 <table cellspacing="0">
702 <table cellspacing="0">
702
703
703 <tr class="parity0">
704 <tr class="parity0">
704 <td class="age"><i>1970-01-01</i></td>
705 <td class="age"><i>1970-01-01</i></td>
705 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
706 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
706 <td class="link">
707 <td class="link">
707 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
708 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
708 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
709 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
709 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
710 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
710 </td>
711 </td>
711 </tr>
712 </tr>
712 <tr class="light"><td colspan="3"><a class="list" href="/tags?style=gitweb">...</a></td></tr>
713 <tr class="light"><td colspan="3"><a class="list" href="/tags?style=gitweb">...</a></td></tr>
713 </table>
714 </table>
714
715
715 <div><a class="title" href="#">branches</a></div>
716 <div><a class="title" href="#">branches</a></div>
716 <table cellspacing="0">
717 <table cellspacing="0">
717
718
718 <tr class="parity0">
719 <tr class="parity0">
719 <td class="age"><i>1970-01-01</i></td>
720 <td class="age"><i>1970-01-01</i></td>
720 <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
721 <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
721 <td class="">stable</td>
722 <td class="">stable</td>
722 <td class="link">
723 <td class="link">
723 <a href="/changeset/1d22e65f027e?style=gitweb">changeset</a> |
724 <a href="/changeset/1d22e65f027e?style=gitweb">changeset</a> |
724 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
725 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
725 <a href="/file/1d22e65f027e?style=gitweb">files</a>
726 <a href="/file/1d22e65f027e?style=gitweb">files</a>
726 </td>
727 </td>
727 </tr>
728 </tr>
728 <tr class="parity1">
729 <tr class="parity1">
729 <td class="age"><i>1970-01-01</i></td>
730 <td class="age"><i>1970-01-01</i></td>
730 <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
731 <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
731 <td class="">default</td>
732 <td class="">default</td>
732 <td class="link">
733 <td class="link">
733 <a href="/changeset/a4f92ed23982?style=gitweb">changeset</a> |
734 <a href="/changeset/a4f92ed23982?style=gitweb">changeset</a> |
734 <a href="/log/a4f92ed23982?style=gitweb">changelog</a> |
735 <a href="/log/a4f92ed23982?style=gitweb">changelog</a> |
735 <a href="/file/a4f92ed23982?style=gitweb">files</a>
736 <a href="/file/a4f92ed23982?style=gitweb">files</a>
736 </td>
737 </td>
737 </tr>
738 </tr>
738 <tr class="light">
739 <tr class="light">
739 <td colspan="4"><a class="list" href="#">...</a></td>
740 <td colspan="4"><a class="list" href="#">...</a></td>
740 </tr>
741 </tr>
741 </table>
742 </table>
742 <div class="page_footer">
743 <div class="page_footer">
743 <div class="page_footer_text">test</div>
744 <div class="page_footer_text">test</div>
744 <div class="rss_logo">
745 <div class="rss_logo">
745 <a href="/rss-log">RSS</a>
746 <a href="/rss-log">RSS</a>
746 <a href="/atom-log">Atom</a>
747 <a href="/atom-log">Atom</a>
747 </div>
748 </div>
748 <br />
749 <br />
749
750
750 </div>
751 </div>
751 </body>
752 </body>
752 </html>
753 </html>
753
754
754 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb'
755 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb'
755 200 Script output follows
756 200 Script output follows
756
757
757 <?xml version="1.0" encoding="ascii"?>
758 <?xml version="1.0" encoding="ascii"?>
758 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
759 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
759 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
760 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
760 <head>
761 <head>
761 <link rel="icon" href="/static/hgicon.png" type="image/png" />
762 <link rel="icon" href="/static/hgicon.png" type="image/png" />
762 <meta name="robots" content="index, nofollow"/>
763 <meta name="robots" content="index, nofollow"/>
763 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
764 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
764
765
765
766
766 <title>test: Graph</title>
767 <title>test: Graph</title>
767 <link rel="alternate" type="application/atom+xml"
768 <link rel="alternate" type="application/atom+xml"
768 href="/atom-log" title="Atom feed for test"/>
769 href="/atom-log" title="Atom feed for test"/>
769 <link rel="alternate" type="application/rss+xml"
770 <link rel="alternate" type="application/rss+xml"
770 href="/rss-log" title="RSS feed for test"/>
771 href="/rss-log" title="RSS feed for test"/>
771 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
772 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
772 </head>
773 </head>
773 <body>
774 <body>
774
775
775 <div class="page_header">
776 <div class="page_header">
776 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / graph
777 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / graph
777 </div>
778 </div>
778
779
779 <form action="/log">
780 <form action="/log">
780 <input type="hidden" name="style" value="gitweb" />
781 <input type="hidden" name="style" value="gitweb" />
781 <div class="search">
782 <div class="search">
782 <input type="text" name="rev" />
783 <input type="text" name="rev" />
783 </div>
784 </div>
784 </form>
785 </form>
785 <div class="page_nav">
786 <div class="page_nav">
786 <a href="/summary?style=gitweb">summary</a> |
787 <a href="/summary?style=gitweb">summary</a> |
787 <a href="/shortlog?style=gitweb">shortlog</a> |
788 <a href="/shortlog?style=gitweb">shortlog</a> |
788 <a href="/log/2?style=gitweb">changelog</a> |
789 <a href="/log/2?style=gitweb">changelog</a> |
789 graph |
790 graph |
790 <a href="/tags?style=gitweb">tags</a> |
791 <a href="/tags?style=gitweb">tags</a> |
791 <a href="/branches?style=gitweb">branches</a> |
792 <a href="/branches?style=gitweb">branches</a> |
792 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
793 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
793 <a href="/help?style=gitweb">help</a>
794 <a href="/help?style=gitweb">help</a>
794 <br/>
795 <br/>
795 <a href="/graph/2?style=gitweb&revcount=30">less</a>
796 <a href="/graph/2?style=gitweb&revcount=30">less</a>
796 <a href="/graph/2?style=gitweb&revcount=120">more</a>
797 <a href="/graph/2?style=gitweb&revcount=120">more</a>
797 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a> <br/>
798 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a> <br/>
798 </div>
799 </div>
799
800
800 <div class="title">&nbsp;</div>
801 <div class="title">&nbsp;</div>
801
802
802 <noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
803 <noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
803
804
804 <div id="wrapper">
805 <div id="wrapper">
805 <ul id="nodebgs"></ul>
806 <ul id="nodebgs"></ul>
806 <canvas id="graph" width="224" height="129"></canvas>
807 <canvas id="graph" width="224" height="129"></canvas>
807 <ul id="graphnodes"></ul>
808 <ul id="graphnodes"></ul>
808 </div>
809 </div>
809
810
810 <script type="text/javascript" src="/static/graph.js"></script>
811 <script type="text/javascript" src="/static/graph.js"></script>
811 <script>
812 <script>
812 <!-- hide script content
813 <!-- hide script content
813
814
814 var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", true], ["tip"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"]]];
815 var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], []]];
815 var graph = new Graph();
816 var graph = new Graph();
816 graph.scale(39);
817 graph.scale(39);
817
818
818 graph.edge = function(x0, y0, x1, y1, color) {
819 graph.edge = function(x0, y0, x1, y1, color) {
819
820
820 this.setColor(color, 0.0, 0.65);
821 this.setColor(color, 0.0, 0.65);
821 this.ctx.beginPath();
822 this.ctx.beginPath();
822 this.ctx.moveTo(x0, y0);
823 this.ctx.moveTo(x0, y0);
823 this.ctx.lineTo(x1, y1);
824 this.ctx.lineTo(x1, y1);
824 this.ctx.stroke();
825 this.ctx.stroke();
825
826
826 }
827 }
827
828
828 var revlink = '<li style="_STYLE"><span class="desc">';
829 var revlink = '<li style="_STYLE"><span class="desc">';
829 revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
830 revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
830 revlink += '</span> _TAGS';
831 revlink += '</span> _TAGS';
831 revlink += '<span class="info">_DATE, by _USER</span></li>';
832 revlink += '<span class="info">_DATE, by _USER</span></li>';
832
833
833 graph.vertex = function(x, y, color, parity, cur) {
834 graph.vertex = function(x, y, color, parity, cur) {
834
835
835 this.ctx.beginPath();
836 this.ctx.beginPath();
836 color = this.setColor(color, 0.25, 0.75);
837 color = this.setColor(color, 0.25, 0.75);
837 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
838 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
838 this.ctx.fill();
839 this.ctx.fill();
839
840
840 var bg = '<li class="bg parity' + parity + '"></li>';
841 var bg = '<li class="bg parity' + parity + '"></li>';
841 var left = (this.columns + 1) * this.bg_height;
842 var left = (this.columns + 1) * this.bg_height;
842 var nstyle = 'padding-left: ' + left + 'px;';
843 var nstyle = 'padding-left: ' + left + 'px;';
843 var item = revlink.replace(/_STYLE/, nstyle);
844 var item = revlink.replace(/_STYLE/, nstyle);
844 item = item.replace(/_PARITY/, 'parity' + parity);
845 item = item.replace(/_PARITY/, 'parity' + parity);
845 item = item.replace(/_NODEID/, cur[0]);
846 item = item.replace(/_NODEID/, cur[0]);
846 item = item.replace(/_NODEID/, cur[0]);
847 item = item.replace(/_NODEID/, cur[0]);
847 item = item.replace(/_DESC/, cur[3]);
848 item = item.replace(/_DESC/, cur[3]);
848 item = item.replace(/_USER/, cur[4]);
849 item = item.replace(/_USER/, cur[4]);
849 item = item.replace(/_DATE/, cur[5]);
850 item = item.replace(/_DATE/, cur[5]);
850
851
851 var tagspan = '';
852 var tagspan = '';
852 if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
853 if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
853 tagspan = '<span class="logtags">';
854 tagspan = '<span class="logtags">';
854 if (cur[6][1]) {
855 if (cur[6][1]) {
855 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
856 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
856 tagspan += cur[6][0] + '</span> ';
857 tagspan += cur[6][0] + '</span> ';
857 } else if (!cur[6][1] && cur[6][0] != 'default') {
858 } else if (!cur[6][1] && cur[6][0] != 'default') {
858 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
859 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
859 tagspan += cur[6][0] + '</span> ';
860 tagspan += cur[6][0] + '</span> ';
860 }
861 }
861 if (cur[7].length) {
862 if (cur[7].length) {
862 for (var t in cur[7]) {
863 for (var t in cur[7]) {
863 var tag = cur[7][t];
864 var tag = cur[7][t];
864 tagspan += '<span class="tagtag">' + tag + '</span> ';
865 tagspan += '<span class="tagtag">' + tag + '</span> ';
865 }
866 }
866 }
867 }
867 tagspan += '</span>';
868 tagspan += '</span>';
868 }
869 }
869
870
870 item = item.replace(/_TAGS/, tagspan);
871 item = item.replace(/_TAGS/, tagspan);
871 return [bg, item];
872 return [bg, item];
872
873
873 }
874 }
874
875
875 graph.render(data);
876 graph.render(data);
876
877
877 // stop hiding script -->
878 // stop hiding script -->
878 </script>
879 </script>
879
880
880 <div class="page_nav">
881 <div class="page_nav">
881 <a href="/graph/2?style=gitweb&revcount=30">less</a>
882 <a href="/graph/2?style=gitweb&revcount=30">less</a>
882 <a href="/graph/2?style=gitweb&revcount=120">more</a>
883 <a href="/graph/2?style=gitweb&revcount=120">more</a>
883 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a>
884 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a>
884 </div>
885 </div>
885
886
886 <div class="page_footer">
887 <div class="page_footer">
887 <div class="page_footer_text">test</div>
888 <div class="page_footer_text">test</div>
888 <div class="rss_logo">
889 <div class="rss_logo">
889 <a href="/rss-log">RSS</a>
890 <a href="/rss-log">RSS</a>
890 <a href="/atom-log">Atom</a>
891 <a href="/atom-log">Atom</a>
891 </div>
892 </div>
892 <br />
893 <br />
893
894
894 </div>
895 </div>
895 </body>
896 </body>
896 </html>
897 </html>
897
898
898
899
899 capabilities
900 capabilities
900
901
901 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
902 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
902 200 Script output follows
903 200 Script output follows
903
904
904 lookup changegroupsubset branchmap pushkey unbundle=HG10GZ,HG10BZ,HG10UN
905 lookup changegroupsubset branchmap pushkey unbundle=HG10GZ,HG10BZ,HG10UN
905
906
906 heads
907 heads
907
908
908 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
909 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
909 200 Script output follows
910 200 Script output follows
910
911
911 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
912 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
912
913
913 branches
914 branches
914
915
915 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches&nodes=0000000000000000000000000000000000000000'
916 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches&nodes=0000000000000000000000000000000000000000'
916 200 Script output follows
917 200 Script output follows
917
918
918 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
919 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
919
920
920 changegroup
921 changegroup
921
922
922 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
923 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
923 200 Script output follows
924 200 Script output follows
924
925
925 x\x9c\xbdTMHUA\x14\xbe\xa8\xf9\xec\xda&\x10\x11*\xb8\x88\x81\x99\xbef\xe6\xce\xbdw\xc6\xf2a\x16E\x1b\x11[%\x98\xcc\xaf\x8f\x8c\xf7\xc0\xf7\x82 (esc)
926 x\x9c\xbdTMHUA\x14\xbe\xa8\xf9\xec\xda&\x10\x11*\xb8\x88\x81\x99\xbef\xe6\xce\xbdw\xc6\xf2a\x16E\x1b\x11[%\x98\xcc\xaf\x8f\x8c\xf7\xc0\xf7\x82 (esc)
926 4\x11KP2m\x95\xad*\xabE\x05AP\xd0\xc22Z\x14\xf9\x03\xb9j\xa3\x9b$\xa4MJ\xb4\x90\xc0\x9a\x9bO0\x10\xdf\x13\xa2\x81\x0f\x869g\xe6|\xe7\x9c\xef\x8ceY\xf7\xa2KO\xd2\xb7K\x16~\\n\xe9\xad\x90w\x86\xab\x93W\x8e\xdf\xb0r\\Y\xee6(\xa2)\xf6\x95\xc6\x01\xe4\x1az\x80R\xe8kN\x98\xe7R\xa4\xa9K@\xe0!A\xb4k\xa7U*m\x03\x07\xd8\x92\x1d\xd2\xc9\xa4\x1d\xc2\xe6,\xa5\xcc+\x1f\xef\xafDgi\xef\xab\x1d\x1d\xb7\x9a\xe7[W\xfbc\x8f\xde-\xcd\xe7\xcaz\xb3\xbb\x19\xd3\x81\x10>c>\x08\x00"X\x11\xc2\x84@\xd2\xe7B*L\x00\x01P\x04R\xc3@\xbaB0\xdb8#\x83:\x83\xa2h\xbc=\xcd\xdaS\xe1Y,L\xd3\xa0\xf2\xa8\x94J:\xe6\xd8\x81Q\xe0\xe8d\xa7#\xe2,\xd1\xaeR*\xed \xa5\x01\x13\x01\xa6\x0cb\xe3;\xbe\xaf\xfcK[^wK\xe1N\xaf\xbbk\xe8B\xd1\xf4\xc1\x07\xb3\xab[\x10\xfdkmvwcB\xa6\xa4\xd4G\xc4D\xc2\x141\xad\x91\x10\x00\x08J\x81\xcb}\xee \xee+W\xba\x8a\x80\x90|\xd4\xa0\xd6\xa0\xd4T\xde\xe1\x9d,!\xe2\xb5\xa94\xe3\xe7\xd5\x9f\x06\x18\xcba\x03aP\xb8f\xcd\x04\x1a_\\9\xf1\xed\xe4\x9e\xe5\xa6\xd1\xd2\x9f\x03\xa7o\xae\x90H\xf3\xfb\xef\xffH3\xadk (esc)
927 4\x11KP2m\x95\xad*\xabE\x05AP\xd0\xc22Z\x14\xf9\x03\xb9j\xa3\x9b$\xa4MJ\xb4\x90\xc0\x9a\x9bO0\x10\xdf\x13\xa2\x81\x0f\x869g\xe6|\xe7\x9c\xef\x8ceY\xf7\xa2KO\xd2\xb7K\x16~\\n\xe9\xad\x90w\x86\xab\x93W\x8e\xdf\xb0r\\Y\xee6(\xa2)\xf6\x95\xc6\x01\xe4\x1az\x80R\xe8kN\x98\xe7R\xa4\xa9K@\xe0!A\xb4k\xa7U*m\x03\x07\xd8\x92\x1d\xd2\xc9\xa4\x1d\xc2\xe6,\xa5\xcc+\x1f\xef\xafDgi\xef\xab\x1d\x1d\xb7\x9a\xe7[W\xfbc\x8f\xde-\xcd\xe7\xcaz\xb3\xbb\x19\xd3\x81\x10>c>\x08\x00"X\x11\xc2\x84@\xd2\xe7B*L\x00\x01P\x04R\xc3@\xbaB0\xdb8#\x83:\x83\xa2h\xbc=\xcd\xdaS\xe1Y,L\xd3\xa0\xf2\xa8\x94J:\xe6\xd8\x81Q\xe0\xe8d\xa7#\xe2,\xd1\xaeR*\xed \xa5\x01\x13\x01\xa6\x0cb\xe3;\xbe\xaf\xfcK[^wK\xe1N\xaf\xbbk\xe8B\xd1\xf4\xc1\x07\xb3\xab[\x10\xfdkmvwcB\xa6\xa4\xd4G\xc4D\xc2\x141\xad\x91\x10\x00\x08J\x81\xcb}\xee \xee+W\xba\x8a\x80\x90|\xd4\xa0\xd6\xa0\xd4T\xde\xe1\x9d,!\xe2\xb5\xa94\xe3\xe7\xd5\x9f\x06\x18\xcba\x03aP\xb8f\xcd\x04\x1a_\\9\xf1\xed\xe4\x9e\xe5\xa6\xd1\xd2\x9f\x03\xa7o\xae\x90H\xf3\xfb\xef\xffH3\xadk (esc)
927 \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
928 \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
928 \xa8\x80\x84S \xa5\xbd-g\x13`\xe4\xdc\xc3H^\xdf\xe2\xc0TM\xc7\xf4BO\xcf\xde\xae\xe5\xae#\x1frM(K\x97`F\x19\x16s\x05GD\xb9\x01\xc1\x00+\x8c|\x9fp\xc11\xf0\x14\x00\x9cJ\x82<\xe0\x12\x9f\xc1\x90\xd0\xf5\xc8\x19>Pr\xaa\xeaW\xf5\xc4\xae\xd1\xfc\x17\xcf'\x13u\xb1\x9e\xcdHnC\x0e\xcc`\xc8\xa0&\xac\x0e\xf1|\x8c\x10$\xc4\x8c\xa2p\x05`\xdc\x08 \x80\xc4\xd7Rr-\x94\x10\x102\xedi;\xf3f\xf1z\x16\x86\xdb\xd8d\xe5\xe7\x8b\xf5\x8d\rzp\xb2\xfe\xac\xf5\xf2\xd3\xfe\xfckws\xedt\x96b\xd5l\x1c\x0b\x85\xb5\x170\x8f\x11\x84\xb0\x8f\x19\xa0\x00 _\x07\x1ac\xa2\xc3\x89Z\xe7\x96\xf9 \xccNFg\xc7F\xaa\x8a+\x9a\x9cc_\x17\x1b\x17\x9e]z38<\x97+\xb5,",\xc8\xc8?\\\x91\xff\x17.~U\x96\x97\xf5%\xdeN<\x8e\xf5\x97%\xe7^\xcfL\xed~\xda\x96k\xdc->\x86\x02\x83"\x96H\xa6\xe3\xaas=-\xeb7\xe5\xda\x8f\xbc (no-eol) (esc)
929 \xa8\x80\x84S \xa5\xbd-g\x13`\xe4\xdc\xc3H^\xdf\xe2\xc0TM\xc7\xf4BO\xcf\xde\xae\xe5\xae#\x1frM(K\x97`F\x19\x16s\x05GD\xb9\x01\xc1\x00+\x8c|\x9fp\xc11\xf0\x14\x00\x9cJ\x82<\xe0\x12\x9f\xc1\x90\xd0\xf5\xc8\x19>Pr\xaa\xeaW\xf5\xc4\xae\xd1\xfc\x17\xcf'\x13u\xb1\x9e\xcdHnC\x0e\xcc`\xc8\xa0&\xac\x0e\xf1|\x8c\x10$\xc4\x8c\xa2p\x05`\xdc\x08 \x80\xc4\xd7Rr-\x94\x10\x102\xedi;\xf3f\xf1z\x16\x86\xdb\xd8d\xe5\xe7\x8b\xf5\x8d\rzp\xb2\xfe\xac\xf5\xf2\xd3\xfe\xfckws\xedt\x96b\xd5l\x1c\x0b\x85\xb5\x170\x8f\x11\x84\xb0\x8f\x19\xa0\x00 _\x07\x1ac\xa2\xc3\x89Z\xe7\x96\xf9 \xccNFg\xc7F\xaa\x8a+\x9a\x9cc_\x17\x1b\x17\x9e]z38<\x97+\xb5,",\xc8\xc8?\\\x91\xff\x17.~U\x96\x97\xf5%\xdeN<\x8e\xf5\x97%\xe7^\xcfL\xed~\xda\x96k\xdc->\x86\x02\x83"\x96H\xa6\xe3\xaas=-\xeb7\xe5\xda\x8f\xbc (no-eol) (esc)
929
930
930 stream_out
931 stream_out
931
932
932 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out'
933 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out'
933 200 Script output follows
934 200 Script output follows
934
935
935 1
936 1
936
937
937 failing unbundle, requires POST request
938 failing unbundle, requires POST request
938
939
939 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle'
940 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle'
940 405 push requires POST request
941 405 push requires POST request
941
942
942 0
943 0
943 push requires POST request
944 push requires POST request
944 [1]
945 [1]
945
946
946 Static files
947 Static files
947
948
948 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css'
949 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css'
949 200 Script output follows
950 200 Script output follows
950
951
951 a { text-decoration:none; }
952 a { text-decoration:none; }
952 .age { white-space:nowrap; }
953 .age { white-space:nowrap; }
953 .date { white-space:nowrap; }
954 .date { white-space:nowrap; }
954 .indexlinks { white-space:nowrap; }
955 .indexlinks { white-space:nowrap; }
955 .parity0 { background-color: #ddd; }
956 .parity0 { background-color: #ddd; }
956 .parity1 { background-color: #eee; }
957 .parity1 { background-color: #eee; }
957 .lineno { width: 60px; color: #aaa; font-size: smaller;
958 .lineno { width: 60px; color: #aaa; font-size: smaller;
958 text-align: right; }
959 text-align: right; }
959 .plusline { color: green; }
960 .plusline { color: green; }
960 .minusline { color: red; }
961 .minusline { color: red; }
961 .atline { color: purple; }
962 .atline { color: purple; }
962 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
963 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
963 .buttons a {
964 .buttons a {
964 background-color: #666;
965 background-color: #666;
965 padding: 2pt;
966 padding: 2pt;
966 color: white;
967 color: white;
967 font-family: sans;
968 font-family: sans;
968 font-weight: bold;
969 font-weight: bold;
969 }
970 }
970 .navigate a {
971 .navigate a {
971 background-color: #ccc;
972 background-color: #ccc;
972 padding: 2pt;
973 padding: 2pt;
973 font-family: sans;
974 font-family: sans;
974 color: black;
975 color: black;
975 }
976 }
976
977
977 .metatag {
978 .metatag {
978 background-color: #888;
979 background-color: #888;
979 color: white;
980 color: white;
980 text-align: right;
981 text-align: right;
981 }
982 }
982
983
983 /* Common */
984 /* Common */
984 pre { margin: 0; }
985 pre { margin: 0; }
985
986
986 .logo {
987 .logo {
987 float: right;
988 float: right;
988 clear: right;
989 clear: right;
989 }
990 }
990
991
991 /* Changelog/Filelog entries */
992 /* Changelog/Filelog entries */
992 .logEntry { width: 100%; }
993 .logEntry { width: 100%; }
993 .logEntry .age { width: 15%; }
994 .logEntry .age { width: 15%; }
994 .logEntry th { font-weight: normal; text-align: right; vertical-align: top; }
995 .logEntry th { font-weight: normal; text-align: right; vertical-align: top; }
995 .logEntry th.age, .logEntry th.firstline { font-weight: bold; }
996 .logEntry th.age, .logEntry th.firstline { font-weight: bold; }
996 .logEntry th.firstline { text-align: left; width: inherit; }
997 .logEntry th.firstline { text-align: left; width: inherit; }
997
998
998 /* Shortlog entries */
999 /* Shortlog entries */
999 .slogEntry { width: 100%; }
1000 .slogEntry { width: 100%; }
1000 .slogEntry .age { width: 8em; }
1001 .slogEntry .age { width: 8em; }
1001 .slogEntry td { font-weight: normal; text-align: left; vertical-align: top; }
1002 .slogEntry td { font-weight: normal; text-align: left; vertical-align: top; }
1002 .slogEntry td.author { width: 15em; }
1003 .slogEntry td.author { width: 15em; }
1003
1004
1004 /* Tag entries */
1005 /* Tag entries */
1005 #tagEntries { list-style: none; margin: 0; padding: 0; }
1006 #tagEntries { list-style: none; margin: 0; padding: 0; }
1006 #tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
1007 #tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
1007
1008
1008 /* Changeset entry */
1009 /* Changeset entry */
1009 #changesetEntry { }
1010 #changesetEntry { }
1010 #changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1011 #changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1011 #changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
1012 #changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
1012
1013
1013 /* File diff view */
1014 /* File diff view */
1014 #filediffEntry { }
1015 #filediffEntry { }
1015 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1016 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1016
1017
1017 /* Graph */
1018 /* Graph */
1018 div#wrapper {
1019 div#wrapper {
1019 position: relative;
1020 position: relative;
1020 margin: 0;
1021 margin: 0;
1021 padding: 0;
1022 padding: 0;
1022 }
1023 }
1023
1024
1024 canvas {
1025 canvas {
1025 position: absolute;
1026 position: absolute;
1026 z-index: 5;
1027 z-index: 5;
1027 top: -0.6em;
1028 top: -0.6em;
1028 margin: 0;
1029 margin: 0;
1029 }
1030 }
1030
1031
1031 ul#nodebgs {
1032 ul#nodebgs {
1032 list-style: none inside none;
1033 list-style: none inside none;
1033 padding: 0;
1034 padding: 0;
1034 margin: 0;
1035 margin: 0;
1035 top: -0.7em;
1036 top: -0.7em;
1036 }
1037 }
1037
1038
1038 ul#graphnodes li, ul#nodebgs li {
1039 ul#graphnodes li, ul#nodebgs li {
1039 height: 39px;
1040 height: 39px;
1040 }
1041 }
1041
1042
1042 ul#graphnodes {
1043 ul#graphnodes {
1043 position: absolute;
1044 position: absolute;
1044 z-index: 10;
1045 z-index: 10;
1045 top: -0.85em;
1046 top: -0.85em;
1046 list-style: none inside none;
1047 list-style: none inside none;
1047 padding: 0;
1048 padding: 0;
1048 }
1049 }
1049
1050
1050 ul#graphnodes li .info {
1051 ul#graphnodes li .info {
1051 display: block;
1052 display: block;
1052 font-size: 70%;
1053 font-size: 70%;
1053 position: relative;
1054 position: relative;
1054 top: -1px;
1055 top: -1px;
1055 }
1056 }
1056
1057
1057 Stop and restart with HGENCODING=cp932
1058 Stop and restart with HGENCODING=cp932
1058
1059
1059 $ "$TESTDIR/killdaemons.py"
1060 $ "$TESTDIR/killdaemons.py"
1060 $ HGENCODING=cp932 hg serve --config server.uncompressed=False -n test \
1061 $ HGENCODING=cp932 hg serve --config server.uncompressed=False -n test \
1061 > -p $HGPORT -d --pid-file=hg.pid -E errors.log
1062 > -p $HGPORT -d --pid-file=hg.pid -E errors.log
1062 $ cat hg.pid >> $DAEMON_PIDS
1063 $ cat hg.pid >> $DAEMON_PIDS
1063
1064
1064 commit message with Japanese Kanji 'Noh', which ends with '\x5c'
1065 commit message with Japanese Kanji 'Noh', which ends with '\x5c'
1065
1066
1066 $ echo foo >> foo
1067 $ echo foo >> foo
1067 $ HGENCODING=cp932 hg ci -m `python -c 'print("\x94\x5c")'`
1068 $ HGENCODING=cp932 hg ci -m `python -c 'print("\x94\x5c")'`
1068
1069
1069 Graph json escape of multibyte character
1070 Graph json escape of multibyte character
1070
1071
1071 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
1072 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
1072 > | grep '^var data ='
1073 > | grep '^var data ='
1073 var data = [["40b4d6888e92", [0, 1], [[0, 0, 1]], "\u80fd", "test", "1970-01-01", ["stable", true], ["tip"]], ["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", false], []], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"]]];
1074 var data = [["40b4d6888e92", [0, 1], [[0, 0, 1]], "\u80fd", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", false], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], []]];
1074
1075
1075 ERRORS ENCOUNTERED
1076 ERRORS ENCOUNTERED
1076
1077
1077 $ cat errors.log
1078 $ cat errors.log
@@ -1,388 +1,394 b''
1 Some tests for hgweb in an empty repository
1 Some tests for hgweb in an empty repository
2
2
3 $ hg init test
3 $ hg init test
4 $ cd test
4 $ cd test
5 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
5 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
6 $ cat hg.pid >> $DAEMON_PIDS
6 $ cat hg.pid >> $DAEMON_PIDS
7 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/shortlog')
7 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/shortlog')
8 200 Script output follows
8 200 Script output follows
9
9
10 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
10 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
11 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
11 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
12 <head>
12 <head>
13 <link rel="icon" href="/static/hgicon.png" type="image/png" />
13 <link rel="icon" href="/static/hgicon.png" type="image/png" />
14 <meta name="robots" content="index, nofollow" />
14 <meta name="robots" content="index, nofollow" />
15 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
15 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
16
16
17 <title>test: log</title>
17 <title>test: log</title>
18 <link rel="alternate" type="application/atom+xml"
18 <link rel="alternate" type="application/atom+xml"
19 href="/atom-log" title="Atom feed for test" />
19 href="/atom-log" title="Atom feed for test" />
20 <link rel="alternate" type="application/rss+xml"
20 <link rel="alternate" type="application/rss+xml"
21 href="/rss-log" title="RSS feed for test" />
21 href="/rss-log" title="RSS feed for test" />
22 </head>
22 </head>
23 <body>
23 <body>
24
24
25 <div class="container">
25 <div class="container">
26 <div class="menu">
26 <div class="menu">
27 <div class="logo">
27 <div class="logo">
28 <a href="http://mercurial.selenic.com/">
28 <a href="http://mercurial.selenic.com/">
29 <img src="/static/hglogo.png" alt="mercurial" /></a>
29 <img src="/static/hglogo.png" alt="mercurial" /></a>
30 </div>
30 </div>
31 <ul>
31 <ul>
32 <li class="active">log</li>
32 <li class="active">log</li>
33 <li><a href="/graph/000000000000">graph</a></li>
33 <li><a href="/graph/000000000000">graph</a></li>
34 <li><a href="/tags">tags</a></li>
34 <li><a href="/tags">tags</a></li>
35 <li><a href="/branches">branches</a></li>
35 <li><a href="/branches">branches</a></li>
36 </ul>
36 </ul>
37 <ul>
37 <ul>
38 <li><a href="/rev/000000000000">changeset</a></li>
38 <li><a href="/rev/000000000000">changeset</a></li>
39 <li><a href="/file/000000000000">browse</a></li>
39 <li><a href="/file/000000000000">browse</a></li>
40 </ul>
40 </ul>
41 <ul>
41 <ul>
42
42
43 </ul>
43 </ul>
44 <ul>
44 <ul>
45 <li><a href="/help">help</a></li>
45 <li><a href="/help">help</a></li>
46 </ul>
46 </ul>
47 </div>
47 </div>
48
48
49 <div class="main">
49 <div class="main">
50 <h2><a href="/">test</a></h2>
50 <h2><a href="/">test</a></h2>
51 <h3>log</h3>
51 <h3>log</h3>
52
52
53 <form class="search" action="/log">
53 <form class="search" action="/log">
54
54
55 <p><input name="rev" id="search1" type="text" size="30" /></p>
55 <p><input name="rev" id="search1" type="text" size="30" /></p>
56 <div id="hint">find changesets by author, revision,
56 <div id="hint">find changesets by author, revision,
57 files, or words in the commit message</div>
57 files, or words in the commit message</div>
58 </form>
58 </form>
59
59
60 <div class="navigate">
60 <div class="navigate">
61 <a href="/shortlog/-1?revcount=30">less</a>
61 <a href="/shortlog/-1?revcount=30">less</a>
62 <a href="/shortlog/-1?revcount=120">more</a>
62 <a href="/shortlog/-1?revcount=120">more</a>
63 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
63 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
64 </div>
64 </div>
65
65
66 <table class="bigtable">
66 <table class="bigtable">
67 <tr>
67 <tr>
68 <th class="age">age</th>
68 <th class="age">age</th>
69 <th class="author">author</th>
69 <th class="author">author</th>
70 <th class="description">description</th>
70 <th class="description">description</th>
71 </tr>
71 </tr>
72
72
73 </table>
73 </table>
74
74
75 <div class="navigate">
75 <div class="navigate">
76 <a href="/shortlog/-1?revcount=30">less</a>
76 <a href="/shortlog/-1?revcount=30">less</a>
77 <a href="/shortlog/-1?revcount=120">more</a>
77 <a href="/shortlog/-1?revcount=120">more</a>
78 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
78 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
79 </div>
79 </div>
80
80
81 </div>
81 </div>
82 </div>
82 </div>
83
83
84
84
85
85
86 </body>
86 </body>
87 </html>
87 </html>
88
88
89 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/log')
89 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/log')
90 200 Script output follows
90 200 Script output follows
91
91
92 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
92 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
93 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
93 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
94 <head>
94 <head>
95 <link rel="icon" href="/static/hgicon.png" type="image/png" />
95 <link rel="icon" href="/static/hgicon.png" type="image/png" />
96 <meta name="robots" content="index, nofollow" />
96 <meta name="robots" content="index, nofollow" />
97 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
97 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
98
98
99 <title>test: log</title>
99 <title>test: log</title>
100 <link rel="alternate" type="application/atom+xml"
100 <link rel="alternate" type="application/atom+xml"
101 href="/atom-log" title="Atom feed for test" />
101 href="/atom-log" title="Atom feed for test" />
102 <link rel="alternate" type="application/rss+xml"
102 <link rel="alternate" type="application/rss+xml"
103 href="/rss-log" title="RSS feed for test" />
103 href="/rss-log" title="RSS feed for test" />
104 </head>
104 </head>
105 <body>
105 <body>
106
106
107 <div class="container">
107 <div class="container">
108 <div class="menu">
108 <div class="menu">
109 <div class="logo">
109 <div class="logo">
110 <a href="http://mercurial.selenic.com/">
110 <a href="http://mercurial.selenic.com/">
111 <img src="/static/hglogo.png" alt="mercurial" /></a>
111 <img src="/static/hglogo.png" alt="mercurial" /></a>
112 </div>
112 </div>
113 <ul>
113 <ul>
114 <li class="active">log</li>
114 <li class="active">log</li>
115 <li><a href="/graph/000000000000">graph</a></li>
115 <li><a href="/graph/000000000000">graph</a></li>
116 <li><a href="/tags">tags</a></li>
116 <li><a href="/tags">tags</a></li>
117 <li><a href="/branches">branches</a></li>
117 <li><a href="/branches">branches</a></li>
118 </ul>
118 </ul>
119 <ul>
119 <ul>
120 <li><a href="/rev/000000000000">changeset</a></li>
120 <li><a href="/rev/000000000000">changeset</a></li>
121 <li><a href="/file/000000000000">browse</a></li>
121 <li><a href="/file/000000000000">browse</a></li>
122 </ul>
122 </ul>
123 <ul>
123 <ul>
124
124
125 </ul>
125 </ul>
126 <ul>
126 <ul>
127 <li><a href="/help">help</a></li>
127 <li><a href="/help">help</a></li>
128 </ul>
128 </ul>
129 </div>
129 </div>
130
130
131 <div class="main">
131 <div class="main">
132 <h2><a href="/">test</a></h2>
132 <h2><a href="/">test</a></h2>
133 <h3>log</h3>
133 <h3>log</h3>
134
134
135 <form class="search" action="/log">
135 <form class="search" action="/log">
136
136
137 <p><input name="rev" id="search1" type="text" size="30" /></p>
137 <p><input name="rev" id="search1" type="text" size="30" /></p>
138 <div id="hint">find changesets by author, revision,
138 <div id="hint">find changesets by author, revision,
139 files, or words in the commit message</div>
139 files, or words in the commit message</div>
140 </form>
140 </form>
141
141
142 <div class="navigate">
142 <div class="navigate">
143 <a href="/shortlog/-1?revcount=5">less</a>
143 <a href="/shortlog/-1?revcount=5">less</a>
144 <a href="/shortlog/-1?revcount=20">more</a>
144 <a href="/shortlog/-1?revcount=20">more</a>
145 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
145 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
146 </div>
146 </div>
147
147
148 <table class="bigtable">
148 <table class="bigtable">
149 <tr>
149 <tr>
150 <th class="age">age</th>
150 <th class="age">age</th>
151 <th class="author">author</th>
151 <th class="author">author</th>
152 <th class="description">description</th>
152 <th class="description">description</th>
153 </tr>
153 </tr>
154
154
155 </table>
155 </table>
156
156
157 <div class="navigate">
157 <div class="navigate">
158 <a href="/shortlog/-1?revcount=5">less</a>
158 <a href="/shortlog/-1?revcount=5">less</a>
159 <a href="/shortlog/-1?revcount=20">more</a>
159 <a href="/shortlog/-1?revcount=20">more</a>
160 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
160 | rev -1: <a href="/shortlog/000000000000">(0)</a> <a href="/shortlog/tip">tip</a>
161 </div>
161 </div>
162
162
163 </div>
163 </div>
164 </div>
164 </div>
165
165
166
166
167
167
168 </body>
168 </body>
169 </html>
169 </html>
170
170
171 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/graph')
171 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/graph')
172 200 Script output follows
172 200 Script output follows
173
173
174 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
174 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
175 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
175 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
176 <head>
176 <head>
177 <link rel="icon" href="/static/hgicon.png" type="image/png" />
177 <link rel="icon" href="/static/hgicon.png" type="image/png" />
178 <meta name="robots" content="index, nofollow" />
178 <meta name="robots" content="index, nofollow" />
179 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
179 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
180
180
181 <title>test: revision graph</title>
181 <title>test: revision graph</title>
182 <link rel="alternate" type="application/atom+xml"
182 <link rel="alternate" type="application/atom+xml"
183 href="/atom-log" title="Atom feed for test: log" />
183 href="/atom-log" title="Atom feed for test: log" />
184 <link rel="alternate" type="application/rss+xml"
184 <link rel="alternate" type="application/rss+xml"
185 href="/rss-log" title="RSS feed for test: log" />
185 href="/rss-log" title="RSS feed for test: log" />
186 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
186 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
187 </head>
187 </head>
188 <body>
188 <body>
189
189
190 <div class="container">
190 <div class="container">
191 <div class="menu">
191 <div class="menu">
192 <div class="logo">
192 <div class="logo">
193 <a href="http://mercurial.selenic.com/">
193 <a href="http://mercurial.selenic.com/">
194 <img src="/static/hglogo.png" alt="mercurial" /></a>
194 <img src="/static/hglogo.png" alt="mercurial" /></a>
195 </div>
195 </div>
196 <ul>
196 <ul>
197 <li><a href="/shortlog/000000000000">log</a></li>
197 <li><a href="/shortlog/000000000000">log</a></li>
198 <li class="active">graph</li>
198 <li class="active">graph</li>
199 <li><a href="/tags">tags</a></li>
199 <li><a href="/tags">tags</a></li>
200 <li><a href="/branches">branches</a></li>
200 <li><a href="/branches">branches</a></li>
201 </ul>
201 </ul>
202 <ul>
202 <ul>
203 <li><a href="/rev/000000000000">changeset</a></li>
203 <li><a href="/rev/000000000000">changeset</a></li>
204 <li><a href="/file/000000000000">browse</a></li>
204 <li><a href="/file/000000000000">browse</a></li>
205 </ul>
205 </ul>
206 <ul>
206 <ul>
207 <li><a href="/help">help</a></li>
207 <li><a href="/help">help</a></li>
208 </ul>
208 </ul>
209 </div>
209 </div>
210
210
211 <div class="main">
211 <div class="main">
212 <h2><a href="/">test</a></h2>
212 <h2><a href="/">test</a></h2>
213 <h3>graph</h3>
213 <h3>graph</h3>
214
214
215 <form class="search" action="/log">
215 <form class="search" action="/log">
216
216
217 <p><input name="rev" id="search1" type="text" size="30" /></p>
217 <p><input name="rev" id="search1" type="text" size="30" /></p>
218 <div id="hint">find changesets by author, revision,
218 <div id="hint">find changesets by author, revision,
219 files, or words in the commit message</div>
219 files, or words in the commit message</div>
220 </form>
220 </form>
221
221
222 <div class="navigate">
222 <div class="navigate">
223 <a href="/graph/-1?revcount=30">less</a>
223 <a href="/graph/-1?revcount=30">less</a>
224 <a href="/graph/-1?revcount=120">more</a>
224 <a href="/graph/-1?revcount=120">more</a>
225 | rev -1: <a href="/graph/000000000000">(0)</a> <a href="/graph/tip">tip</a>
225 | rev -1: <a href="/graph/000000000000">(0)</a> <a href="/graph/tip">tip</a>
226 </div>
226 </div>
227
227
228 <noscript><p>The revision graph only works with JavaScript-enabled browsers.</p></noscript>
228 <noscript><p>The revision graph only works with JavaScript-enabled browsers.</p></noscript>
229
229
230 <div id="wrapper">
230 <div id="wrapper">
231 <ul id="nodebgs"></ul>
231 <ul id="nodebgs"></ul>
232 <canvas id="graph" width="224" height="12"></canvas>
232 <canvas id="graph" width="224" height="12"></canvas>
233 <ul id="graphnodes"></ul>
233 <ul id="graphnodes"></ul>
234 </div>
234 </div>
235
235
236 <script type="text/javascript" src="/static/graph.js"></script>
236 <script type="text/javascript" src="/static/graph.js"></script>
237 <script type="text/javascript">
237 <script type="text/javascript">
238 <!-- hide script content
238 <!-- hide script content
239
239
240 var data = [];
240 var data = [];
241 var graph = new Graph();
241 var graph = new Graph();
242 graph.scale(39);
242 graph.scale(39);
243
243
244 graph.edge = function(x0, y0, x1, y1, color) {
244 graph.edge = function(x0, y0, x1, y1, color) {
245
245
246 this.setColor(color, 0.0, 0.65);
246 this.setColor(color, 0.0, 0.65);
247 this.ctx.beginPath();
247 this.ctx.beginPath();
248 this.ctx.moveTo(x0, y0);
248 this.ctx.moveTo(x0, y0);
249 this.ctx.lineTo(x1, y1);
249 this.ctx.lineTo(x1, y1);
250 this.ctx.stroke();
250 this.ctx.stroke();
251
251
252 }
252 }
253
253
254 var revlink = '<li style="_STYLE"><span class="desc">';
254 var revlink = '<li style="_STYLE"><span class="desc">';
255 revlink += '<a href="/rev/_NODEID" title="_NODEID">_DESC</a>';
255 revlink += '<a href="/rev/_NODEID" title="_NODEID">_DESC</a>';
256 revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
256 revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
257
257
258 graph.vertex = function(x, y, color, parity, cur) {
258 graph.vertex = function(x, y, color, parity, cur) {
259
259
260 this.ctx.beginPath();
260 this.ctx.beginPath();
261 color = this.setColor(color, 0.25, 0.75);
261 color = this.setColor(color, 0.25, 0.75);
262 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
262 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
263 this.ctx.fill();
263 this.ctx.fill();
264
264
265 var bg = '<li class="bg parity' + parity + '"></li>';
265 var bg = '<li class="bg parity' + parity + '"></li>';
266 var left = (this.columns + 1) * this.bg_height;
266 var left = (this.columns + 1) * this.bg_height;
267 var nstyle = 'padding-left: ' + left + 'px;';
267 var nstyle = 'padding-left: ' + left + 'px;';
268 var item = revlink.replace(/_STYLE/, nstyle);
268 var item = revlink.replace(/_STYLE/, nstyle);
269 item = item.replace(/_PARITY/, 'parity' + parity);
269 item = item.replace(/_PARITY/, 'parity' + parity);
270 item = item.replace(/_NODEID/, cur[0]);
270 item = item.replace(/_NODEID/, cur[0]);
271 item = item.replace(/_NODEID/, cur[0]);
271 item = item.replace(/_NODEID/, cur[0]);
272 item = item.replace(/_DESC/, cur[3]);
272 item = item.replace(/_DESC/, cur[3]);
273 item = item.replace(/_USER/, cur[4]);
273 item = item.replace(/_USER/, cur[4]);
274 item = item.replace(/_DATE/, cur[5]);
274 item = item.replace(/_DATE/, cur[5]);
275
275
276 var tagspan = '';
276 var tagspan = '';
277 if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
277 if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
278 tagspan = '<span class="logtags">';
278 tagspan = '<span class="logtags">';
279 if (cur[6][1]) {
279 if (cur[6][1]) {
280 tagspan += '<span class="branchhead" title="' + cur[6][0] + '">';
280 tagspan += '<span class="branchhead" title="' + cur[6][0] + '">';
281 tagspan += cur[6][0] + '</span> ';
281 tagspan += cur[6][0] + '</span> ';
282 } else if (!cur[6][1] && cur[6][0] != 'default') {
282 } else if (!cur[6][1] && cur[6][0] != 'default') {
283 tagspan += '<span class="branchname" title="' + cur[6][0] + '">';
283 tagspan += '<span class="branchname" title="' + cur[6][0] + '">';
284 tagspan += cur[6][0] + '</span> ';
284 tagspan += cur[6][0] + '</span> ';
285 }
285 }
286 if (cur[7].length) {
286 if (cur[7].length) {
287 for (var t in cur[7]) {
287 for (var t in cur[7]) {
288 var tag = cur[7][t];
288 var tag = cur[7][t];
289 tagspan += '<span class="tag">' + tag + '</span> ';
289 tagspan += '<span class="tag">' + tag + '</span> ';
290 }
290 }
291 }
291 }
292 if (cur[8].length) {
293 for (var b in cur[8]) {
294 var bookmark = cur[8][b];
295 tagspan += '<span class="tag">' + bookmark + '</span> ';
296 }
297 }
292 tagspan += '</span>';
298 tagspan += '</span>';
293 }
299 }
294
300
295 item = item.replace(/_TAGS/, tagspan);
301 item = item.replace(/_TAGS/, tagspan);
296 return [bg, item];
302 return [bg, item];
297
303
298 }
304 }
299
305
300 graph.render(data);
306 graph.render(data);
301
307
302 // stop hiding script -->
308 // stop hiding script -->
303 </script>
309 </script>
304
310
305 <div class="navigate">
311 <div class="navigate">
306 <a href="/graph/-1?revcount=30">less</a>
312 <a href="/graph/-1?revcount=30">less</a>
307 <a href="/graph/-1?revcount=120">more</a>
313 <a href="/graph/-1?revcount=120">more</a>
308 | rev -1: <a href="/graph/000000000000">(0)</a> <a href="/graph/tip">tip</a>
314 | rev -1: <a href="/graph/000000000000">(0)</a> <a href="/graph/tip">tip</a>
309 </div>
315 </div>
310
316
311 </div>
317 </div>
312 </div>
318 </div>
313
319
314
320
315
321
316 </body>
322 </body>
317 </html>
323 </html>
318
324
319 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file')
325 $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file')
320 200 Script output follows
326 200 Script output follows
321
327
322 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
328 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
323 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
329 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
324 <head>
330 <head>
325 <link rel="icon" href="/static/hgicon.png" type="image/png" />
331 <link rel="icon" href="/static/hgicon.png" type="image/png" />
326 <meta name="robots" content="index, nofollow" />
332 <meta name="robots" content="index, nofollow" />
327 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
333 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
328
334
329 <title>test: 000000000000 /</title>
335 <title>test: 000000000000 /</title>
330 </head>
336 </head>
331 <body>
337 <body>
332
338
333 <div class="container">
339 <div class="container">
334 <div class="menu">
340 <div class="menu">
335 <div class="logo">
341 <div class="logo">
336 <a href="http://mercurial.selenic.com/">
342 <a href="http://mercurial.selenic.com/">
337 <img src="/static/hglogo.png" alt="mercurial" /></a>
343 <img src="/static/hglogo.png" alt="mercurial" /></a>
338 </div>
344 </div>
339 <ul>
345 <ul>
340 <li><a href="/shortlog/000000000000">log</a></li>
346 <li><a href="/shortlog/000000000000">log</a></li>
341 <li><a href="/graph/000000000000">graph</a></li>
347 <li><a href="/graph/000000000000">graph</a></li>
342 <li><a href="/tags">tags</a></li>
348 <li><a href="/tags">tags</a></li>
343 <li><a href="/branches">branches</a></li>
349 <li><a href="/branches">branches</a></li>
344 </ul>
350 </ul>
345 <ul>
351 <ul>
346 <li><a href="/rev/000000000000">changeset</a></li>
352 <li><a href="/rev/000000000000">changeset</a></li>
347 <li class="active">browse</li>
353 <li class="active">browse</li>
348 </ul>
354 </ul>
349 <ul>
355 <ul>
350
356
351 </ul>
357 </ul>
352 <ul>
358 <ul>
353 <li><a href="/help">help</a></li>
359 <li><a href="/help">help</a></li>
354 </ul>
360 </ul>
355 </div>
361 </div>
356
362
357 <div class="main">
363 <div class="main">
358 <h2><a href="/">test</a></h2>
364 <h2><a href="/">test</a></h2>
359 <h3>directory / @ -1:000000000000 <span class="tag">tip</span> </h3>
365 <h3>directory / @ -1:000000000000 <span class="tag">tip</span> </h3>
360
366
361 <form class="search" action="/log">
367 <form class="search" action="/log">
362
368
363 <p><input name="rev" id="search1" type="text" size="30" /></p>
369 <p><input name="rev" id="search1" type="text" size="30" /></p>
364 <div id="hint">find changesets by author, revision,
370 <div id="hint">find changesets by author, revision,
365 files, or words in the commit message</div>
371 files, or words in the commit message</div>
366 </form>
372 </form>
367
373
368 <table class="bigtable">
374 <table class="bigtable">
369 <tr>
375 <tr>
370 <th class="name">name</th>
376 <th class="name">name</th>
371 <th class="size">size</th>
377 <th class="size">size</th>
372 <th class="permissions">permissions</th>
378 <th class="permissions">permissions</th>
373 </tr>
379 </tr>
374 <tr class="fileline parity0">
380 <tr class="fileline parity0">
375 <td class="name"><a href="/file/000000000000/">[up]</a></td>
381 <td class="name"><a href="/file/000000000000/">[up]</a></td>
376 <td class="size"></td>
382 <td class="size"></td>
377 <td class="permissions">drwxr-xr-x</td>
383 <td class="permissions">drwxr-xr-x</td>
378 </tr>
384 </tr>
379
385
380
386
381 </table>
387 </table>
382 </div>
388 </div>
383 </div>
389 </div>
384
390
385
391
386 </body>
392 </body>
387 </html>
393 </html>
388
394
General Comments 0
You need to be logged in to leave comments. Login now