##// END OF EJS Templates
hgweb: add bookmarks listing to summary page of gitweb/monoblue styles
Yuya Nishihara -
r13924:ea726c97 default
parent child Browse files
Show More
@@ -1,819 +1,829
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', 'bookmarks', 'branches', 'summary', 'filediff', 'diff',
24 'manifest', 'tags', 'bookmarks', 'branches', 'summary', 'filediff', 'diff',
25 'annotate', 'filelog', 'archive', 'static', 'graph', 'help',
25 'annotate', '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 bookmarks=webutil.nodebookmarksdict(web.repo, n),
162 bookmarks=webutil.nodebookmarksdict(web.repo, n),
163 inbranch=webutil.nodeinbranch(web.repo, ctx),
163 inbranch=webutil.nodeinbranch(web.repo, ctx),
164 branches=webutil.nodebranchdict(web.repo, ctx))
164 branches=webutil.nodebranchdict(web.repo, ctx))
165
165
166 if count >= revcount:
166 if count >= revcount:
167 break
167 break
168
168
169 tip = web.repo['tip']
169 tip = web.repo['tip']
170 parity = paritygen(web.stripecount)
170 parity = paritygen(web.stripecount)
171
171
172 return tmpl('search', query=query, node=tip.hex(),
172 return tmpl('search', query=query, node=tip.hex(),
173 entries=changelist, archives=web.archivelist("tip"),
173 entries=changelist, archives=web.archivelist("tip"),
174 morevars=morevars, lessvars=lessvars)
174 morevars=morevars, lessvars=lessvars)
175
175
176 def changelog(web, req, tmpl, shortlog=False):
176 def changelog(web, req, tmpl, shortlog=False):
177
177
178 if 'node' in req.form:
178 if 'node' in req.form:
179 ctx = webutil.changectx(web.repo, req)
179 ctx = webutil.changectx(web.repo, req)
180 else:
180 else:
181 if 'rev' in req.form:
181 if 'rev' in req.form:
182 hi = req.form['rev'][0]
182 hi = req.form['rev'][0]
183 else:
183 else:
184 hi = len(web.repo) - 1
184 hi = len(web.repo) - 1
185 try:
185 try:
186 ctx = web.repo[hi]
186 ctx = web.repo[hi]
187 except error.RepoError:
187 except error.RepoError:
188 return _search(web, req, tmpl) # XXX redirect to 404 page?
188 return _search(web, req, tmpl) # XXX redirect to 404 page?
189
189
190 def changelist(limit=0, **map):
190 def changelist(limit=0, **map):
191 l = [] # build a list in forward order for efficiency
191 l = [] # build a list in forward order for efficiency
192 for i in xrange(start, end):
192 for i in xrange(start, end):
193 ctx = web.repo[i]
193 ctx = web.repo[i]
194 n = ctx.node()
194 n = ctx.node()
195 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
195 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
196 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
196 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
197
197
198 l.insert(0, {"parity": parity.next(),
198 l.insert(0, {"parity": parity.next(),
199 "author": ctx.user(),
199 "author": ctx.user(),
200 "parent": webutil.parents(ctx, i - 1),
200 "parent": webutil.parents(ctx, i - 1),
201 "child": webutil.children(ctx, i + 1),
201 "child": webutil.children(ctx, i + 1),
202 "changelogtag": showtags,
202 "changelogtag": showtags,
203 "desc": ctx.description(),
203 "desc": ctx.description(),
204 "date": ctx.date(),
204 "date": ctx.date(),
205 "files": files,
205 "files": files,
206 "rev": i,
206 "rev": i,
207 "node": hex(n),
207 "node": hex(n),
208 "tags": webutil.nodetagsdict(web.repo, n),
208 "tags": webutil.nodetagsdict(web.repo, n),
209 "bookmarks": webutil.nodebookmarksdict(web.repo, n),
209 "bookmarks": webutil.nodebookmarksdict(web.repo, n),
210 "inbranch": webutil.nodeinbranch(web.repo, ctx),
210 "inbranch": webutil.nodeinbranch(web.repo, ctx),
211 "branches": webutil.nodebranchdict(web.repo, ctx)
211 "branches": webutil.nodebranchdict(web.repo, ctx)
212 })
212 })
213
213
214 if limit > 0:
214 if limit > 0:
215 l = l[:limit]
215 l = l[:limit]
216
216
217 for e in l:
217 for e in l:
218 yield e
218 yield e
219
219
220 revcount = shortlog and web.maxshortchanges or web.maxchanges
220 revcount = shortlog and web.maxshortchanges or web.maxchanges
221 if 'revcount' in req.form:
221 if 'revcount' in req.form:
222 revcount = int(req.form.get('revcount', [revcount])[0])
222 revcount = int(req.form.get('revcount', [revcount])[0])
223 tmpl.defaults['sessionvars']['revcount'] = revcount
223 tmpl.defaults['sessionvars']['revcount'] = revcount
224
224
225 lessvars = copy.copy(tmpl.defaults['sessionvars'])
225 lessvars = copy.copy(tmpl.defaults['sessionvars'])
226 lessvars['revcount'] = revcount / 2
226 lessvars['revcount'] = revcount / 2
227 morevars = copy.copy(tmpl.defaults['sessionvars'])
227 morevars = copy.copy(tmpl.defaults['sessionvars'])
228 morevars['revcount'] = revcount * 2
228 morevars['revcount'] = revcount * 2
229
229
230 count = len(web.repo)
230 count = len(web.repo)
231 pos = ctx.rev()
231 pos = ctx.rev()
232 start = max(0, pos - revcount + 1)
232 start = max(0, pos - revcount + 1)
233 end = min(count, start + revcount)
233 end = min(count, start + revcount)
234 pos = end - 1
234 pos = end - 1
235 parity = paritygen(web.stripecount, offset=start - end)
235 parity = paritygen(web.stripecount, offset=start - end)
236
236
237 changenav = webutil.revnavgen(pos, revcount, count, web.repo.changectx)
237 changenav = webutil.revnavgen(pos, revcount, count, web.repo.changectx)
238
238
239 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
239 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
240 node=hex(ctx.node()), rev=pos, changesets=count,
240 node=hex(ctx.node()), rev=pos, changesets=count,
241 entries=lambda **x: changelist(limit=0,**x),
241 entries=lambda **x: changelist(limit=0,**x),
242 latestentry=lambda **x: changelist(limit=1,**x),
242 latestentry=lambda **x: changelist(limit=1,**x),
243 archives=web.archivelist("tip"), revcount=revcount,
243 archives=web.archivelist("tip"), revcount=revcount,
244 morevars=morevars, lessvars=lessvars)
244 morevars=morevars, lessvars=lessvars)
245
245
246 def shortlog(web, req, tmpl):
246 def shortlog(web, req, tmpl):
247 return changelog(web, req, tmpl, shortlog = True)
247 return changelog(web, req, tmpl, shortlog = True)
248
248
249 def changeset(web, req, tmpl):
249 def changeset(web, req, tmpl):
250 ctx = webutil.changectx(web.repo, req)
250 ctx = webutil.changectx(web.repo, req)
251 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
251 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
252 showbookmarks = webutil.showbookmark(web.repo, tmpl, 'changesetbookmark',
252 showbookmarks = webutil.showbookmark(web.repo, tmpl, 'changesetbookmark',
253 ctx.node())
253 ctx.node())
254 showbranch = webutil.nodebranchnodefault(ctx)
254 showbranch = webutil.nodebranchnodefault(ctx)
255
255
256 files = []
256 files = []
257 parity = paritygen(web.stripecount)
257 parity = paritygen(web.stripecount)
258 for f in ctx.files():
258 for f in ctx.files():
259 template = f in ctx and 'filenodelink' or 'filenolink'
259 template = f in ctx and 'filenodelink' or 'filenolink'
260 files.append(tmpl(template,
260 files.append(tmpl(template,
261 node=ctx.hex(), file=f,
261 node=ctx.hex(), file=f,
262 parity=parity.next()))
262 parity=parity.next()))
263
263
264 parity = paritygen(web.stripecount)
264 parity = paritygen(web.stripecount)
265 style = web.config('web', 'style', 'paper')
265 style = web.config('web', 'style', 'paper')
266 if 'style' in req.form:
266 if 'style' in req.form:
267 style = req.form['style'][0]
267 style = req.form['style'][0]
268
268
269 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity, style)
269 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity, style)
270 return tmpl('changeset',
270 return tmpl('changeset',
271 diff=diffs,
271 diff=diffs,
272 rev=ctx.rev(),
272 rev=ctx.rev(),
273 node=ctx.hex(),
273 node=ctx.hex(),
274 parent=webutil.parents(ctx),
274 parent=webutil.parents(ctx),
275 child=webutil.children(ctx),
275 child=webutil.children(ctx),
276 changesettag=showtags,
276 changesettag=showtags,
277 changesetbookmark=showbookmarks,
277 changesetbookmark=showbookmarks,
278 changesetbranch=showbranch,
278 changesetbranch=showbranch,
279 author=ctx.user(),
279 author=ctx.user(),
280 desc=ctx.description(),
280 desc=ctx.description(),
281 date=ctx.date(),
281 date=ctx.date(),
282 files=files,
282 files=files,
283 archives=web.archivelist(ctx.hex()),
283 archives=web.archivelist(ctx.hex()),
284 tags=webutil.nodetagsdict(web.repo, ctx.node()),
284 tags=webutil.nodetagsdict(web.repo, ctx.node()),
285 bookmarks=webutil.nodebookmarksdict(web.repo, ctx.node()),
285 bookmarks=webutil.nodebookmarksdict(web.repo, ctx.node()),
286 branch=webutil.nodebranchnodefault(ctx),
286 branch=webutil.nodebranchnodefault(ctx),
287 inbranch=webutil.nodeinbranch(web.repo, ctx),
287 inbranch=webutil.nodeinbranch(web.repo, ctx),
288 branches=webutil.nodebranchdict(web.repo, ctx))
288 branches=webutil.nodebranchdict(web.repo, ctx))
289
289
290 rev = changeset
290 rev = changeset
291
291
292 def manifest(web, req, tmpl):
292 def manifest(web, req, tmpl):
293 ctx = webutil.changectx(web.repo, req)
293 ctx = webutil.changectx(web.repo, req)
294 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
294 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
295 mf = ctx.manifest()
295 mf = ctx.manifest()
296 node = ctx.node()
296 node = ctx.node()
297
297
298 files = {}
298 files = {}
299 dirs = {}
299 dirs = {}
300 parity = paritygen(web.stripecount)
300 parity = paritygen(web.stripecount)
301
301
302 if path and path[-1] != "/":
302 if path and path[-1] != "/":
303 path += "/"
303 path += "/"
304 l = len(path)
304 l = len(path)
305 abspath = "/" + path
305 abspath = "/" + path
306
306
307 for f, n in mf.iteritems():
307 for f, n in mf.iteritems():
308 if f[:l] != path:
308 if f[:l] != path:
309 continue
309 continue
310 remain = f[l:]
310 remain = f[l:]
311 elements = remain.split('/')
311 elements = remain.split('/')
312 if len(elements) == 1:
312 if len(elements) == 1:
313 files[remain] = f
313 files[remain] = f
314 else:
314 else:
315 h = dirs # need to retain ref to dirs (root)
315 h = dirs # need to retain ref to dirs (root)
316 for elem in elements[0:-1]:
316 for elem in elements[0:-1]:
317 if elem not in h:
317 if elem not in h:
318 h[elem] = {}
318 h[elem] = {}
319 h = h[elem]
319 h = h[elem]
320 if len(h) > 1:
320 if len(h) > 1:
321 break
321 break
322 h[None] = None # denotes files present
322 h[None] = None # denotes files present
323
323
324 if mf and not files and not dirs:
324 if mf and not files and not dirs:
325 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
325 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
326
326
327 def filelist(**map):
327 def filelist(**map):
328 for f in sorted(files):
328 for f in sorted(files):
329 full = files[f]
329 full = files[f]
330
330
331 fctx = ctx.filectx(full)
331 fctx = ctx.filectx(full)
332 yield {"file": full,
332 yield {"file": full,
333 "parity": parity.next(),
333 "parity": parity.next(),
334 "basename": f,
334 "basename": f,
335 "date": fctx.date(),
335 "date": fctx.date(),
336 "size": fctx.size(),
336 "size": fctx.size(),
337 "permissions": mf.flags(full)}
337 "permissions": mf.flags(full)}
338
338
339 def dirlist(**map):
339 def dirlist(**map):
340 for d in sorted(dirs):
340 for d in sorted(dirs):
341
341
342 emptydirs = []
342 emptydirs = []
343 h = dirs[d]
343 h = dirs[d]
344 while isinstance(h, dict) and len(h) == 1:
344 while isinstance(h, dict) and len(h) == 1:
345 k, v = h.items()[0]
345 k, v = h.items()[0]
346 if v:
346 if v:
347 emptydirs.append(k)
347 emptydirs.append(k)
348 h = v
348 h = v
349
349
350 path = "%s%s" % (abspath, d)
350 path = "%s%s" % (abspath, d)
351 yield {"parity": parity.next(),
351 yield {"parity": parity.next(),
352 "path": path,
352 "path": path,
353 "emptydirs": "/".join(emptydirs),
353 "emptydirs": "/".join(emptydirs),
354 "basename": d}
354 "basename": d}
355
355
356 return tmpl("manifest",
356 return tmpl("manifest",
357 rev=ctx.rev(),
357 rev=ctx.rev(),
358 node=hex(node),
358 node=hex(node),
359 path=abspath,
359 path=abspath,
360 up=webutil.up(abspath),
360 up=webutil.up(abspath),
361 upparity=parity.next(),
361 upparity=parity.next(),
362 fentries=filelist,
362 fentries=filelist,
363 dentries=dirlist,
363 dentries=dirlist,
364 archives=web.archivelist(hex(node)),
364 archives=web.archivelist(hex(node)),
365 tags=webutil.nodetagsdict(web.repo, node),
365 tags=webutil.nodetagsdict(web.repo, node),
366 bookmarks=webutil.nodebookmarksdict(web.repo, node),
366 bookmarks=webutil.nodebookmarksdict(web.repo, node),
367 inbranch=webutil.nodeinbranch(web.repo, ctx),
367 inbranch=webutil.nodeinbranch(web.repo, ctx),
368 branches=webutil.nodebranchdict(web.repo, ctx))
368 branches=webutil.nodebranchdict(web.repo, ctx))
369
369
370 def tags(web, req, tmpl):
370 def tags(web, req, tmpl):
371 i = web.repo.tagslist()
371 i = web.repo.tagslist()
372 i.reverse()
372 i.reverse()
373 parity = paritygen(web.stripecount)
373 parity = paritygen(web.stripecount)
374
374
375 def entries(notip=False, limit=0, **map):
375 def entries(notip=False, limit=0, **map):
376 count = 0
376 count = 0
377 for k, n in i:
377 for k, n in i:
378 if notip and k == "tip":
378 if notip and k == "tip":
379 continue
379 continue
380 if limit > 0 and count >= limit:
380 if limit > 0 and count >= limit:
381 continue
381 continue
382 count = count + 1
382 count = count + 1
383 yield {"parity": parity.next(),
383 yield {"parity": parity.next(),
384 "tag": k,
384 "tag": k,
385 "date": web.repo[n].date(),
385 "date": web.repo[n].date(),
386 "node": hex(n)}
386 "node": hex(n)}
387
387
388 return tmpl("tags",
388 return tmpl("tags",
389 node=hex(web.repo.changelog.tip()),
389 node=hex(web.repo.changelog.tip()),
390 entries=lambda **x: entries(False, 0, **x),
390 entries=lambda **x: entries(False, 0, **x),
391 entriesnotip=lambda **x: entries(True, 0, **x),
391 entriesnotip=lambda **x: entries(True, 0, **x),
392 latestentry=lambda **x: entries(True, 1, **x))
392 latestentry=lambda **x: entries(True, 1, **x))
393
393
394 def bookmarks(web, req, tmpl):
394 def bookmarks(web, req, tmpl):
395 i = web.repo._bookmarks.items()
395 i = web.repo._bookmarks.items()
396 parity = paritygen(web.stripecount)
396 parity = paritygen(web.stripecount)
397
397
398 def entries(limit=0, **map):
398 def entries(limit=0, **map):
399 count = 0
399 count = 0
400 for k, n in sorted(i):
400 for k, n in sorted(i):
401 if limit > 0 and count >= limit:
401 if limit > 0 and count >= limit:
402 continue
402 continue
403 count = count + 1
403 count = count + 1
404 yield {"parity": parity.next(),
404 yield {"parity": parity.next(),
405 "bookmark": k,
405 "bookmark": k,
406 "date": web.repo[n].date(),
406 "date": web.repo[n].date(),
407 "node": hex(n)}
407 "node": hex(n)}
408
408
409 return tmpl("bookmarks",
409 return tmpl("bookmarks",
410 node=hex(web.repo.changelog.tip()),
410 node=hex(web.repo.changelog.tip()),
411 entries=lambda **x: entries(0, **x),
411 entries=lambda **x: entries(0, **x),
412 latestentry=lambda **x: entries(1, **x))
412 latestentry=lambda **x: entries(1, **x))
413
413
414 def branches(web, req, tmpl):
414 def branches(web, req, tmpl):
415 tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems())
415 tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems())
416 heads = web.repo.heads()
416 heads = web.repo.heads()
417 parity = paritygen(web.stripecount)
417 parity = paritygen(web.stripecount)
418 sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev())
418 sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev())
419
419
420 def entries(limit, **map):
420 def entries(limit, **map):
421 count = 0
421 count = 0
422 for ctx in sorted(tips, key=sortkey, reverse=True):
422 for ctx in sorted(tips, key=sortkey, reverse=True):
423 if limit > 0 and count >= limit:
423 if limit > 0 and count >= limit:
424 return
424 return
425 count += 1
425 count += 1
426 if ctx.node() not in heads:
426 if ctx.node() not in heads:
427 status = 'inactive'
427 status = 'inactive'
428 elif not web.repo.branchheads(ctx.branch()):
428 elif not web.repo.branchheads(ctx.branch()):
429 status = 'closed'
429 status = 'closed'
430 else:
430 else:
431 status = 'open'
431 status = 'open'
432 yield {'parity': parity.next(),
432 yield {'parity': parity.next(),
433 'branch': ctx.branch(),
433 'branch': ctx.branch(),
434 'status': status,
434 'status': status,
435 'node': ctx.hex(),
435 'node': ctx.hex(),
436 'date': ctx.date()}
436 'date': ctx.date()}
437
437
438 return tmpl('branches', node=hex(web.repo.changelog.tip()),
438 return tmpl('branches', node=hex(web.repo.changelog.tip()),
439 entries=lambda **x: entries(0, **x),
439 entries=lambda **x: entries(0, **x),
440 latestentry=lambda **x: entries(1, **x))
440 latestentry=lambda **x: entries(1, **x))
441
441
442 def summary(web, req, tmpl):
442 def summary(web, req, tmpl):
443 i = web.repo.tagslist()
443 i = web.repo.tagslist()
444 i.reverse()
444 i.reverse()
445
445
446 def tagentries(**map):
446 def tagentries(**map):
447 parity = paritygen(web.stripecount)
447 parity = paritygen(web.stripecount)
448 count = 0
448 count = 0
449 for k, n in i:
449 for k, n in i:
450 if k == "tip": # skip tip
450 if k == "tip": # skip tip
451 continue
451 continue
452
452
453 count += 1
453 count += 1
454 if count > 10: # limit to 10 tags
454 if count > 10: # limit to 10 tags
455 break
455 break
456
456
457 yield tmpl("tagentry",
457 yield tmpl("tagentry",
458 parity=parity.next(),
458 parity=parity.next(),
459 tag=k,
459 tag=k,
460 node=hex(n),
460 node=hex(n),
461 date=web.repo[n].date())
461 date=web.repo[n].date())
462
462
463 def bookmarks(**map):
464 parity = paritygen(web.stripecount)
465 b = web.repo._bookmarks.items()
466 for k, n in sorted(b)[:10]: # limit to 10 bookmarks
467 yield {'parity': parity.next(),
468 'bookmark': k,
469 'date': web.repo[n].date(),
470 'node': hex(n)}
471
463 def branches(**map):
472 def branches(**map):
464 parity = paritygen(web.stripecount)
473 parity = paritygen(web.stripecount)
465
474
466 b = web.repo.branchtags()
475 b = web.repo.branchtags()
467 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
476 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
468 for r, n, t in sorted(l):
477 for r, n, t in sorted(l):
469 yield {'parity': parity.next(),
478 yield {'parity': parity.next(),
470 'branch': t,
479 'branch': t,
471 'node': hex(n),
480 'node': hex(n),
472 'date': web.repo[n].date()}
481 'date': web.repo[n].date()}
473
482
474 def changelist(**map):
483 def changelist(**map):
475 parity = paritygen(web.stripecount, offset=start - end)
484 parity = paritygen(web.stripecount, offset=start - end)
476 l = [] # build a list in forward order for efficiency
485 l = [] # build a list in forward order for efficiency
477 for i in xrange(start, end):
486 for i in xrange(start, end):
478 ctx = web.repo[i]
487 ctx = web.repo[i]
479 n = ctx.node()
488 n = ctx.node()
480 hn = hex(n)
489 hn = hex(n)
481
490
482 l.insert(0, tmpl(
491 l.insert(0, tmpl(
483 'shortlogentry',
492 'shortlogentry',
484 parity=parity.next(),
493 parity=parity.next(),
485 author=ctx.user(),
494 author=ctx.user(),
486 desc=ctx.description(),
495 desc=ctx.description(),
487 date=ctx.date(),
496 date=ctx.date(),
488 rev=i,
497 rev=i,
489 node=hn,
498 node=hn,
490 tags=webutil.nodetagsdict(web.repo, n),
499 tags=webutil.nodetagsdict(web.repo, n),
491 bookmarks=webutil.nodebookmarksdict(web.repo, n),
500 bookmarks=webutil.nodebookmarksdict(web.repo, n),
492 inbranch=webutil.nodeinbranch(web.repo, ctx),
501 inbranch=webutil.nodeinbranch(web.repo, ctx),
493 branches=webutil.nodebranchdict(web.repo, ctx)))
502 branches=webutil.nodebranchdict(web.repo, ctx)))
494
503
495 yield l
504 yield l
496
505
497 tip = web.repo['tip']
506 tip = web.repo['tip']
498 count = len(web.repo)
507 count = len(web.repo)
499 start = max(0, count - web.maxchanges)
508 start = max(0, count - web.maxchanges)
500 end = min(count, start + web.maxchanges)
509 end = min(count, start + web.maxchanges)
501
510
502 return tmpl("summary",
511 return tmpl("summary",
503 desc=web.config("web", "description", "unknown"),
512 desc=web.config("web", "description", "unknown"),
504 owner=get_contact(web.config) or "unknown",
513 owner=get_contact(web.config) or "unknown",
505 lastchange=tip.date(),
514 lastchange=tip.date(),
506 tags=tagentries,
515 tags=tagentries,
516 bookmarks=bookmarks,
507 branches=branches,
517 branches=branches,
508 shortlog=changelist,
518 shortlog=changelist,
509 node=tip.hex(),
519 node=tip.hex(),
510 archives=web.archivelist("tip"))
520 archives=web.archivelist("tip"))
511
521
512 def filediff(web, req, tmpl):
522 def filediff(web, req, tmpl):
513 fctx, ctx = None, None
523 fctx, ctx = None, None
514 try:
524 try:
515 fctx = webutil.filectx(web.repo, req)
525 fctx = webutil.filectx(web.repo, req)
516 except LookupError:
526 except LookupError:
517 ctx = webutil.changectx(web.repo, req)
527 ctx = webutil.changectx(web.repo, req)
518 path = webutil.cleanpath(web.repo, req.form['file'][0])
528 path = webutil.cleanpath(web.repo, req.form['file'][0])
519 if path not in ctx.files():
529 if path not in ctx.files():
520 raise
530 raise
521
531
522 if fctx is not None:
532 if fctx is not None:
523 n = fctx.node()
533 n = fctx.node()
524 path = fctx.path()
534 path = fctx.path()
525 else:
535 else:
526 n = ctx.node()
536 n = ctx.node()
527 # path already defined in except clause
537 # path already defined in except clause
528
538
529 parity = paritygen(web.stripecount)
539 parity = paritygen(web.stripecount)
530 style = web.config('web', 'style', 'paper')
540 style = web.config('web', 'style', 'paper')
531 if 'style' in req.form:
541 if 'style' in req.form:
532 style = req.form['style'][0]
542 style = req.form['style'][0]
533
543
534 diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity, style)
544 diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity, style)
535 rename = fctx and webutil.renamelink(fctx) or []
545 rename = fctx and webutil.renamelink(fctx) or []
536 ctx = fctx and fctx or ctx
546 ctx = fctx and fctx or ctx
537 return tmpl("filediff",
547 return tmpl("filediff",
538 file=path,
548 file=path,
539 node=hex(n),
549 node=hex(n),
540 rev=ctx.rev(),
550 rev=ctx.rev(),
541 date=ctx.date(),
551 date=ctx.date(),
542 desc=ctx.description(),
552 desc=ctx.description(),
543 author=ctx.user(),
553 author=ctx.user(),
544 rename=rename,
554 rename=rename,
545 branch=webutil.nodebranchnodefault(ctx),
555 branch=webutil.nodebranchnodefault(ctx),
546 parent=webutil.parents(ctx),
556 parent=webutil.parents(ctx),
547 child=webutil.children(ctx),
557 child=webutil.children(ctx),
548 diff=diffs)
558 diff=diffs)
549
559
550 diff = filediff
560 diff = filediff
551
561
552 def annotate(web, req, tmpl):
562 def annotate(web, req, tmpl):
553 fctx = webutil.filectx(web.repo, req)
563 fctx = webutil.filectx(web.repo, req)
554 f = fctx.path()
564 f = fctx.path()
555 parity = paritygen(web.stripecount)
565 parity = paritygen(web.stripecount)
556
566
557 def annotate(**map):
567 def annotate(**map):
558 last = None
568 last = None
559 if binary(fctx.data()):
569 if binary(fctx.data()):
560 mt = (mimetypes.guess_type(fctx.path())[0]
570 mt = (mimetypes.guess_type(fctx.path())[0]
561 or 'application/octet-stream')
571 or 'application/octet-stream')
562 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
572 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
563 '(binary:%s)' % mt)])
573 '(binary:%s)' % mt)])
564 else:
574 else:
565 lines = enumerate(fctx.annotate(follow=True, linenumber=True))
575 lines = enumerate(fctx.annotate(follow=True, linenumber=True))
566 for lineno, ((f, targetline), l) in lines:
576 for lineno, ((f, targetline), l) in lines:
567 fnode = f.filenode()
577 fnode = f.filenode()
568
578
569 if last != fnode:
579 if last != fnode:
570 last = fnode
580 last = fnode
571
581
572 yield {"parity": parity.next(),
582 yield {"parity": parity.next(),
573 "node": hex(f.node()),
583 "node": hex(f.node()),
574 "rev": f.rev(),
584 "rev": f.rev(),
575 "author": f.user(),
585 "author": f.user(),
576 "desc": f.description(),
586 "desc": f.description(),
577 "file": f.path(),
587 "file": f.path(),
578 "targetline": targetline,
588 "targetline": targetline,
579 "line": l,
589 "line": l,
580 "lineid": "l%d" % (lineno + 1),
590 "lineid": "l%d" % (lineno + 1),
581 "linenumber": "% 6d" % (lineno + 1),
591 "linenumber": "% 6d" % (lineno + 1),
582 "revdate": f.date()}
592 "revdate": f.date()}
583
593
584 return tmpl("fileannotate",
594 return tmpl("fileannotate",
585 file=f,
595 file=f,
586 annotate=annotate,
596 annotate=annotate,
587 path=webutil.up(f),
597 path=webutil.up(f),
588 rev=fctx.rev(),
598 rev=fctx.rev(),
589 node=hex(fctx.node()),
599 node=hex(fctx.node()),
590 author=fctx.user(),
600 author=fctx.user(),
591 date=fctx.date(),
601 date=fctx.date(),
592 desc=fctx.description(),
602 desc=fctx.description(),
593 rename=webutil.renamelink(fctx),
603 rename=webutil.renamelink(fctx),
594 branch=webutil.nodebranchnodefault(fctx),
604 branch=webutil.nodebranchnodefault(fctx),
595 parent=webutil.parents(fctx),
605 parent=webutil.parents(fctx),
596 child=webutil.children(fctx),
606 child=webutil.children(fctx),
597 permissions=fctx.manifest().flags(f))
607 permissions=fctx.manifest().flags(f))
598
608
599 def filelog(web, req, tmpl):
609 def filelog(web, req, tmpl):
600
610
601 try:
611 try:
602 fctx = webutil.filectx(web.repo, req)
612 fctx = webutil.filectx(web.repo, req)
603 f = fctx.path()
613 f = fctx.path()
604 fl = fctx.filelog()
614 fl = fctx.filelog()
605 except error.LookupError:
615 except error.LookupError:
606 f = webutil.cleanpath(web.repo, req.form['file'][0])
616 f = webutil.cleanpath(web.repo, req.form['file'][0])
607 fl = web.repo.file(f)
617 fl = web.repo.file(f)
608 numrevs = len(fl)
618 numrevs = len(fl)
609 if not numrevs: # file doesn't exist at all
619 if not numrevs: # file doesn't exist at all
610 raise
620 raise
611 rev = webutil.changectx(web.repo, req).rev()
621 rev = webutil.changectx(web.repo, req).rev()
612 first = fl.linkrev(0)
622 first = fl.linkrev(0)
613 if rev < first: # current rev is from before file existed
623 if rev < first: # current rev is from before file existed
614 raise
624 raise
615 frev = numrevs - 1
625 frev = numrevs - 1
616 while fl.linkrev(frev) > rev:
626 while fl.linkrev(frev) > rev:
617 frev -= 1
627 frev -= 1
618 fctx = web.repo.filectx(f, fl.linkrev(frev))
628 fctx = web.repo.filectx(f, fl.linkrev(frev))
619
629
620 revcount = web.maxshortchanges
630 revcount = web.maxshortchanges
621 if 'revcount' in req.form:
631 if 'revcount' in req.form:
622 revcount = int(req.form.get('revcount', [revcount])[0])
632 revcount = int(req.form.get('revcount', [revcount])[0])
623 tmpl.defaults['sessionvars']['revcount'] = revcount
633 tmpl.defaults['sessionvars']['revcount'] = revcount
624
634
625 lessvars = copy.copy(tmpl.defaults['sessionvars'])
635 lessvars = copy.copy(tmpl.defaults['sessionvars'])
626 lessvars['revcount'] = revcount / 2
636 lessvars['revcount'] = revcount / 2
627 morevars = copy.copy(tmpl.defaults['sessionvars'])
637 morevars = copy.copy(tmpl.defaults['sessionvars'])
628 morevars['revcount'] = revcount * 2
638 morevars['revcount'] = revcount * 2
629
639
630 count = fctx.filerev() + 1
640 count = fctx.filerev() + 1
631 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
641 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
632 end = min(count, start + revcount) # last rev on this page
642 end = min(count, start + revcount) # last rev on this page
633 parity = paritygen(web.stripecount, offset=start - end)
643 parity = paritygen(web.stripecount, offset=start - end)
634
644
635 def entries(limit=0, **map):
645 def entries(limit=0, **map):
636 l = []
646 l = []
637
647
638 repo = web.repo
648 repo = web.repo
639 for i in xrange(start, end):
649 for i in xrange(start, end):
640 iterfctx = fctx.filectx(i)
650 iterfctx = fctx.filectx(i)
641
651
642 l.insert(0, {"parity": parity.next(),
652 l.insert(0, {"parity": parity.next(),
643 "filerev": i,
653 "filerev": i,
644 "file": f,
654 "file": f,
645 "node": hex(iterfctx.node()),
655 "node": hex(iterfctx.node()),
646 "author": iterfctx.user(),
656 "author": iterfctx.user(),
647 "date": iterfctx.date(),
657 "date": iterfctx.date(),
648 "rename": webutil.renamelink(iterfctx),
658 "rename": webutil.renamelink(iterfctx),
649 "parent": webutil.parents(iterfctx),
659 "parent": webutil.parents(iterfctx),
650 "child": webutil.children(iterfctx),
660 "child": webutil.children(iterfctx),
651 "desc": iterfctx.description(),
661 "desc": iterfctx.description(),
652 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
662 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
653 "bookmarks": webutil.nodebookmarksdict(
663 "bookmarks": webutil.nodebookmarksdict(
654 repo, iterfctx.node()),
664 repo, iterfctx.node()),
655 "branch": webutil.nodebranchnodefault(iterfctx),
665 "branch": webutil.nodebranchnodefault(iterfctx),
656 "inbranch": webutil.nodeinbranch(repo, iterfctx),
666 "inbranch": webutil.nodeinbranch(repo, iterfctx),
657 "branches": webutil.nodebranchdict(repo, iterfctx)})
667 "branches": webutil.nodebranchdict(repo, iterfctx)})
658
668
659 if limit > 0:
669 if limit > 0:
660 l = l[:limit]
670 l = l[:limit]
661
671
662 for e in l:
672 for e in l:
663 yield e
673 yield e
664
674
665 nodefunc = lambda x: fctx.filectx(fileid=x)
675 nodefunc = lambda x: fctx.filectx(fileid=x)
666 nav = webutil.revnavgen(end - 1, revcount, count, nodefunc)
676 nav = webutil.revnavgen(end - 1, revcount, count, nodefunc)
667 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
677 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
668 entries=lambda **x: entries(limit=0, **x),
678 entries=lambda **x: entries(limit=0, **x),
669 latestentry=lambda **x: entries(limit=1, **x),
679 latestentry=lambda **x: entries(limit=1, **x),
670 revcount=revcount, morevars=morevars, lessvars=lessvars)
680 revcount=revcount, morevars=morevars, lessvars=lessvars)
671
681
672 def archive(web, req, tmpl):
682 def archive(web, req, tmpl):
673 type_ = req.form.get('type', [None])[0]
683 type_ = req.form.get('type', [None])[0]
674 allowed = web.configlist("web", "allow_archive")
684 allowed = web.configlist("web", "allow_archive")
675 key = req.form['node'][0]
685 key = req.form['node'][0]
676
686
677 if type_ not in web.archives:
687 if type_ not in web.archives:
678 msg = 'Unsupported archive type: %s' % type_
688 msg = 'Unsupported archive type: %s' % type_
679 raise ErrorResponse(HTTP_NOT_FOUND, msg)
689 raise ErrorResponse(HTTP_NOT_FOUND, msg)
680
690
681 if not ((type_ in allowed or
691 if not ((type_ in allowed or
682 web.configbool("web", "allow" + type_, False))):
692 web.configbool("web", "allow" + type_, False))):
683 msg = 'Archive type not allowed: %s' % type_
693 msg = 'Archive type not allowed: %s' % type_
684 raise ErrorResponse(HTTP_FORBIDDEN, msg)
694 raise ErrorResponse(HTTP_FORBIDDEN, msg)
685
695
686 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
696 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
687 cnode = web.repo.lookup(key)
697 cnode = web.repo.lookup(key)
688 arch_version = key
698 arch_version = key
689 if cnode == key or key == 'tip':
699 if cnode == key or key == 'tip':
690 arch_version = short(cnode)
700 arch_version = short(cnode)
691 name = "%s-%s" % (reponame, arch_version)
701 name = "%s-%s" % (reponame, arch_version)
692 mimetype, artype, extension, encoding = web.archive_specs[type_]
702 mimetype, artype, extension, encoding = web.archive_specs[type_]
693 headers = [
703 headers = [
694 ('Content-Type', mimetype),
704 ('Content-Type', mimetype),
695 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
705 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
696 ]
706 ]
697 if encoding:
707 if encoding:
698 headers.append(('Content-Encoding', encoding))
708 headers.append(('Content-Encoding', encoding))
699 req.header(headers)
709 req.header(headers)
700 req.respond(HTTP_OK)
710 req.respond(HTTP_OK)
701 archival.archive(web.repo, req, cnode, artype, prefix=name)
711 archival.archive(web.repo, req, cnode, artype, prefix=name)
702 return []
712 return []
703
713
704
714
705 def static(web, req, tmpl):
715 def static(web, req, tmpl):
706 fname = req.form['file'][0]
716 fname = req.form['file'][0]
707 # a repo owner may set web.static in .hg/hgrc to get any file
717 # a repo owner may set web.static in .hg/hgrc to get any file
708 # readable by the user running the CGI script
718 # readable by the user running the CGI script
709 static = web.config("web", "static", None, untrusted=False)
719 static = web.config("web", "static", None, untrusted=False)
710 if not static:
720 if not static:
711 tp = web.templatepath or templater.templatepath()
721 tp = web.templatepath or templater.templatepath()
712 if isinstance(tp, str):
722 if isinstance(tp, str):
713 tp = [tp]
723 tp = [tp]
714 static = [os.path.join(p, 'static') for p in tp]
724 static = [os.path.join(p, 'static') for p in tp]
715 return [staticfile(static, fname, req)]
725 return [staticfile(static, fname, req)]
716
726
717 def graph(web, req, tmpl):
727 def graph(web, req, tmpl):
718
728
719 rev = webutil.changectx(web.repo, req).rev()
729 rev = webutil.changectx(web.repo, req).rev()
720 bg_height = 39
730 bg_height = 39
721 revcount = web.maxshortchanges
731 revcount = web.maxshortchanges
722 if 'revcount' in req.form:
732 if 'revcount' in req.form:
723 revcount = int(req.form.get('revcount', [revcount])[0])
733 revcount = int(req.form.get('revcount', [revcount])[0])
724 tmpl.defaults['sessionvars']['revcount'] = revcount
734 tmpl.defaults['sessionvars']['revcount'] = revcount
725
735
726 lessvars = copy.copy(tmpl.defaults['sessionvars'])
736 lessvars = copy.copy(tmpl.defaults['sessionvars'])
727 lessvars['revcount'] = revcount / 2
737 lessvars['revcount'] = revcount / 2
728 morevars = copy.copy(tmpl.defaults['sessionvars'])
738 morevars = copy.copy(tmpl.defaults['sessionvars'])
729 morevars['revcount'] = revcount * 2
739 morevars['revcount'] = revcount * 2
730
740
731 max_rev = len(web.repo) - 1
741 max_rev = len(web.repo) - 1
732 revcount = min(max_rev, revcount)
742 revcount = min(max_rev, revcount)
733 revnode = web.repo.changelog.node(rev)
743 revnode = web.repo.changelog.node(rev)
734 revnode_hex = hex(revnode)
744 revnode_hex = hex(revnode)
735 uprev = min(max_rev, rev + revcount)
745 uprev = min(max_rev, rev + revcount)
736 downrev = max(0, rev - revcount)
746 downrev = max(0, rev - revcount)
737 count = len(web.repo)
747 count = len(web.repo)
738 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
748 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
739 startrev = rev
749 startrev = rev
740 # if starting revision is less than 60 set it to uprev
750 # if starting revision is less than 60 set it to uprev
741 if rev < web.maxshortchanges:
751 if rev < web.maxshortchanges:
742 startrev = uprev
752 startrev = uprev
743
753
744 dag = graphmod.revisions(web.repo, startrev, downrev)
754 dag = graphmod.revisions(web.repo, startrev, downrev)
745 tree = list(graphmod.colored(dag))
755 tree = list(graphmod.colored(dag))
746 canvasheight = (len(tree) + 1) * bg_height - 27
756 canvasheight = (len(tree) + 1) * bg_height - 27
747 data = []
757 data = []
748 for (id, type, ctx, vtx, edges) in tree:
758 for (id, type, ctx, vtx, edges) in tree:
749 if type != graphmod.CHANGESET:
759 if type != graphmod.CHANGESET:
750 continue
760 continue
751 node = short(ctx.node())
761 node = short(ctx.node())
752 age = templatefilters.age(ctx.date())
762 age = templatefilters.age(ctx.date())
753 desc = templatefilters.firstline(ctx.description())
763 desc = templatefilters.firstline(ctx.description())
754 desc = cgi.escape(templatefilters.nonempty(desc))
764 desc = cgi.escape(templatefilters.nonempty(desc))
755 user = cgi.escape(templatefilters.person(ctx.user()))
765 user = cgi.escape(templatefilters.person(ctx.user()))
756 branch = ctx.branch()
766 branch = ctx.branch()
757 branch = branch, web.repo.branchtags().get(branch) == ctx.node()
767 branch = branch, web.repo.branchtags().get(branch) == ctx.node()
758 data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(),
768 data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(),
759 ctx.bookmarks()))
769 ctx.bookmarks()))
760
770
761 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
771 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
762 lessvars=lessvars, morevars=morevars, downrev=downrev,
772 lessvars=lessvars, morevars=morevars, downrev=downrev,
763 canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
773 canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
764 node=revnode_hex, changenav=changenav)
774 node=revnode_hex, changenav=changenav)
765
775
766 def _getdoc(e):
776 def _getdoc(e):
767 doc = e[0].__doc__
777 doc = e[0].__doc__
768 if doc:
778 if doc:
769 doc = doc.split('\n')[0]
779 doc = doc.split('\n')[0]
770 else:
780 else:
771 doc = _('(no help text available)')
781 doc = _('(no help text available)')
772 return doc
782 return doc
773
783
774 def help(web, req, tmpl):
784 def help(web, req, tmpl):
775 from mercurial import commands # avoid cycle
785 from mercurial import commands # avoid cycle
776
786
777 topicname = req.form.get('node', [None])[0]
787 topicname = req.form.get('node', [None])[0]
778 if not topicname:
788 if not topicname:
779 topic = []
789 topic = []
780
790
781 def topics(**map):
791 def topics(**map):
782 for entries, summary, _ in helpmod.helptable:
792 for entries, summary, _ in helpmod.helptable:
783 entries = sorted(entries, key=len)
793 entries = sorted(entries, key=len)
784 yield {'topic': entries[-1], 'summary': summary}
794 yield {'topic': entries[-1], 'summary': summary}
785
795
786 early, other = [], []
796 early, other = [], []
787 primary = lambda s: s.split('|')[0]
797 primary = lambda s: s.split('|')[0]
788 for c, e in commands.table.iteritems():
798 for c, e in commands.table.iteritems():
789 doc = _getdoc(e)
799 doc = _getdoc(e)
790 if 'DEPRECATED' in doc or c.startswith('debug'):
800 if 'DEPRECATED' in doc or c.startswith('debug'):
791 continue
801 continue
792 cmd = primary(c)
802 cmd = primary(c)
793 if cmd.startswith('^'):
803 if cmd.startswith('^'):
794 early.append((cmd[1:], doc))
804 early.append((cmd[1:], doc))
795 else:
805 else:
796 other.append((cmd, doc))
806 other.append((cmd, doc))
797
807
798 early.sort()
808 early.sort()
799 other.sort()
809 other.sort()
800
810
801 def earlycommands(**map):
811 def earlycommands(**map):
802 for c, doc in early:
812 for c, doc in early:
803 yield {'topic': c, 'summary': doc}
813 yield {'topic': c, 'summary': doc}
804
814
805 def othercommands(**map):
815 def othercommands(**map):
806 for c, doc in other:
816 for c, doc in other:
807 yield {'topic': c, 'summary': doc}
817 yield {'topic': c, 'summary': doc}
808
818
809 return tmpl('helptopics', topics=topics, earlycommands=earlycommands,
819 return tmpl('helptopics', topics=topics, earlycommands=earlycommands,
810 othercommands=othercommands, title='Index')
820 othercommands=othercommands, title='Index')
811
821
812 u = webutil.wsgiui()
822 u = webutil.wsgiui()
813 u.pushbuffer()
823 u.pushbuffer()
814 try:
824 try:
815 commands.help_(u, topicname)
825 commands.help_(u, topicname)
816 except error.UnknownCommand:
826 except error.UnknownCommand:
817 raise ErrorResponse(HTTP_NOT_FOUND)
827 raise ErrorResponse(HTTP_NOT_FOUND)
818 doc = u.popbuffer()
828 doc = u.popbuffer()
819 return tmpl('help', topic=topicname, doc=doc)
829 return tmpl('help', topic=topicname, doc=doc)
@@ -1,60 +1,66
1 {header}
1 {header}
2 <title>{repo|escape}: Summary</title>
2 <title>{repo|escape}: Summary</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}"/>
4 href="{url}atom-log" title="Atom feed for {repo|escape}"/>
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}"/>
6 href="{url}rss-log" title="RSS feed for {repo|escape}"/>
7 </head>
7 </head>
8 <body>
8 <body>
9
9
10 <div class="page_header">
10 <div class="page_header">
11 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / summary
11 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / summary
12
12
13 <form action="{url}log">
13 <form action="{url}log">
14 {sessionvars%hiddenformentry}
14 {sessionvars%hiddenformentry}
15 <div class="search">
15 <div class="search">
16 <input type="text" name="rev" />
16 <input type="text" name="rev" />
17 </div>
17 </div>
18 </form>
18 </form>
19 </div>
19 </div>
20
20
21 <div class="page_nav">
21 <div class="page_nav">
22 summary |
22 summary |
23 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
23 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
24 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
24 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
25 <a href="{url}graph{sessionvars%urlparameter}">graph</a> |
25 <a href="{url}graph{sessionvars%urlparameter}">graph</a> |
26 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
26 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
27 <a href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a> |
27 <a href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a> |
28 <a href="{url}branches{sessionvars%urlparameter}">branches</a> |
28 <a href="{url}branches{sessionvars%urlparameter}">branches</a> |
29 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>{archives%archiveentry} |
29 <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>{archives%archiveentry} |
30 <a href="{url}help{sessionvars%urlparameter}">help</a>
30 <a href="{url}help{sessionvars%urlparameter}">help</a>
31 <br/>
31 <br/>
32 </div>
32 </div>
33
33
34 <div class="title">&nbsp;</div>
34 <div class="title">&nbsp;</div>
35 <table cellspacing="0">
35 <table cellspacing="0">
36 <tr><td>description</td><td>{desc}</td></tr>
36 <tr><td>description</td><td>{desc}</td></tr>
37 <tr><td>owner</td><td>{owner|obfuscate}</td></tr>
37 <tr><td>owner</td><td>{owner|obfuscate}</td></tr>
38 <tr><td>last change</td><td>{lastchange|rfc822date}</td></tr>
38 <tr><td>last change</td><td>{lastchange|rfc822date}</td></tr>
39 </table>
39 </table>
40
40
41 <div><a class="title" href="{url}shortlog{sessionvars%urlparameter}">changes</a></div>
41 <div><a class="title" href="{url}shortlog{sessionvars%urlparameter}">changes</a></div>
42 <table cellspacing="0">
42 <table cellspacing="0">
43 {shortlog}
43 {shortlog}
44 <tr class="light"><td colspan="4"><a class="list" href="{url}shortlog{sessionvars%urlparameter}">...</a></td></tr>
44 <tr class="light"><td colspan="4"><a class="list" href="{url}shortlog{sessionvars%urlparameter}">...</a></td></tr>
45 </table>
45 </table>
46
46
47 <div><a class="title" href="{url}tags{sessionvars%urlparameter}">tags</a></div>
47 <div><a class="title" href="{url}tags{sessionvars%urlparameter}">tags</a></div>
48 <table cellspacing="0">
48 <table cellspacing="0">
49 {tags}
49 {tags}
50 <tr class="light"><td colspan="3"><a class="list" href="{url}tags{sessionvars%urlparameter}">...</a></td></tr>
50 <tr class="light"><td colspan="3"><a class="list" href="{url}tags{sessionvars%urlparameter}">...</a></td></tr>
51 </table>
51 </table>
52
52
53 <div><a class="title" href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a></div>
54 <table cellspacing="0">
55 {bookmarks%bookmarkentry}
56 <tr class="light"><td colspan="3"><a class="list" href="{url}bookmarks{sessionvars%urlparameter}">...</a></td></tr>
57 </table>
58
53 <div><a class="title" href="#">branches</a></div>
59 <div><a class="title" href="#">branches</a></div>
54 <table cellspacing="0">
60 <table cellspacing="0">
55 {branches%branchentry}
61 {branches%branchentry}
56 <tr class="light">
62 <tr class="light">
57 <td colspan="4"><a class="list" href="#">...</a></td>
63 <td colspan="4"><a class="list" href="#">...</a></td>
58 </tr>
64 </tr>
59 </table>
65 </table>
60 {footer}
66 {footer}
@@ -1,68 +1,76
1 {header}
1 {header}
2 <title>{repo|escape}: Summary</title>
2 <title>{repo|escape}: Summary</title>
3 <link rel="alternate" type="application/atom+xml" href="{url}atom-log" title="Atom feed for {repo|escape}"/>
3 <link rel="alternate" type="application/atom+xml" href="{url}atom-log" title="Atom feed for {repo|escape}"/>
4 <link rel="alternate" type="application/rss+xml" href="{url}rss-log" title="RSS feed for {repo|escape}"/>
4 <link rel="alternate" type="application/rss+xml" href="{url}rss-log" title="RSS feed for {repo|escape}"/>
5 </head>
5 </head>
6
6
7 <body>
7 <body>
8 <div id="container">
8 <div id="container">
9 <div class="page-header">
9 <div class="page-header">
10 <h1><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / summary</h1>
10 <h1><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / summary</h1>
11
11
12 <form action="{url}log">
12 <form action="{url}log">
13 {sessionvars%hiddenformentry}
13 {sessionvars%hiddenformentry}
14 <dl class="search">
14 <dl class="search">
15 <dt><label>Search: </label></dt>
15 <dt><label>Search: </label></dt>
16 <dd><input type="text" name="rev" /></dd>
16 <dd><input type="text" name="rev" /></dd>
17 </dl>
17 </dl>
18 </form>
18 </form>
19
19
20 <ul class="page-nav">
20 <ul class="page-nav">
21 <li class="current">summary</li>
21 <li class="current">summary</li>
22 <li><a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a></li>
22 <li><a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a></li>
23 <li><a href="{url}log{sessionvars%urlparameter}">changelog</a></li>
23 <li><a href="{url}log{sessionvars%urlparameter}">changelog</a></li>
24 <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
24 <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
25 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
25 <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
26 <li><a href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a></li>
26 <li><a href="{url}bookmarks{sessionvars%urlparameter}">bookmarks</a></li>
27 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
27 <li><a href="{url}branches{sessionvars%urlparameter}">branches</a></li>
28 <li><a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a></li>
28 <li><a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a></li>
29 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
29 <li><a href="{url}help{sessionvars%urlparameter}">help</a></li>
30 </ul>
30 </ul>
31 </div>
31 </div>
32
32
33 <h2 class="no-link no-border">Mercurial Repository Overview</h2>
33 <h2 class="no-link no-border">Mercurial Repository Overview</h2>
34 <dl class="overview">
34 <dl class="overview">
35 <dt>name</dt>
35 <dt>name</dt>
36 <dd>{repo|escape}</dd>
36 <dd>{repo|escape}</dd>
37 <dt>description</dt>
37 <dt>description</dt>
38 <dd>{desc}</dd>
38 <dd>{desc}</dd>
39 <dt>owner</dt>
39 <dt>owner</dt>
40 <dd>{owner|obfuscate}</dd>
40 <dd>{owner|obfuscate}</dd>
41 <dt>last change</dt>
41 <dt>last change</dt>
42 <dd>{lastchange|rfc822date}</dd>
42 <dd>{lastchange|rfc822date}</dd>
43 </dl>
43 </dl>
44
44
45 <h2><a href="{url}shortlog{sessionvars%urlparameter}">Changes</a></h2>
45 <h2><a href="{url}shortlog{sessionvars%urlparameter}">Changes</a></h2>
46 <table>
46 <table>
47 {shortlog}
47 {shortlog}
48 <tr class="light">
48 <tr class="light">
49 <td colspan="4"><a class="list" href="{url}shortlog{sessionvars%urlparameter}">...</a></td>
49 <td colspan="4"><a class="list" href="{url}shortlog{sessionvars%urlparameter}">...</a></td>
50 </tr>
50 </tr>
51 </table>
51 </table>
52
52
53 <h2><a href="{url}tags{sessionvars%urlparameter}">Tags</a></h2>
53 <h2><a href="{url}tags{sessionvars%urlparameter}">Tags</a></h2>
54 <table>
54 <table>
55 {tags}
55 {tags}
56 <tr class="light">
56 <tr class="light">
57 <td colspan="3"><a class="list" href="{url}tags{sessionvars%urlparameter}">...</a></td>
57 <td colspan="3"><a class="list" href="{url}tags{sessionvars%urlparameter}">...</a></td>
58 </tr>
58 </tr>
59 </table>
59 </table>
60
60
61 <h2><a href="{url}bookmarks{sessionvars%urlparameter}">Bookmarks</a></h2>
62 <table>
63 {bookmarks%bookmarkentry}
64 <tr class="light">
65 <td colspan="3"><a class="list" href="{url}bookmarks{sessionvars%urlparameter}">...</a></td>
66 </tr>
67 </table>
68
61 <h2 class="no-link">Branches</h2>
69 <h2 class="no-link">Branches</h2>
62 <table>
70 <table>
63 {branches%branchentry}
71 {branches%branchentry}
64 <tr class="light">
72 <tr class="light">
65 <td colspan="4"><a class="list" href="#">...</a></td>
73 <td colspan="4"><a class="list" href="#">...</a></td>
66 </tr>
74 </tr>
67 </table>
75 </table>
68 {footer}
76 {footer}
@@ -1,1095 +1,1119
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 $ hg bookmark something
19 $ hg bookmark -r0 anotherthing
19 $ hg bookmark -r0 anotherthing
20 $ echo another > foo
20 $ echo another > foo
21 $ hg branch stable
21 $ hg branch stable
22 marked working directory as branch stable
22 marked working directory as branch stable
23 $ hg ci -Ambranch
23 $ hg ci -Ambranch
24 $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
24 $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
25 $ cat hg.pid >> $DAEMON_PIDS
25 $ cat hg.pid >> $DAEMON_PIDS
26
26
27 Logs and changes
27 Logs and changes
28
28
29 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom'
29 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom'
30 200 Script output follows
30 200 Script output follows
31
31
32 <?xml version="1.0" encoding="ascii"?>
32 <?xml version="1.0" encoding="ascii"?>
33 <feed xmlns="http://www.w3.org/2005/Atom">
33 <feed xmlns="http://www.w3.org/2005/Atom">
34 <!-- Changelog -->
34 <!-- Changelog -->
35 <id>http://*:$HGPORT/</id> (glob)
35 <id>http://*:$HGPORT/</id> (glob)
36 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
36 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
37 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
37 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
38 <title>test Changelog</title>
38 <title>test Changelog</title>
39 <updated>1970-01-01T00:00:00+00:00</updated>
39 <updated>1970-01-01T00:00:00+00:00</updated>
40
40
41 <entry>
41 <entry>
42 <title>branch</title>
42 <title>branch</title>
43 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
43 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
44 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
44 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
45 <author>
45 <author>
46 <name>test</name>
46 <name>test</name>
47 <email>&#116;&#101;&#115;&#116;</email>
47 <email>&#116;&#101;&#115;&#116;</email>
48 </author>
48 </author>
49 <updated>1970-01-01T00:00:00+00:00</updated>
49 <updated>1970-01-01T00:00:00+00:00</updated>
50 <published>1970-01-01T00:00:00+00:00</published>
50 <published>1970-01-01T00:00:00+00:00</published>
51 <content type="xhtml">
51 <content type="xhtml">
52 <div xmlns="http://www.w3.org/1999/xhtml">
52 <div xmlns="http://www.w3.org/1999/xhtml">
53 <pre xml:space="preserve">branch</pre>
53 <pre xml:space="preserve">branch</pre>
54 </div>
54 </div>
55 </content>
55 </content>
56 </entry>
56 </entry>
57 <entry>
57 <entry>
58 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
58 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
59 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
59 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
60 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
60 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
61 <author>
61 <author>
62 <name>test</name>
62 <name>test</name>
63 <email>&#116;&#101;&#115;&#116;</email>
63 <email>&#116;&#101;&#115;&#116;</email>
64 </author>
64 </author>
65 <updated>1970-01-01T00:00:00+00:00</updated>
65 <updated>1970-01-01T00:00:00+00:00</updated>
66 <published>1970-01-01T00:00:00+00:00</published>
66 <published>1970-01-01T00:00:00+00:00</published>
67 <content type="xhtml">
67 <content type="xhtml">
68 <div xmlns="http://www.w3.org/1999/xhtml">
68 <div xmlns="http://www.w3.org/1999/xhtml">
69 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
69 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
70 </div>
70 </div>
71 </content>
71 </content>
72 </entry>
72 </entry>
73 <entry>
73 <entry>
74 <title>base</title>
74 <title>base</title>
75 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
75 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
76 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
76 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
77 <author>
77 <author>
78 <name>test</name>
78 <name>test</name>
79 <email>&#116;&#101;&#115;&#116;</email>
79 <email>&#116;&#101;&#115;&#116;</email>
80 </author>
80 </author>
81 <updated>1970-01-01T00:00:00+00:00</updated>
81 <updated>1970-01-01T00:00:00+00:00</updated>
82 <published>1970-01-01T00:00:00+00:00</published>
82 <published>1970-01-01T00:00:00+00:00</published>
83 <content type="xhtml">
83 <content type="xhtml">
84 <div xmlns="http://www.w3.org/1999/xhtml">
84 <div xmlns="http://www.w3.org/1999/xhtml">
85 <pre xml:space="preserve">base</pre>
85 <pre xml:space="preserve">base</pre>
86 </div>
86 </div>
87 </content>
87 </content>
88 </entry>
88 </entry>
89
89
90 </feed>
90 </feed>
91 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom'
91 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom'
92 200 Script output follows
92 200 Script output follows
93
93
94 <?xml version="1.0" encoding="ascii"?>
94 <?xml version="1.0" encoding="ascii"?>
95 <feed xmlns="http://www.w3.org/2005/Atom">
95 <feed xmlns="http://www.w3.org/2005/Atom">
96 <!-- Changelog -->
96 <!-- Changelog -->
97 <id>http://*:$HGPORT/</id> (glob)
97 <id>http://*:$HGPORT/</id> (glob)
98 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
98 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
99 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
99 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
100 <title>test Changelog</title>
100 <title>test Changelog</title>
101 <updated>1970-01-01T00:00:00+00:00</updated>
101 <updated>1970-01-01T00:00:00+00:00</updated>
102
102
103 <entry>
103 <entry>
104 <title>branch</title>
104 <title>branch</title>
105 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
105 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
106 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
106 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
107 <author>
107 <author>
108 <name>test</name>
108 <name>test</name>
109 <email>&#116;&#101;&#115;&#116;</email>
109 <email>&#116;&#101;&#115;&#116;</email>
110 </author>
110 </author>
111 <updated>1970-01-01T00:00:00+00:00</updated>
111 <updated>1970-01-01T00:00:00+00:00</updated>
112 <published>1970-01-01T00:00:00+00:00</published>
112 <published>1970-01-01T00:00:00+00:00</published>
113 <content type="xhtml">
113 <content type="xhtml">
114 <div xmlns="http://www.w3.org/1999/xhtml">
114 <div xmlns="http://www.w3.org/1999/xhtml">
115 <pre xml:space="preserve">branch</pre>
115 <pre xml:space="preserve">branch</pre>
116 </div>
116 </div>
117 </content>
117 </content>
118 </entry>
118 </entry>
119 <entry>
119 <entry>
120 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
120 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
121 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
121 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
122 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
122 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
123 <author>
123 <author>
124 <name>test</name>
124 <name>test</name>
125 <email>&#116;&#101;&#115;&#116;</email>
125 <email>&#116;&#101;&#115;&#116;</email>
126 </author>
126 </author>
127 <updated>1970-01-01T00:00:00+00:00</updated>
127 <updated>1970-01-01T00:00:00+00:00</updated>
128 <published>1970-01-01T00:00:00+00:00</published>
128 <published>1970-01-01T00:00:00+00:00</published>
129 <content type="xhtml">
129 <content type="xhtml">
130 <div xmlns="http://www.w3.org/1999/xhtml">
130 <div xmlns="http://www.w3.org/1999/xhtml">
131 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
131 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
132 </div>
132 </div>
133 </content>
133 </content>
134 </entry>
134 </entry>
135 <entry>
135 <entry>
136 <title>base</title>
136 <title>base</title>
137 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
137 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
138 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
138 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
139 <author>
139 <author>
140 <name>test</name>
140 <name>test</name>
141 <email>&#116;&#101;&#115;&#116;</email>
141 <email>&#116;&#101;&#115;&#116;</email>
142 </author>
142 </author>
143 <updated>1970-01-01T00:00:00+00:00</updated>
143 <updated>1970-01-01T00:00:00+00:00</updated>
144 <published>1970-01-01T00:00:00+00:00</published>
144 <published>1970-01-01T00:00:00+00:00</published>
145 <content type="xhtml">
145 <content type="xhtml">
146 <div xmlns="http://www.w3.org/1999/xhtml">
146 <div xmlns="http://www.w3.org/1999/xhtml">
147 <pre xml:space="preserve">base</pre>
147 <pre xml:space="preserve">base</pre>
148 </div>
148 </div>
149 </content>
149 </content>
150 </entry>
150 </entry>
151
151
152 </feed>
152 </feed>
153 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom'
153 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom'
154 200 Script output follows
154 200 Script output follows
155
155
156 <?xml version="1.0" encoding="ascii"?>
156 <?xml version="1.0" encoding="ascii"?>
157 <feed xmlns="http://www.w3.org/2005/Atom">
157 <feed xmlns="http://www.w3.org/2005/Atom">
158 <id>http://*:$HGPORT/atom-log/tip/foo</id> (glob)
158 <id>http://*:$HGPORT/atom-log/tip/foo</id> (glob)
159 <link rel="self" href="http://*:$HGPORT/atom-log/tip/foo"/> (glob)
159 <link rel="self" href="http://*:$HGPORT/atom-log/tip/foo"/> (glob)
160 <title>test: foo history</title>
160 <title>test: foo history</title>
161 <updated>1970-01-01T00:00:00+00:00</updated>
161 <updated>1970-01-01T00:00:00+00:00</updated>
162
162
163 <entry>
163 <entry>
164 <title>base</title>
164 <title>base</title>
165 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
165 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
166 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
166 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
167 <author>
167 <author>
168 <name>test</name>
168 <name>test</name>
169 <email>&#116;&#101;&#115;&#116;</email>
169 <email>&#116;&#101;&#115;&#116;</email>
170 </author>
170 </author>
171 <updated>1970-01-01T00:00:00+00:00</updated>
171 <updated>1970-01-01T00:00:00+00:00</updated>
172 <published>1970-01-01T00:00:00+00:00</published>
172 <published>1970-01-01T00:00:00+00:00</published>
173 <content type="xhtml">
173 <content type="xhtml">
174 <div xmlns="http://www.w3.org/1999/xhtml">
174 <div xmlns="http://www.w3.org/1999/xhtml">
175 <pre xml:space="preserve">base</pre>
175 <pre xml:space="preserve">base</pre>
176 </div>
176 </div>
177 </content>
177 </content>
178 </entry>
178 </entry>
179
179
180 </feed>
180 </feed>
181 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/'
181 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/'
182 200 Script output follows
182 200 Script output follows
183
183
184 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
184 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
185 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
185 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
186 <head>
186 <head>
187 <link rel="icon" href="/static/hgicon.png" type="image/png" />
187 <link rel="icon" href="/static/hgicon.png" type="image/png" />
188 <meta name="robots" content="index, nofollow" />
188 <meta name="robots" content="index, nofollow" />
189 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
189 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
190
190
191 <title>test: log</title>
191 <title>test: log</title>
192 <link rel="alternate" type="application/atom+xml"
192 <link rel="alternate" type="application/atom+xml"
193 href="/atom-log" title="Atom feed for test" />
193 href="/atom-log" title="Atom feed for test" />
194 <link rel="alternate" type="application/rss+xml"
194 <link rel="alternate" type="application/rss+xml"
195 href="/rss-log" title="RSS feed for test" />
195 href="/rss-log" title="RSS feed for test" />
196 </head>
196 </head>
197 <body>
197 <body>
198
198
199 <div class="container">
199 <div class="container">
200 <div class="menu">
200 <div class="menu">
201 <div class="logo">
201 <div class="logo">
202 <a href="http://mercurial.selenic.com/">
202 <a href="http://mercurial.selenic.com/">
203 <img src="/static/hglogo.png" alt="mercurial" /></a>
203 <img src="/static/hglogo.png" alt="mercurial" /></a>
204 </div>
204 </div>
205 <ul>
205 <ul>
206 <li class="active">log</li>
206 <li class="active">log</li>
207 <li><a href="/graph/1d22e65f027e">graph</a></li>
207 <li><a href="/graph/1d22e65f027e">graph</a></li>
208 <li><a href="/tags">tags</a></li>
208 <li><a href="/tags">tags</a></li>
209 <li><a href="/bookmarks">bookmarks</a></li>
209 <li><a href="/bookmarks">bookmarks</a></li>
210 <li><a href="/branches">branches</a></li>
210 <li><a href="/branches">branches</a></li>
211 </ul>
211 </ul>
212 <ul>
212 <ul>
213 <li><a href="/rev/1d22e65f027e">changeset</a></li>
213 <li><a href="/rev/1d22e65f027e">changeset</a></li>
214 <li><a href="/file/1d22e65f027e">browse</a></li>
214 <li><a href="/file/1d22e65f027e">browse</a></li>
215 </ul>
215 </ul>
216 <ul>
216 <ul>
217
217
218 </ul>
218 </ul>
219 <ul>
219 <ul>
220 <li><a href="/help">help</a></li>
220 <li><a href="/help">help</a></li>
221 </ul>
221 </ul>
222 </div>
222 </div>
223
223
224 <div class="main">
224 <div class="main">
225 <h2><a href="/">test</a></h2>
225 <h2><a href="/">test</a></h2>
226 <h3>log</h3>
226 <h3>log</h3>
227
227
228 <form class="search" action="/log">
228 <form class="search" action="/log">
229
229
230 <p><input name="rev" id="search1" type="text" size="30" /></p>
230 <p><input name="rev" id="search1" type="text" size="30" /></p>
231 <div id="hint">find changesets by author, revision,
231 <div id="hint">find changesets by author, revision,
232 files, or words in the commit message</div>
232 files, or words in the commit message</div>
233 </form>
233 </form>
234
234
235 <div class="navigate">
235 <div class="navigate">
236 <a href="/shortlog/2?revcount=30">less</a>
236 <a href="/shortlog/2?revcount=30">less</a>
237 <a href="/shortlog/2?revcount=120">more</a>
237 <a href="/shortlog/2?revcount=120">more</a>
238 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
238 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
239 </div>
239 </div>
240
240
241 <table class="bigtable">
241 <table class="bigtable">
242 <tr>
242 <tr>
243 <th class="age">age</th>
243 <th class="age">age</th>
244 <th class="author">author</th>
244 <th class="author">author</th>
245 <th class="description">description</th>
245 <th class="description">description</th>
246 </tr>
246 </tr>
247 <tr class="parity0">
247 <tr class="parity0">
248 <td class="age">1970-01-01</td>
248 <td class="age">1970-01-01</td>
249 <td class="author">test</td>
249 <td class="author">test</td>
250 <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>
250 <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>
251 </tr>
251 </tr>
252 <tr class="parity1">
252 <tr class="parity1">
253 <td class="age">1970-01-01</td>
253 <td class="age">1970-01-01</td>
254 <td class="author">test</td>
254 <td class="author">test</td>
255 <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
255 <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
256 </tr>
256 </tr>
257 <tr class="parity0">
257 <tr class="parity0">
258 <td class="age">1970-01-01</td>
258 <td class="age">1970-01-01</td>
259 <td class="author">test</td>
259 <td class="author">test</td>
260 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
260 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
261 </tr>
261 </tr>
262
262
263 </table>
263 </table>
264
264
265 <div class="navigate">
265 <div class="navigate">
266 <a href="/shortlog/2?revcount=30">less</a>
266 <a href="/shortlog/2?revcount=30">less</a>
267 <a href="/shortlog/2?revcount=120">more</a>
267 <a href="/shortlog/2?revcount=120">more</a>
268 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
268 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
269 </div>
269 </div>
270
270
271 </div>
271 </div>
272 </div>
272 </div>
273
273
274
274
275
275
276 </body>
276 </body>
277 </html>
277 </html>
278
278
279 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/'
279 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/'
280 200 Script output follows
280 200 Script output follows
281
281
282 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
282 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
283 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
283 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
284 <head>
284 <head>
285 <link rel="icon" href="/static/hgicon.png" type="image/png" />
285 <link rel="icon" href="/static/hgicon.png" type="image/png" />
286 <meta name="robots" content="index, nofollow" />
286 <meta name="robots" content="index, nofollow" />
287 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
287 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
288
288
289 <title>test: 2ef0ac749a14</title>
289 <title>test: 2ef0ac749a14</title>
290 </head>
290 </head>
291 <body>
291 <body>
292 <div class="container">
292 <div class="container">
293 <div class="menu">
293 <div class="menu">
294 <div class="logo">
294 <div class="logo">
295 <a href="http://mercurial.selenic.com/">
295 <a href="http://mercurial.selenic.com/">
296 <img src="/static/hglogo.png" alt="mercurial" /></a>
296 <img src="/static/hglogo.png" alt="mercurial" /></a>
297 </div>
297 </div>
298 <ul>
298 <ul>
299 <li><a href="/shortlog/2ef0ac749a14">log</a></li>
299 <li><a href="/shortlog/2ef0ac749a14">log</a></li>
300 <li><a href="/graph/2ef0ac749a14">graph</a></li>
300 <li><a href="/graph/2ef0ac749a14">graph</a></li>
301 <li><a href="/tags">tags</a></li>
301 <li><a href="/tags">tags</a></li>
302 <li><a href="/bookmarks">bookmarks</a></li>
302 <li><a href="/bookmarks">bookmarks</a></li>
303 <li><a href="/branches">branches</a></li>
303 <li><a href="/branches">branches</a></li>
304 </ul>
304 </ul>
305 <ul>
305 <ul>
306 <li class="active">changeset</li>
306 <li class="active">changeset</li>
307 <li><a href="/raw-rev/2ef0ac749a14">raw</a></li>
307 <li><a href="/raw-rev/2ef0ac749a14">raw</a></li>
308 <li><a href="/file/2ef0ac749a14">browse</a></li>
308 <li><a href="/file/2ef0ac749a14">browse</a></li>
309 </ul>
309 </ul>
310 <ul>
310 <ul>
311
311
312 </ul>
312 </ul>
313 <ul>
313 <ul>
314 <li><a href="/help">help</a></li>
314 <li><a href="/help">help</a></li>
315 </ul>
315 </ul>
316 </div>
316 </div>
317
317
318 <div class="main">
318 <div class="main">
319
319
320 <h2><a href="/">test</a></h2>
320 <h2><a href="/">test</a></h2>
321 <h3>changeset 0:2ef0ac749a14 <span class="tag">1.0</span> <span class="tag">anotherthing</span> </h3>
321 <h3>changeset 0:2ef0ac749a14 <span class="tag">1.0</span> <span class="tag">anotherthing</span> </h3>
322
322
323 <form class="search" action="/log">
323 <form class="search" action="/log">
324
324
325 <p><input name="rev" id="search1" type="text" size="30" /></p>
325 <p><input name="rev" id="search1" type="text" size="30" /></p>
326 <div id="hint">find changesets by author, revision,
326 <div id="hint">find changesets by author, revision,
327 files, or words in the commit message</div>
327 files, or words in the commit message</div>
328 </form>
328 </form>
329
329
330 <div class="description">base</div>
330 <div class="description">base</div>
331
331
332 <table id="changesetEntry">
332 <table id="changesetEntry">
333 <tr>
333 <tr>
334 <th class="author">author</th>
334 <th class="author">author</th>
335 <td class="author">&#116;&#101;&#115;&#116;</td>
335 <td class="author">&#116;&#101;&#115;&#116;</td>
336 </tr>
336 </tr>
337 <tr>
337 <tr>
338 <th class="date">date</th>
338 <th class="date">date</th>
339 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
339 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
340 <tr>
340 <tr>
341 <th class="author">parents</th>
341 <th class="author">parents</th>
342 <td class="author"></td>
342 <td class="author"></td>
343 </tr>
343 </tr>
344 <tr>
344 <tr>
345 <th class="author">children</th>
345 <th class="author">children</th>
346 <td class="author"> <a href="/rev/a4f92ed23982">a4f92ed23982</a></td>
346 <td class="author"> <a href="/rev/a4f92ed23982">a4f92ed23982</a></td>
347 </tr>
347 </tr>
348 <tr>
348 <tr>
349 <th class="files">files</th>
349 <th class="files">files</th>
350 <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td>
350 <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td>
351 </tr>
351 </tr>
352 </table>
352 </table>
353
353
354 <div class="overflow">
354 <div class="overflow">
355 <div class="sourcefirst"> line diff</div>
355 <div class="sourcefirst"> line diff</div>
356
356
357 <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
357 <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
358 </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
358 </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
359 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
359 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
360 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+foo
360 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+foo
361 </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
361 </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
362 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/foo Thu Jan 01 00:00:00 1970 +0000
362 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/foo Thu Jan 01 00:00:00 1970 +0000
363 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
363 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
364 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+foo
364 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+foo
365 </span></pre></div>
365 </span></pre></div>
366 </div>
366 </div>
367
367
368 </div>
368 </div>
369 </div>
369 </div>
370
370
371
371
372 </body>
372 </body>
373 </html>
373 </html>
374
374
375 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw'
375 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw'
376 200 Script output follows
376 200 Script output follows
377
377
378
378
379 # HG changeset patch
379 # HG changeset patch
380 # User test
380 # User test
381 # Date 0 0
381 # Date 0 0
382 # Node ID a4f92ed23982be056b9852de5dfe873eaac7f0de
382 # Node ID a4f92ed23982be056b9852de5dfe873eaac7f0de
383 # Parent 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
383 # Parent 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
384 Added tag 1.0 for changeset 2ef0ac749a14
384 Added tag 1.0 for changeset 2ef0ac749a14
385
385
386 diff -r 2ef0ac749a14 -r a4f92ed23982 .hgtags
386 diff -r 2ef0ac749a14 -r a4f92ed23982 .hgtags
387 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
387 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
388 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
388 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
389 @@ -0,0 +1,1 @@
389 @@ -0,0 +1,1 @@
390 +2ef0ac749a14e4f57a5a822464a0902c6f7f448f 1.0
390 +2ef0ac749a14e4f57a5a822464a0902c6f7f448f 1.0
391
391
392 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base'
392 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base'
393 200 Script output follows
393 200 Script output follows
394
394
395 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
395 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
396 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
396 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
397 <head>
397 <head>
398 <link rel="icon" href="/static/hgicon.png" type="image/png" />
398 <link rel="icon" href="/static/hgicon.png" type="image/png" />
399 <meta name="robots" content="index, nofollow" />
399 <meta name="robots" content="index, nofollow" />
400 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
400 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
401
401
402 <title>test: searching for base</title>
402 <title>test: searching for base</title>
403 </head>
403 </head>
404 <body>
404 <body>
405
405
406 <div class="container">
406 <div class="container">
407 <div class="menu">
407 <div class="menu">
408 <div class="logo">
408 <div class="logo">
409 <a href="http://mercurial.selenic.com/">
409 <a href="http://mercurial.selenic.com/">
410 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
410 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
411 </div>
411 </div>
412 <ul>
412 <ul>
413 <li><a href="/shortlog">log</a></li>
413 <li><a href="/shortlog">log</a></li>
414 <li><a href="/graph">graph</a></li>
414 <li><a href="/graph">graph</a></li>
415 <li><a href="/tags">tags</a></li>
415 <li><a href="/tags">tags</a></li>
416 <li><a href="/bookmarks">bookmarks</a></li>
416 <li><a href="/bookmarks">bookmarks</a></li>
417 <li><a href="/branches">branches</a></li>
417 <li><a href="/branches">branches</a></li>
418 <li><a href="/help">help</a></li>
418 <li><a href="/help">help</a></li>
419 </ul>
419 </ul>
420 </div>
420 </div>
421
421
422 <div class="main">
422 <div class="main">
423 <h2><a href="/">test</a></h2>
423 <h2><a href="/">test</a></h2>
424 <h3>searching for 'base'</h3>
424 <h3>searching for 'base'</h3>
425
425
426 <form class="search" action="/log">
426 <form class="search" action="/log">
427
427
428 <p><input name="rev" id="search1" type="text" size="30"></p>
428 <p><input name="rev" id="search1" type="text" size="30"></p>
429 <div id="hint">find changesets by author, revision,
429 <div id="hint">find changesets by author, revision,
430 files, or words in the commit message</div>
430 files, or words in the commit message</div>
431 </form>
431 </form>
432
432
433 <div class="navigate">
433 <div class="navigate">
434 <a href="/search/?rev=base&revcount=5">less</a>
434 <a href="/search/?rev=base&revcount=5">less</a>
435 <a href="/search/?rev=base&revcount=20">more</a>
435 <a href="/search/?rev=base&revcount=20">more</a>
436 </div>
436 </div>
437
437
438 <table class="bigtable">
438 <table class="bigtable">
439 <tr>
439 <tr>
440 <th class="age">age</th>
440 <th class="age">age</th>
441 <th class="author">author</th>
441 <th class="author">author</th>
442 <th class="description">description</th>
442 <th class="description">description</th>
443 </tr>
443 </tr>
444 <tr class="parity0">
444 <tr class="parity0">
445 <td class="age">1970-01-01</td>
445 <td class="age">1970-01-01</td>
446 <td class="author">test</td>
446 <td class="author">test</td>
447 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
447 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
448 </tr>
448 </tr>
449
449
450 </table>
450 </table>
451
451
452 <div class="navigate">
452 <div class="navigate">
453 <a href="/search/?rev=base&revcount=5">less</a>
453 <a href="/search/?rev=base&revcount=5">less</a>
454 <a href="/search/?rev=base&revcount=20">more</a>
454 <a href="/search/?rev=base&revcount=20">more</a>
455 </div>
455 </div>
456
456
457 </div>
457 </div>
458 </div>
458 </div>
459
459
460
460
461
461
462 </body>
462 </body>
463 </html>
463 </html>
464
464
465
465
466 File-related
466 File-related
467
467
468 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw'
468 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw'
469 200 Script output follows
469 200 Script output follows
470
470
471 foo
471 foo
472 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw'
472 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw'
473 200 Script output follows
473 200 Script output follows
474
474
475
475
476 test@0: foo
476 test@0: foo
477
477
478
478
479
479
480
480
481 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw'
481 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw'
482 200 Script output follows
482 200 Script output follows
483
483
484
484
485 drwxr-xr-x da
485 drwxr-xr-x da
486 -rw-r--r-- 45 .hgtags
486 -rw-r--r-- 45 .hgtags
487 -rw-r--r-- 4 foo
487 -rw-r--r-- 4 foo
488
488
489
489
490 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo'
490 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo'
491 200 Script output follows
491 200 Script output follows
492
492
493 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
493 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
494 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
494 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
495 <head>
495 <head>
496 <link rel="icon" href="/static/hgicon.png" type="image/png" />
496 <link rel="icon" href="/static/hgicon.png" type="image/png" />
497 <meta name="robots" content="index, nofollow" />
497 <meta name="robots" content="index, nofollow" />
498 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
498 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
499
499
500 <title>test: a4f92ed23982 foo</title>
500 <title>test: a4f92ed23982 foo</title>
501 </head>
501 </head>
502 <body>
502 <body>
503
503
504 <div class="container">
504 <div class="container">
505 <div class="menu">
505 <div class="menu">
506 <div class="logo">
506 <div class="logo">
507 <a href="http://mercurial.selenic.com/">
507 <a href="http://mercurial.selenic.com/">
508 <img src="/static/hglogo.png" alt="mercurial" /></a>
508 <img src="/static/hglogo.png" alt="mercurial" /></a>
509 </div>
509 </div>
510 <ul>
510 <ul>
511 <li><a href="/shortlog/a4f92ed23982">log</a></li>
511 <li><a href="/shortlog/a4f92ed23982">log</a></li>
512 <li><a href="/graph/a4f92ed23982">graph</a></li>
512 <li><a href="/graph/a4f92ed23982">graph</a></li>
513 <li><a href="/tags">tags</a></li>
513 <li><a href="/tags">tags</a></li>
514 <li><a href="/branches">branches</a></li>
514 <li><a href="/branches">branches</a></li>
515 </ul>
515 </ul>
516 <ul>
516 <ul>
517 <li><a href="/rev/a4f92ed23982">changeset</a></li>
517 <li><a href="/rev/a4f92ed23982">changeset</a></li>
518 <li><a href="/file/a4f92ed23982/">browse</a></li>
518 <li><a href="/file/a4f92ed23982/">browse</a></li>
519 </ul>
519 </ul>
520 <ul>
520 <ul>
521 <li class="active">file</li>
521 <li class="active">file</li>
522 <li><a href="/file/tip/foo">latest</a></li>
522 <li><a href="/file/tip/foo">latest</a></li>
523 <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
523 <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
524 <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
524 <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
525 <li><a href="/log/a4f92ed23982/foo">file log</a></li>
525 <li><a href="/log/a4f92ed23982/foo">file log</a></li>
526 <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
526 <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
527 </ul>
527 </ul>
528 <ul>
528 <ul>
529 <li><a href="/help">help</a></li>
529 <li><a href="/help">help</a></li>
530 </ul>
530 </ul>
531 </div>
531 </div>
532
532
533 <div class="main">
533 <div class="main">
534 <h2><a href="/">test</a></h2>
534 <h2><a href="/">test</a></h2>
535 <h3>view foo @ 1:a4f92ed23982</h3>
535 <h3>view foo @ 1:a4f92ed23982</h3>
536
536
537 <form class="search" action="/log">
537 <form class="search" action="/log">
538
538
539 <p><input name="rev" id="search1" type="text" size="30" /></p>
539 <p><input name="rev" id="search1" type="text" size="30" /></p>
540 <div id="hint">find changesets by author, revision,
540 <div id="hint">find changesets by author, revision,
541 files, or words in the commit message</div>
541 files, or words in the commit message</div>
542 </form>
542 </form>
543
543
544 <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
544 <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
545
545
546 <table id="changesetEntry">
546 <table id="changesetEntry">
547 <tr>
547 <tr>
548 <th class="author">author</th>
548 <th class="author">author</th>
549 <td class="author">&#116;&#101;&#115;&#116;</td>
549 <td class="author">&#116;&#101;&#115;&#116;</td>
550 </tr>
550 </tr>
551 <tr>
551 <tr>
552 <th class="date">date</th>
552 <th class="date">date</th>
553 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
553 <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
554 </tr>
554 </tr>
555 <tr>
555 <tr>
556 <th class="author">parents</th>
556 <th class="author">parents</th>
557 <td class="author"></td>
557 <td class="author"></td>
558 </tr>
558 </tr>
559 <tr>
559 <tr>
560 <th class="author">children</th>
560 <th class="author">children</th>
561 <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
561 <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
562 </tr>
562 </tr>
563
563
564 </table>
564 </table>
565
565
566 <div class="overflow">
566 <div class="overflow">
567 <div class="sourcefirst"> line source</div>
567 <div class="sourcefirst"> line source</div>
568
568
569 <div class="parity0 source"><a href="#l1" id="l1"> 1</a> foo
569 <div class="parity0 source"><a href="#l1" id="l1"> 1</a> foo
570 </div>
570 </div>
571 <div class="sourcelast"></div>
571 <div class="sourcelast"></div>
572 </div>
572 </div>
573 </div>
573 </div>
574 </div>
574 </div>
575
575
576
576
577
577
578 </body>
578 </body>
579 </html>
579 </html>
580
580
581 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
581 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
582 200 Script output follows
582 200 Script output follows
583
583
584
584
585 diff -r 000000000000 -r a4f92ed23982 foo
585 diff -r 000000000000 -r a4f92ed23982 foo
586 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
586 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
587 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
587 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
588 @@ -0,0 +1,1 @@
588 @@ -0,0 +1,1 @@
589 +foo
589 +foo
590
590
591
591
592
592
593
593
594
594
595 Overviews
595 Overviews
596
596
597 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
597 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
598 200 Script output follows
598 200 Script output follows
599
599
600 tip 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
600 tip 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
601 1.0 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
601 1.0 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
602 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
602 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
603 200 Script output follows
603 200 Script output follows
604
604
605 stable 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe open
605 stable 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe open
606 default a4f92ed23982be056b9852de5dfe873eaac7f0de inactive
606 default a4f92ed23982be056b9852de5dfe873eaac7f0de inactive
607 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-bookmarks'
607 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-bookmarks'
608 200 Script output follows
608 200 Script output follows
609
609
610 anotherthing 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
610 anotherthing 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
611 something 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
611 something 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
612 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
612 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
613 200 Script output follows
613 200 Script output follows
614
614
615 <?xml version="1.0" encoding="ascii"?>
615 <?xml version="1.0" encoding="ascii"?>
616 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
616 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
617 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
617 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
618 <head>
618 <head>
619 <link rel="icon" href="/static/hgicon.png" type="image/png" />
619 <link rel="icon" href="/static/hgicon.png" type="image/png" />
620 <meta name="robots" content="index, nofollow"/>
620 <meta name="robots" content="index, nofollow"/>
621 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
621 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
622
622
623
623
624 <title>test: Summary</title>
624 <title>test: Summary</title>
625 <link rel="alternate" type="application/atom+xml"
625 <link rel="alternate" type="application/atom+xml"
626 href="/atom-log" title="Atom feed for test"/>
626 href="/atom-log" title="Atom feed for test"/>
627 <link rel="alternate" type="application/rss+xml"
627 <link rel="alternate" type="application/rss+xml"
628 href="/rss-log" title="RSS feed for test"/>
628 href="/rss-log" title="RSS feed for test"/>
629 </head>
629 </head>
630 <body>
630 <body>
631
631
632 <div class="page_header">
632 <div class="page_header">
633 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / summary
633 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / summary
634
634
635 <form action="/log">
635 <form action="/log">
636 <input type="hidden" name="style" value="gitweb" />
636 <input type="hidden" name="style" value="gitweb" />
637 <div class="search">
637 <div class="search">
638 <input type="text" name="rev" />
638 <input type="text" name="rev" />
639 </div>
639 </div>
640 </form>
640 </form>
641 </div>
641 </div>
642
642
643 <div class="page_nav">
643 <div class="page_nav">
644 summary |
644 summary |
645 <a href="/shortlog?style=gitweb">shortlog</a> |
645 <a href="/shortlog?style=gitweb">shortlog</a> |
646 <a href="/log?style=gitweb">changelog</a> |
646 <a href="/log?style=gitweb">changelog</a> |
647 <a href="/graph?style=gitweb">graph</a> |
647 <a href="/graph?style=gitweb">graph</a> |
648 <a href="/tags?style=gitweb">tags</a> |
648 <a href="/tags?style=gitweb">tags</a> |
649 <a href="/bookmarks?style=gitweb">bookmarks</a> |
649 <a href="/bookmarks?style=gitweb">bookmarks</a> |
650 <a href="/branches?style=gitweb">branches</a> |
650 <a href="/branches?style=gitweb">branches</a> |
651 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
651 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
652 <a href="/help?style=gitweb">help</a>
652 <a href="/help?style=gitweb">help</a>
653 <br/>
653 <br/>
654 </div>
654 </div>
655
655
656 <div class="title">&nbsp;</div>
656 <div class="title">&nbsp;</div>
657 <table cellspacing="0">
657 <table cellspacing="0">
658 <tr><td>description</td><td>unknown</td></tr>
658 <tr><td>description</td><td>unknown</td></tr>
659 <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>
659 <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>
660 <tr><td>last change</td><td>Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
660 <tr><td>last change</td><td>Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
661 </table>
661 </table>
662
662
663 <div><a class="title" href="/shortlog?style=gitweb">changes</a></div>
663 <div><a class="title" href="/shortlog?style=gitweb">changes</a></div>
664 <table cellspacing="0">
664 <table cellspacing="0">
665
665
666 <tr class="parity0">
666 <tr class="parity0">
667 <td class="age"><i>1970-01-01</i></td>
667 <td class="age"><i>1970-01-01</i></td>
668 <td><i>test</i></td>
668 <td><i>test</i></td>
669 <td>
669 <td>
670 <a class="list" href="/rev/1d22e65f027e?style=gitweb">
670 <a class="list" href="/rev/1d22e65f027e?style=gitweb">
671 <b>branch</b>
671 <b>branch</b>
672 <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> <span class="bookmarktag" title="something">something</span> </span>
672 <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> <span class="bookmarktag" title="something">something</span> </span>
673 </a>
673 </a>
674 </td>
674 </td>
675 <td class="link" nowrap>
675 <td class="link" nowrap>
676 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
676 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
677 <a href="/file/1d22e65f027e?style=gitweb">files</a>
677 <a href="/file/1d22e65f027e?style=gitweb">files</a>
678 </td>
678 </td>
679 </tr>
679 </tr>
680 <tr class="parity1">
680 <tr class="parity1">
681 <td class="age"><i>1970-01-01</i></td>
681 <td class="age"><i>1970-01-01</i></td>
682 <td><i>test</i></td>
682 <td><i>test</i></td>
683 <td>
683 <td>
684 <a class="list" href="/rev/a4f92ed23982?style=gitweb">
684 <a class="list" href="/rev/a4f92ed23982?style=gitweb">
685 <b>Added tag 1.0 for changeset 2ef0ac749a14</b>
685 <b>Added tag 1.0 for changeset 2ef0ac749a14</b>
686 <span class="logtags"><span class="branchtag" title="default">default</span> </span>
686 <span class="logtags"><span class="branchtag" title="default">default</span> </span>
687 </a>
687 </a>
688 </td>
688 </td>
689 <td class="link" nowrap>
689 <td class="link" nowrap>
690 <a href="/rev/a4f92ed23982?style=gitweb">changeset</a> |
690 <a href="/rev/a4f92ed23982?style=gitweb">changeset</a> |
691 <a href="/file/a4f92ed23982?style=gitweb">files</a>
691 <a href="/file/a4f92ed23982?style=gitweb">files</a>
692 </td>
692 </td>
693 </tr>
693 </tr>
694 <tr class="parity0">
694 <tr class="parity0">
695 <td class="age"><i>1970-01-01</i></td>
695 <td class="age"><i>1970-01-01</i></td>
696 <td><i>test</i></td>
696 <td><i>test</i></td>
697 <td>
697 <td>
698 <a class="list" href="/rev/2ef0ac749a14?style=gitweb">
698 <a class="list" href="/rev/2ef0ac749a14?style=gitweb">
699 <b>base</b>
699 <b>base</b>
700 <span class="logtags"><span class="tagtag" title="1.0">1.0</span> <span class="bookmarktag" title="anotherthing">anotherthing</span> </span>
700 <span class="logtags"><span class="tagtag" title="1.0">1.0</span> <span class="bookmarktag" title="anotherthing">anotherthing</span> </span>
701 </a>
701 </a>
702 </td>
702 </td>
703 <td class="link" nowrap>
703 <td class="link" nowrap>
704 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
704 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
705 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
705 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
706 </td>
706 </td>
707 </tr>
707 </tr>
708 <tr class="light"><td colspan="4"><a class="list" href="/shortlog?style=gitweb">...</a></td></tr>
708 <tr class="light"><td colspan="4"><a class="list" href="/shortlog?style=gitweb">...</a></td></tr>
709 </table>
709 </table>
710
710
711 <div><a class="title" href="/tags?style=gitweb">tags</a></div>
711 <div><a class="title" href="/tags?style=gitweb">tags</a></div>
712 <table cellspacing="0">
712 <table cellspacing="0">
713
713
714 <tr class="parity0">
714 <tr class="parity0">
715 <td class="age"><i>1970-01-01</i></td>
715 <td class="age"><i>1970-01-01</i></td>
716 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
716 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
717 <td class="link">
717 <td class="link">
718 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
718 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
719 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
719 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
720 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
720 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
721 </td>
721 </td>
722 </tr>
722 </tr>
723 <tr class="light"><td colspan="3"><a class="list" href="/tags?style=gitweb">...</a></td></tr>
723 <tr class="light"><td colspan="3"><a class="list" href="/tags?style=gitweb">...</a></td></tr>
724 </table>
724 </table>
725
725
726 <div><a class="title" href="/bookmarks?style=gitweb">bookmarks</a></div>
727 <table cellspacing="0">
728
729 <tr class="parity0">
730 <td class="age"><i>1970-01-01</i></td>
731 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>anotherthing</b></a></td>
732 <td class="link">
733 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
734 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
735 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
736 </td>
737 </tr>
738 <tr class="parity1">
739 <td class="age"><i>1970-01-01</i></td>
740 <td><a class="list" href="/rev/1d22e65f027e?style=gitweb"><b>something</b></a></td>
741 <td class="link">
742 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
743 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
744 <a href="/file/1d22e65f027e?style=gitweb">files</a>
745 </td>
746 </tr>
747 <tr class="light"><td colspan="3"><a class="list" href="/bookmarks?style=gitweb">...</a></td></tr>
748 </table>
749
726 <div><a class="title" href="#">branches</a></div>
750 <div><a class="title" href="#">branches</a></div>
727 <table cellspacing="0">
751 <table cellspacing="0">
728
752
729 <tr class="parity0">
753 <tr class="parity0">
730 <td class="age"><i>1970-01-01</i></td>
754 <td class="age"><i>1970-01-01</i></td>
731 <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
755 <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
732 <td class="">stable</td>
756 <td class="">stable</td>
733 <td class="link">
757 <td class="link">
734 <a href="/changeset/1d22e65f027e?style=gitweb">changeset</a> |
758 <a href="/changeset/1d22e65f027e?style=gitweb">changeset</a> |
735 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
759 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
736 <a href="/file/1d22e65f027e?style=gitweb">files</a>
760 <a href="/file/1d22e65f027e?style=gitweb">files</a>
737 </td>
761 </td>
738 </tr>
762 </tr>
739 <tr class="parity1">
763 <tr class="parity1">
740 <td class="age"><i>1970-01-01</i></td>
764 <td class="age"><i>1970-01-01</i></td>
741 <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
765 <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
742 <td class="">default</td>
766 <td class="">default</td>
743 <td class="link">
767 <td class="link">
744 <a href="/changeset/a4f92ed23982?style=gitweb">changeset</a> |
768 <a href="/changeset/a4f92ed23982?style=gitweb">changeset</a> |
745 <a href="/log/a4f92ed23982?style=gitweb">changelog</a> |
769 <a href="/log/a4f92ed23982?style=gitweb">changelog</a> |
746 <a href="/file/a4f92ed23982?style=gitweb">files</a>
770 <a href="/file/a4f92ed23982?style=gitweb">files</a>
747 </td>
771 </td>
748 </tr>
772 </tr>
749 <tr class="light">
773 <tr class="light">
750 <td colspan="4"><a class="list" href="#">...</a></td>
774 <td colspan="4"><a class="list" href="#">...</a></td>
751 </tr>
775 </tr>
752 </table>
776 </table>
753 <div class="page_footer">
777 <div class="page_footer">
754 <div class="page_footer_text">test</div>
778 <div class="page_footer_text">test</div>
755 <div class="rss_logo">
779 <div class="rss_logo">
756 <a href="/rss-log">RSS</a>
780 <a href="/rss-log">RSS</a>
757 <a href="/atom-log">Atom</a>
781 <a href="/atom-log">Atom</a>
758 </div>
782 </div>
759 <br />
783 <br />
760
784
761 </div>
785 </div>
762 </body>
786 </body>
763 </html>
787 </html>
764
788
765 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb'
789 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb'
766 200 Script output follows
790 200 Script output follows
767
791
768 <?xml version="1.0" encoding="ascii"?>
792 <?xml version="1.0" encoding="ascii"?>
769 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
793 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
770 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
794 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
771 <head>
795 <head>
772 <link rel="icon" href="/static/hgicon.png" type="image/png" />
796 <link rel="icon" href="/static/hgicon.png" type="image/png" />
773 <meta name="robots" content="index, nofollow"/>
797 <meta name="robots" content="index, nofollow"/>
774 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
798 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
775
799
776
800
777 <title>test: Graph</title>
801 <title>test: Graph</title>
778 <link rel="alternate" type="application/atom+xml"
802 <link rel="alternate" type="application/atom+xml"
779 href="/atom-log" title="Atom feed for test"/>
803 href="/atom-log" title="Atom feed for test"/>
780 <link rel="alternate" type="application/rss+xml"
804 <link rel="alternate" type="application/rss+xml"
781 href="/rss-log" title="RSS feed for test"/>
805 href="/rss-log" title="RSS feed for test"/>
782 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
806 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
783 </head>
807 </head>
784 <body>
808 <body>
785
809
786 <div class="page_header">
810 <div class="page_header">
787 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / graph
811 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / graph
788 </div>
812 </div>
789
813
790 <form action="/log">
814 <form action="/log">
791 <input type="hidden" name="style" value="gitweb" />
815 <input type="hidden" name="style" value="gitweb" />
792 <div class="search">
816 <div class="search">
793 <input type="text" name="rev" />
817 <input type="text" name="rev" />
794 </div>
818 </div>
795 </form>
819 </form>
796 <div class="page_nav">
820 <div class="page_nav">
797 <a href="/summary?style=gitweb">summary</a> |
821 <a href="/summary?style=gitweb">summary</a> |
798 <a href="/shortlog?style=gitweb">shortlog</a> |
822 <a href="/shortlog?style=gitweb">shortlog</a> |
799 <a href="/log/2?style=gitweb">changelog</a> |
823 <a href="/log/2?style=gitweb">changelog</a> |
800 graph |
824 graph |
801 <a href="/tags?style=gitweb">tags</a> |
825 <a href="/tags?style=gitweb">tags</a> |
802 <a href="/bookmarks?style=gitweb">bookmarks</a> |
826 <a href="/bookmarks?style=gitweb">bookmarks</a> |
803 <a href="/branches?style=gitweb">branches</a> |
827 <a href="/branches?style=gitweb">branches</a> |
804 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
828 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
805 <a href="/help?style=gitweb">help</a>
829 <a href="/help?style=gitweb">help</a>
806 <br/>
830 <br/>
807 <a href="/graph/2?style=gitweb&revcount=30">less</a>
831 <a href="/graph/2?style=gitweb&revcount=30">less</a>
808 <a href="/graph/2?style=gitweb&revcount=120">more</a>
832 <a href="/graph/2?style=gitweb&revcount=120">more</a>
809 | <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/>
833 | <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/>
810 </div>
834 </div>
811
835
812 <div class="title">&nbsp;</div>
836 <div class="title">&nbsp;</div>
813
837
814 <noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
838 <noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
815
839
816 <div id="wrapper">
840 <div id="wrapper">
817 <ul id="nodebgs"></ul>
841 <ul id="nodebgs"></ul>
818 <canvas id="graph" width="480" height="129"></canvas>
842 <canvas id="graph" width="480" height="129"></canvas>
819 <ul id="graphnodes"></ul>
843 <ul id="graphnodes"></ul>
820 </div>
844 </div>
821
845
822 <script type="text/javascript" src="/static/graph.js"></script>
846 <script type="text/javascript" src="/static/graph.js"></script>
823 <script>
847 <script>
824 <!-- hide script content
848 <!-- hide script content
825
849
826 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"], ["anotherthing"]]];
850 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"], ["anotherthing"]]];
827 var graph = new Graph();
851 var graph = new Graph();
828 graph.scale(39);
852 graph.scale(39);
829
853
830 graph.edge = function(x0, y0, x1, y1, color) {
854 graph.edge = function(x0, y0, x1, y1, color) {
831
855
832 this.setColor(color, 0.0, 0.65);
856 this.setColor(color, 0.0, 0.65);
833 this.ctx.beginPath();
857 this.ctx.beginPath();
834 this.ctx.moveTo(x0, y0);
858 this.ctx.moveTo(x0, y0);
835 this.ctx.lineTo(x1, y1);
859 this.ctx.lineTo(x1, y1);
836 this.ctx.stroke();
860 this.ctx.stroke();
837
861
838 }
862 }
839
863
840 var revlink = '<li style="_STYLE"><span class="desc">';
864 var revlink = '<li style="_STYLE"><span class="desc">';
841 revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
865 revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
842 revlink += '</span> _TAGS';
866 revlink += '</span> _TAGS';
843 revlink += '<span class="info">_DATE, by _USER</span></li>';
867 revlink += '<span class="info">_DATE, by _USER</span></li>';
844
868
845 graph.vertex = function(x, y, color, parity, cur) {
869 graph.vertex = function(x, y, color, parity, cur) {
846
870
847 this.ctx.beginPath();
871 this.ctx.beginPath();
848 color = this.setColor(color, 0.25, 0.75);
872 color = this.setColor(color, 0.25, 0.75);
849 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
873 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
850 this.ctx.fill();
874 this.ctx.fill();
851
875
852 var bg = '<li class="bg parity' + parity + '"></li>';
876 var bg = '<li class="bg parity' + parity + '"></li>';
853 var left = (this.columns + 1) * this.bg_height;
877 var left = (this.columns + 1) * this.bg_height;
854 var nstyle = 'padding-left: ' + left + 'px;';
878 var nstyle = 'padding-left: ' + left + 'px;';
855 var item = revlink.replace(/_STYLE/, nstyle);
879 var item = revlink.replace(/_STYLE/, nstyle);
856 item = item.replace(/_PARITY/, 'parity' + parity);
880 item = item.replace(/_PARITY/, 'parity' + parity);
857 item = item.replace(/_NODEID/, cur[0]);
881 item = item.replace(/_NODEID/, cur[0]);
858 item = item.replace(/_NODEID/, cur[0]);
882 item = item.replace(/_NODEID/, cur[0]);
859 item = item.replace(/_DESC/, cur[3]);
883 item = item.replace(/_DESC/, cur[3]);
860 item = item.replace(/_USER/, cur[4]);
884 item = item.replace(/_USER/, cur[4]);
861 item = item.replace(/_DATE/, cur[5]);
885 item = item.replace(/_DATE/, cur[5]);
862
886
863 var tagspan = '';
887 var tagspan = '';
864 if (cur[7].length || cur[8].length || (cur[6][0] != 'default' || cur[6][1])) {
888 if (cur[7].length || cur[8].length || (cur[6][0] != 'default' || cur[6][1])) {
865 tagspan = '<span class="logtags">';
889 tagspan = '<span class="logtags">';
866 if (cur[6][1]) {
890 if (cur[6][1]) {
867 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
891 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
868 tagspan += cur[6][0] + '</span> ';
892 tagspan += cur[6][0] + '</span> ';
869 } else if (!cur[6][1] && cur[6][0] != 'default') {
893 } else if (!cur[6][1] && cur[6][0] != 'default') {
870 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
894 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
871 tagspan += cur[6][0] + '</span> ';
895 tagspan += cur[6][0] + '</span> ';
872 }
896 }
873 if (cur[7].length) {
897 if (cur[7].length) {
874 for (var t in cur[7]) {
898 for (var t in cur[7]) {
875 var tag = cur[7][t];
899 var tag = cur[7][t];
876 tagspan += '<span class="tagtag">' + tag + '</span> ';
900 tagspan += '<span class="tagtag">' + tag + '</span> ';
877 }
901 }
878 }
902 }
879 if (cur[8].length) {
903 if (cur[8].length) {
880 for (var t in cur[8]) {
904 for (var t in cur[8]) {
881 var bookmark = cur[8][t];
905 var bookmark = cur[8][t];
882 tagspan += '<span class="bookmarktag">' + bookmark + '</span> ';
906 tagspan += '<span class="bookmarktag">' + bookmark + '</span> ';
883 }
907 }
884 }
908 }
885 tagspan += '</span>';
909 tagspan += '</span>';
886 }
910 }
887
911
888 item = item.replace(/_TAGS/, tagspan);
912 item = item.replace(/_TAGS/, tagspan);
889 return [bg, item];
913 return [bg, item];
890
914
891 }
915 }
892
916
893 graph.render(data);
917 graph.render(data);
894
918
895 // stop hiding script -->
919 // stop hiding script -->
896 </script>
920 </script>
897
921
898 <div class="page_nav">
922 <div class="page_nav">
899 <a href="/graph/2?style=gitweb&revcount=30">less</a>
923 <a href="/graph/2?style=gitweb&revcount=30">less</a>
900 <a href="/graph/2?style=gitweb&revcount=120">more</a>
924 <a href="/graph/2?style=gitweb&revcount=120">more</a>
901 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a>
925 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a>
902 </div>
926 </div>
903
927
904 <div class="page_footer">
928 <div class="page_footer">
905 <div class="page_footer_text">test</div>
929 <div class="page_footer_text">test</div>
906 <div class="rss_logo">
930 <div class="rss_logo">
907 <a href="/rss-log">RSS</a>
931 <a href="/rss-log">RSS</a>
908 <a href="/atom-log">Atom</a>
932 <a href="/atom-log">Atom</a>
909 </div>
933 </div>
910 <br />
934 <br />
911
935
912 </div>
936 </div>
913 </body>
937 </body>
914 </html>
938 </html>
915
939
916
940
917 capabilities
941 capabilities
918
942
919 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
943 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
920 200 Script output follows
944 200 Script output follows
921
945
922 lookup changegroupsubset branchmap pushkey known getbundle unbundle=HG10GZ,HG10BZ,HG10UN
946 lookup changegroupsubset branchmap pushkey known getbundle unbundle=HG10GZ,HG10BZ,HG10UN
923
947
924 heads
948 heads
925
949
926 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
950 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
927 200 Script output follows
951 200 Script output follows
928
952
929 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
953 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
930
954
931 branches
955 branches
932
956
933 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches&nodes=0000000000000000000000000000000000000000'
957 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches&nodes=0000000000000000000000000000000000000000'
934 200 Script output follows
958 200 Script output follows
935
959
936 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
960 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
937
961
938 changegroup
962 changegroup
939
963
940 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
964 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
941 200 Script output follows
965 200 Script output follows
942
966
943 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)
967 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)
944 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)
968 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)
945 \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
969 \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
946 \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)
970 \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)
947
971
948 stream_out
972 stream_out
949
973
950 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out'
974 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out'
951 200 Script output follows
975 200 Script output follows
952
976
953 1
977 1
954
978
955 failing unbundle, requires POST request
979 failing unbundle, requires POST request
956
980
957 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle'
981 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle'
958 405 push requires POST request
982 405 push requires POST request
959
983
960 0
984 0
961 push requires POST request
985 push requires POST request
962 [1]
986 [1]
963
987
964 Static files
988 Static files
965
989
966 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css'
990 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css'
967 200 Script output follows
991 200 Script output follows
968
992
969 a { text-decoration:none; }
993 a { text-decoration:none; }
970 .age { white-space:nowrap; }
994 .age { white-space:nowrap; }
971 .date { white-space:nowrap; }
995 .date { white-space:nowrap; }
972 .indexlinks { white-space:nowrap; }
996 .indexlinks { white-space:nowrap; }
973 .parity0 { background-color: #ddd; }
997 .parity0 { background-color: #ddd; }
974 .parity1 { background-color: #eee; }
998 .parity1 { background-color: #eee; }
975 .lineno { width: 60px; color: #aaa; font-size: smaller;
999 .lineno { width: 60px; color: #aaa; font-size: smaller;
976 text-align: right; }
1000 text-align: right; }
977 .plusline { color: green; }
1001 .plusline { color: green; }
978 .minusline { color: red; }
1002 .minusline { color: red; }
979 .atline { color: purple; }
1003 .atline { color: purple; }
980 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
1004 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
981 .buttons a {
1005 .buttons a {
982 background-color: #666;
1006 background-color: #666;
983 padding: 2pt;
1007 padding: 2pt;
984 color: white;
1008 color: white;
985 font-family: sans;
1009 font-family: sans;
986 font-weight: bold;
1010 font-weight: bold;
987 }
1011 }
988 .navigate a {
1012 .navigate a {
989 background-color: #ccc;
1013 background-color: #ccc;
990 padding: 2pt;
1014 padding: 2pt;
991 font-family: sans;
1015 font-family: sans;
992 color: black;
1016 color: black;
993 }
1017 }
994
1018
995 .metatag {
1019 .metatag {
996 background-color: #888;
1020 background-color: #888;
997 color: white;
1021 color: white;
998 text-align: right;
1022 text-align: right;
999 }
1023 }
1000
1024
1001 /* Common */
1025 /* Common */
1002 pre { margin: 0; }
1026 pre { margin: 0; }
1003
1027
1004 .logo {
1028 .logo {
1005 float: right;
1029 float: right;
1006 clear: right;
1030 clear: right;
1007 }
1031 }
1008
1032
1009 /* Changelog/Filelog entries */
1033 /* Changelog/Filelog entries */
1010 .logEntry { width: 100%; }
1034 .logEntry { width: 100%; }
1011 .logEntry .age { width: 15%; }
1035 .logEntry .age { width: 15%; }
1012 .logEntry th { font-weight: normal; text-align: right; vertical-align: top; }
1036 .logEntry th { font-weight: normal; text-align: right; vertical-align: top; }
1013 .logEntry th.age, .logEntry th.firstline { font-weight: bold; }
1037 .logEntry th.age, .logEntry th.firstline { font-weight: bold; }
1014 .logEntry th.firstline { text-align: left; width: inherit; }
1038 .logEntry th.firstline { text-align: left; width: inherit; }
1015
1039
1016 /* Shortlog entries */
1040 /* Shortlog entries */
1017 .slogEntry { width: 100%; }
1041 .slogEntry { width: 100%; }
1018 .slogEntry .age { width: 8em; }
1042 .slogEntry .age { width: 8em; }
1019 .slogEntry td { font-weight: normal; text-align: left; vertical-align: top; }
1043 .slogEntry td { font-weight: normal; text-align: left; vertical-align: top; }
1020 .slogEntry td.author { width: 15em; }
1044 .slogEntry td.author { width: 15em; }
1021
1045
1022 /* Tag entries */
1046 /* Tag entries */
1023 #tagEntries { list-style: none; margin: 0; padding: 0; }
1047 #tagEntries { list-style: none; margin: 0; padding: 0; }
1024 #tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
1048 #tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
1025
1049
1026 /* Changeset entry */
1050 /* Changeset entry */
1027 #changesetEntry { }
1051 #changesetEntry { }
1028 #changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1052 #changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1029 #changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
1053 #changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
1030
1054
1031 /* File diff view */
1055 /* File diff view */
1032 #filediffEntry { }
1056 #filediffEntry { }
1033 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1057 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1034
1058
1035 /* Graph */
1059 /* Graph */
1036 div#wrapper {
1060 div#wrapper {
1037 position: relative;
1061 position: relative;
1038 margin: 0;
1062 margin: 0;
1039 padding: 0;
1063 padding: 0;
1040 }
1064 }
1041
1065
1042 canvas {
1066 canvas {
1043 position: absolute;
1067 position: absolute;
1044 z-index: 5;
1068 z-index: 5;
1045 top: -0.6em;
1069 top: -0.6em;
1046 margin: 0;
1070 margin: 0;
1047 }
1071 }
1048
1072
1049 ul#nodebgs {
1073 ul#nodebgs {
1050 list-style: none inside none;
1074 list-style: none inside none;
1051 padding: 0;
1075 padding: 0;
1052 margin: 0;
1076 margin: 0;
1053 top: -0.7em;
1077 top: -0.7em;
1054 }
1078 }
1055
1079
1056 ul#graphnodes li, ul#nodebgs li {
1080 ul#graphnodes li, ul#nodebgs li {
1057 height: 39px;
1081 height: 39px;
1058 }
1082 }
1059
1083
1060 ul#graphnodes {
1084 ul#graphnodes {
1061 position: absolute;
1085 position: absolute;
1062 z-index: 10;
1086 z-index: 10;
1063 top: -0.85em;
1087 top: -0.85em;
1064 list-style: none inside none;
1088 list-style: none inside none;
1065 padding: 0;
1089 padding: 0;
1066 }
1090 }
1067
1091
1068 ul#graphnodes li .info {
1092 ul#graphnodes li .info {
1069 display: block;
1093 display: block;
1070 font-size: 70%;
1094 font-size: 70%;
1071 position: relative;
1095 position: relative;
1072 top: -1px;
1096 top: -1px;
1073 }
1097 }
1074
1098
1075 Stop and restart with HGENCODING=cp932
1099 Stop and restart with HGENCODING=cp932
1076
1100
1077 $ "$TESTDIR/killdaemons.py"
1101 $ "$TESTDIR/killdaemons.py"
1078 $ HGENCODING=cp932 hg serve --config server.uncompressed=False -n test \
1102 $ HGENCODING=cp932 hg serve --config server.uncompressed=False -n test \
1079 > -p $HGPORT -d --pid-file=hg.pid -E errors.log
1103 > -p $HGPORT -d --pid-file=hg.pid -E errors.log
1080 $ cat hg.pid >> $DAEMON_PIDS
1104 $ cat hg.pid >> $DAEMON_PIDS
1081
1105
1082 commit message with Japanese Kanji 'Noh', which ends with '\x5c'
1106 commit message with Japanese Kanji 'Noh', which ends with '\x5c'
1083
1107
1084 $ echo foo >> foo
1108 $ echo foo >> foo
1085 $ HGENCODING=cp932 hg ci -m `python -c 'print("\x94\x5c")'`
1109 $ HGENCODING=cp932 hg ci -m `python -c 'print("\x94\x5c")'`
1086
1110
1087 Graph json escape of multibyte character
1111 Graph json escape of multibyte character
1088
1112
1089 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
1113 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
1090 > | grep '^var data ='
1114 > | grep '^var data ='
1091 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"], ["anotherthing"]]];
1115 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"], ["anotherthing"]]];
1092
1116
1093 ERRORS ENCOUNTERED
1117 ERRORS ENCOUNTERED
1094
1118
1095 $ cat errors.log
1119 $ cat errors.log
General Comments 0
You need to be logged in to leave comments. Login now