##// END OF EJS Templates
hgweb: do not audit URL path as working-directory path...
Yuya Nishihara -
r39507:15e8250a default
parent child Browse files
Show More
@@ -1,812 +1,813 b''
1 # hgweb/webutil.py - utility library for the web interface.
1 # hgweb/webutil.py - utility library for the web interface.
2 #
2 #
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 import copy
11 import copy
12 import difflib
12 import difflib
13 import os
13 import os
14 import re
14 import re
15
15
16 from ..i18n import _
16 from ..i18n import _
17 from ..node import hex, nullid, short
17 from ..node import hex, nullid, short
18
18
19 from .common import (
19 from .common import (
20 ErrorResponse,
20 ErrorResponse,
21 HTTP_BAD_REQUEST,
21 HTTP_BAD_REQUEST,
22 HTTP_NOT_FOUND,
22 HTTP_NOT_FOUND,
23 paritygen,
23 paritygen,
24 )
24 )
25
25
26 from .. import (
26 from .. import (
27 context,
27 context,
28 diffutil,
28 diffutil,
29 error,
29 error,
30 match,
30 match,
31 mdiff,
31 mdiff,
32 obsutil,
32 obsutil,
33 patch,
33 patch,
34 pathutil,
34 pathutil,
35 pycompat,
35 pycompat,
36 scmutil,
36 scmutil,
37 templatefilters,
37 templatefilters,
38 templatekw,
38 templatekw,
39 templateutil,
39 templateutil,
40 ui as uimod,
40 ui as uimod,
41 util,
41 util,
42 )
42 )
43
43
44 from ..utils import (
44 from ..utils import (
45 stringutil,
45 stringutil,
46 )
46 )
47
47
48 archivespecs = util.sortdict((
48 archivespecs = util.sortdict((
49 ('zip', ('application/zip', 'zip', '.zip', None)),
49 ('zip', ('application/zip', 'zip', '.zip', None)),
50 ('gz', ('application/x-gzip', 'tgz', '.tar.gz', None)),
50 ('gz', ('application/x-gzip', 'tgz', '.tar.gz', None)),
51 ('bz2', ('application/x-bzip2', 'tbz2', '.tar.bz2', None)),
51 ('bz2', ('application/x-bzip2', 'tbz2', '.tar.bz2', None)),
52 ))
52 ))
53
53
54 def archivelist(ui, nodeid, url=None):
54 def archivelist(ui, nodeid, url=None):
55 allowed = ui.configlist('web', 'allow-archive', untrusted=True)
55 allowed = ui.configlist('web', 'allow-archive', untrusted=True)
56 archives = []
56 archives = []
57
57
58 for typ, spec in archivespecs.iteritems():
58 for typ, spec in archivespecs.iteritems():
59 if typ in allowed or ui.configbool('web', 'allow' + typ,
59 if typ in allowed or ui.configbool('web', 'allow' + typ,
60 untrusted=True):
60 untrusted=True):
61 archives.append({
61 archives.append({
62 'type': typ,
62 'type': typ,
63 'extension': spec[2],
63 'extension': spec[2],
64 'node': nodeid,
64 'node': nodeid,
65 'url': url,
65 'url': url,
66 })
66 })
67
67
68 return templateutil.mappinglist(archives)
68 return templateutil.mappinglist(archives)
69
69
70 def up(p):
70 def up(p):
71 if p[0:1] != "/":
71 if p[0:1] != "/":
72 p = "/" + p
72 p = "/" + p
73 if p[-1:] == "/":
73 if p[-1:] == "/":
74 p = p[:-1]
74 p = p[:-1]
75 up = os.path.dirname(p)
75 up = os.path.dirname(p)
76 if up == "/":
76 if up == "/":
77 return "/"
77 return "/"
78 return up + "/"
78 return up + "/"
79
79
80 def _navseq(step, firststep=None):
80 def _navseq(step, firststep=None):
81 if firststep:
81 if firststep:
82 yield firststep
82 yield firststep
83 if firststep >= 20 and firststep <= 40:
83 if firststep >= 20 and firststep <= 40:
84 firststep = 50
84 firststep = 50
85 yield firststep
85 yield firststep
86 assert step > 0
86 assert step > 0
87 assert firststep > 0
87 assert firststep > 0
88 while step <= firststep:
88 while step <= firststep:
89 step *= 10
89 step *= 10
90 while True:
90 while True:
91 yield 1 * step
91 yield 1 * step
92 yield 3 * step
92 yield 3 * step
93 step *= 10
93 step *= 10
94
94
95 class revnav(object):
95 class revnav(object):
96
96
97 def __init__(self, repo):
97 def __init__(self, repo):
98 """Navigation generation object
98 """Navigation generation object
99
99
100 :repo: repo object we generate nav for
100 :repo: repo object we generate nav for
101 """
101 """
102 # used for hex generation
102 # used for hex generation
103 self._revlog = repo.changelog
103 self._revlog = repo.changelog
104
104
105 def __nonzero__(self):
105 def __nonzero__(self):
106 """return True if any revision to navigate over"""
106 """return True if any revision to navigate over"""
107 return self._first() is not None
107 return self._first() is not None
108
108
109 __bool__ = __nonzero__
109 __bool__ = __nonzero__
110
110
111 def _first(self):
111 def _first(self):
112 """return the minimum non-filtered changeset or None"""
112 """return the minimum non-filtered changeset or None"""
113 try:
113 try:
114 return next(iter(self._revlog))
114 return next(iter(self._revlog))
115 except StopIteration:
115 except StopIteration:
116 return None
116 return None
117
117
118 def hex(self, rev):
118 def hex(self, rev):
119 return hex(self._revlog.node(rev))
119 return hex(self._revlog.node(rev))
120
120
121 def gen(self, pos, pagelen, limit):
121 def gen(self, pos, pagelen, limit):
122 """computes label and revision id for navigation link
122 """computes label and revision id for navigation link
123
123
124 :pos: is the revision relative to which we generate navigation.
124 :pos: is the revision relative to which we generate navigation.
125 :pagelen: the size of each navigation page
125 :pagelen: the size of each navigation page
126 :limit: how far shall we link
126 :limit: how far shall we link
127
127
128 The return is:
128 The return is:
129 - a single element mappinglist
129 - a single element mappinglist
130 - containing a dictionary with a `before` and `after` key
130 - containing a dictionary with a `before` and `after` key
131 - values are dictionaries with `label` and `node` keys
131 - values are dictionaries with `label` and `node` keys
132 """
132 """
133 if not self:
133 if not self:
134 # empty repo
134 # empty repo
135 return templateutil.mappinglist([
135 return templateutil.mappinglist([
136 {'before': templateutil.mappinglist([]),
136 {'before': templateutil.mappinglist([]),
137 'after': templateutil.mappinglist([])},
137 'after': templateutil.mappinglist([])},
138 ])
138 ])
139
139
140 targets = []
140 targets = []
141 for f in _navseq(1, pagelen):
141 for f in _navseq(1, pagelen):
142 if f > limit:
142 if f > limit:
143 break
143 break
144 targets.append(pos + f)
144 targets.append(pos + f)
145 targets.append(pos - f)
145 targets.append(pos - f)
146 targets.sort()
146 targets.sort()
147
147
148 first = self._first()
148 first = self._first()
149 navbefore = [{'label': '(%i)' % first, 'node': self.hex(first)}]
149 navbefore = [{'label': '(%i)' % first, 'node': self.hex(first)}]
150 navafter = []
150 navafter = []
151 for rev in targets:
151 for rev in targets:
152 if rev not in self._revlog:
152 if rev not in self._revlog:
153 continue
153 continue
154 if pos < rev < limit:
154 if pos < rev < limit:
155 navafter.append({'label': '+%d' % abs(rev - pos),
155 navafter.append({'label': '+%d' % abs(rev - pos),
156 'node': self.hex(rev)})
156 'node': self.hex(rev)})
157 if 0 < rev < pos:
157 if 0 < rev < pos:
158 navbefore.append({'label': '-%d' % abs(rev - pos),
158 navbefore.append({'label': '-%d' % abs(rev - pos),
159 'node': self.hex(rev)})
159 'node': self.hex(rev)})
160
160
161 navafter.append({'label': 'tip', 'node': 'tip'})
161 navafter.append({'label': 'tip', 'node': 'tip'})
162
162
163 # TODO: maybe this can be a scalar object supporting tomap()
163 # TODO: maybe this can be a scalar object supporting tomap()
164 return templateutil.mappinglist([
164 return templateutil.mappinglist([
165 {'before': templateutil.mappinglist(navbefore),
165 {'before': templateutil.mappinglist(navbefore),
166 'after': templateutil.mappinglist(navafter)},
166 'after': templateutil.mappinglist(navafter)},
167 ])
167 ])
168
168
169 class filerevnav(revnav):
169 class filerevnav(revnav):
170
170
171 def __init__(self, repo, path):
171 def __init__(self, repo, path):
172 """Navigation generation object
172 """Navigation generation object
173
173
174 :repo: repo object we generate nav for
174 :repo: repo object we generate nav for
175 :path: path of the file we generate nav for
175 :path: path of the file we generate nav for
176 """
176 """
177 # used for iteration
177 # used for iteration
178 self._changelog = repo.unfiltered().changelog
178 self._changelog = repo.unfiltered().changelog
179 # used for hex generation
179 # used for hex generation
180 self._revlog = repo.file(path)
180 self._revlog = repo.file(path)
181
181
182 def hex(self, rev):
182 def hex(self, rev):
183 return hex(self._changelog.node(self._revlog.linkrev(rev)))
183 return hex(self._changelog.node(self._revlog.linkrev(rev)))
184
184
185 # TODO: maybe this can be a wrapper class for changectx/filectx list, which
185 # TODO: maybe this can be a wrapper class for changectx/filectx list, which
186 # yields {'ctx': ctx}
186 # yields {'ctx': ctx}
187 def _ctxsgen(context, ctxs):
187 def _ctxsgen(context, ctxs):
188 for s in ctxs:
188 for s in ctxs:
189 d = {
189 d = {
190 'node': s.hex(),
190 'node': s.hex(),
191 'rev': s.rev(),
191 'rev': s.rev(),
192 'user': s.user(),
192 'user': s.user(),
193 'date': s.date(),
193 'date': s.date(),
194 'description': s.description(),
194 'description': s.description(),
195 'branch': s.branch(),
195 'branch': s.branch(),
196 }
196 }
197 if util.safehasattr(s, 'path'):
197 if util.safehasattr(s, 'path'):
198 d['file'] = s.path()
198 d['file'] = s.path()
199 yield d
199 yield d
200
200
201 def _siblings(siblings=None, hiderev=None):
201 def _siblings(siblings=None, hiderev=None):
202 if siblings is None:
202 if siblings is None:
203 siblings = []
203 siblings = []
204 siblings = [s for s in siblings if s.node() != nullid]
204 siblings = [s for s in siblings if s.node() != nullid]
205 if len(siblings) == 1 and siblings[0].rev() == hiderev:
205 if len(siblings) == 1 and siblings[0].rev() == hiderev:
206 siblings = []
206 siblings = []
207 return templateutil.mappinggenerator(_ctxsgen, args=(siblings,))
207 return templateutil.mappinggenerator(_ctxsgen, args=(siblings,))
208
208
209 def difffeatureopts(req, ui, section):
209 def difffeatureopts(req, ui, section):
210 diffopts = diffutil.difffeatureopts(ui, untrusted=True,
210 diffopts = diffutil.difffeatureopts(ui, untrusted=True,
211 section=section, whitespace=True)
211 section=section, whitespace=True)
212
212
213 for k in ('ignorews', 'ignorewsamount', 'ignorewseol', 'ignoreblanklines'):
213 for k in ('ignorews', 'ignorewsamount', 'ignorewseol', 'ignoreblanklines'):
214 v = req.qsparams.get(k)
214 v = req.qsparams.get(k)
215 if v is not None:
215 if v is not None:
216 v = stringutil.parsebool(v)
216 v = stringutil.parsebool(v)
217 setattr(diffopts, k, v if v is not None else True)
217 setattr(diffopts, k, v if v is not None else True)
218
218
219 return diffopts
219 return diffopts
220
220
221 def annotate(req, fctx, ui):
221 def annotate(req, fctx, ui):
222 diffopts = difffeatureopts(req, ui, 'annotate')
222 diffopts = difffeatureopts(req, ui, 'annotate')
223 return fctx.annotate(follow=True, diffopts=diffopts)
223 return fctx.annotate(follow=True, diffopts=diffopts)
224
224
225 def parents(ctx, hide=None):
225 def parents(ctx, hide=None):
226 if isinstance(ctx, context.basefilectx):
226 if isinstance(ctx, context.basefilectx):
227 introrev = ctx.introrev()
227 introrev = ctx.introrev()
228 if ctx.changectx().rev() != introrev:
228 if ctx.changectx().rev() != introrev:
229 return _siblings([ctx.repo()[introrev]], hide)
229 return _siblings([ctx.repo()[introrev]], hide)
230 return _siblings(ctx.parents(), hide)
230 return _siblings(ctx.parents(), hide)
231
231
232 def children(ctx, hide=None):
232 def children(ctx, hide=None):
233 return _siblings(ctx.children(), hide)
233 return _siblings(ctx.children(), hide)
234
234
235 def renamelink(fctx):
235 def renamelink(fctx):
236 r = fctx.renamed()
236 r = fctx.renamed()
237 if r:
237 if r:
238 return templateutil.mappinglist([{'file': r[0], 'node': hex(r[1])}])
238 return templateutil.mappinglist([{'file': r[0], 'node': hex(r[1])}])
239 return templateutil.mappinglist([])
239 return templateutil.mappinglist([])
240
240
241 def nodetagsdict(repo, node):
241 def nodetagsdict(repo, node):
242 return templateutil.hybridlist(repo.nodetags(node), name='name')
242 return templateutil.hybridlist(repo.nodetags(node), name='name')
243
243
244 def nodebookmarksdict(repo, node):
244 def nodebookmarksdict(repo, node):
245 return templateutil.hybridlist(repo.nodebookmarks(node), name='name')
245 return templateutil.hybridlist(repo.nodebookmarks(node), name='name')
246
246
247 def nodebranchdict(repo, ctx):
247 def nodebranchdict(repo, ctx):
248 branches = []
248 branches = []
249 branch = ctx.branch()
249 branch = ctx.branch()
250 # If this is an empty repo, ctx.node() == nullid,
250 # If this is an empty repo, ctx.node() == nullid,
251 # ctx.branch() == 'default'.
251 # ctx.branch() == 'default'.
252 try:
252 try:
253 branchnode = repo.branchtip(branch)
253 branchnode = repo.branchtip(branch)
254 except error.RepoLookupError:
254 except error.RepoLookupError:
255 branchnode = None
255 branchnode = None
256 if branchnode == ctx.node():
256 if branchnode == ctx.node():
257 branches.append(branch)
257 branches.append(branch)
258 return templateutil.hybridlist(branches, name='name')
258 return templateutil.hybridlist(branches, name='name')
259
259
260 def nodeinbranch(repo, ctx):
260 def nodeinbranch(repo, ctx):
261 branches = []
261 branches = []
262 branch = ctx.branch()
262 branch = ctx.branch()
263 try:
263 try:
264 branchnode = repo.branchtip(branch)
264 branchnode = repo.branchtip(branch)
265 except error.RepoLookupError:
265 except error.RepoLookupError:
266 branchnode = None
266 branchnode = None
267 if branch != 'default' and branchnode != ctx.node():
267 if branch != 'default' and branchnode != ctx.node():
268 branches.append(branch)
268 branches.append(branch)
269 return templateutil.hybridlist(branches, name='name')
269 return templateutil.hybridlist(branches, name='name')
270
270
271 def nodebranchnodefault(ctx):
271 def nodebranchnodefault(ctx):
272 branches = []
272 branches = []
273 branch = ctx.branch()
273 branch = ctx.branch()
274 if branch != 'default':
274 if branch != 'default':
275 branches.append(branch)
275 branches.append(branch)
276 return templateutil.hybridlist(branches, name='name')
276 return templateutil.hybridlist(branches, name='name')
277
277
278 def _nodenamesgen(context, f, node, name):
278 def _nodenamesgen(context, f, node, name):
279 for t in f(node):
279 for t in f(node):
280 yield {name: t}
280 yield {name: t}
281
281
282 def showtag(repo, t1, node=nullid):
282 def showtag(repo, t1, node=nullid):
283 args = (repo.nodetags, node, 'tag')
283 args = (repo.nodetags, node, 'tag')
284 return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1)
284 return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1)
285
285
286 def showbookmark(repo, t1, node=nullid):
286 def showbookmark(repo, t1, node=nullid):
287 args = (repo.nodebookmarks, node, 'bookmark')
287 args = (repo.nodebookmarks, node, 'bookmark')
288 return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1)
288 return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1)
289
289
290 def branchentries(repo, stripecount, limit=0):
290 def branchentries(repo, stripecount, limit=0):
291 tips = []
291 tips = []
292 heads = repo.heads()
292 heads = repo.heads()
293 parity = paritygen(stripecount)
293 parity = paritygen(stripecount)
294 sortkey = lambda item: (not item[1], item[0].rev())
294 sortkey = lambda item: (not item[1], item[0].rev())
295
295
296 def entries(context):
296 def entries(context):
297 count = 0
297 count = 0
298 if not tips:
298 if not tips:
299 for tag, hs, tip, closed in repo.branchmap().iterbranches():
299 for tag, hs, tip, closed in repo.branchmap().iterbranches():
300 tips.append((repo[tip], closed))
300 tips.append((repo[tip], closed))
301 for ctx, closed in sorted(tips, key=sortkey, reverse=True):
301 for ctx, closed in sorted(tips, key=sortkey, reverse=True):
302 if limit > 0 and count >= limit:
302 if limit > 0 and count >= limit:
303 return
303 return
304 count += 1
304 count += 1
305 if closed:
305 if closed:
306 status = 'closed'
306 status = 'closed'
307 elif ctx.node() not in heads:
307 elif ctx.node() not in heads:
308 status = 'inactive'
308 status = 'inactive'
309 else:
309 else:
310 status = 'open'
310 status = 'open'
311 yield {
311 yield {
312 'parity': next(parity),
312 'parity': next(parity),
313 'branch': ctx.branch(),
313 'branch': ctx.branch(),
314 'status': status,
314 'status': status,
315 'node': ctx.hex(),
315 'node': ctx.hex(),
316 'date': ctx.date()
316 'date': ctx.date()
317 }
317 }
318
318
319 return templateutil.mappinggenerator(entries)
319 return templateutil.mappinggenerator(entries)
320
320
321 def cleanpath(repo, path):
321 def cleanpath(repo, path):
322 path = path.lstrip('/')
322 path = path.lstrip('/')
323 return pathutil.canonpath(repo.root, '', path)
323 auditor = pathutil.pathauditor(repo.root, realfs=False)
324 return pathutil.canonpath(repo.root, '', path, auditor=auditor)
324
325
325 def changectx(repo, req):
326 def changectx(repo, req):
326 changeid = "tip"
327 changeid = "tip"
327 if 'node' in req.qsparams:
328 if 'node' in req.qsparams:
328 changeid = req.qsparams['node']
329 changeid = req.qsparams['node']
329 ipos = changeid.find(':')
330 ipos = changeid.find(':')
330 if ipos != -1:
331 if ipos != -1:
331 changeid = changeid[(ipos + 1):]
332 changeid = changeid[(ipos + 1):]
332
333
333 return scmutil.revsymbol(repo, changeid)
334 return scmutil.revsymbol(repo, changeid)
334
335
335 def basechangectx(repo, req):
336 def basechangectx(repo, req):
336 if 'node' in req.qsparams:
337 if 'node' in req.qsparams:
337 changeid = req.qsparams['node']
338 changeid = req.qsparams['node']
338 ipos = changeid.find(':')
339 ipos = changeid.find(':')
339 if ipos != -1:
340 if ipos != -1:
340 changeid = changeid[:ipos]
341 changeid = changeid[:ipos]
341 return scmutil.revsymbol(repo, changeid)
342 return scmutil.revsymbol(repo, changeid)
342
343
343 return None
344 return None
344
345
345 def filectx(repo, req):
346 def filectx(repo, req):
346 if 'file' not in req.qsparams:
347 if 'file' not in req.qsparams:
347 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
348 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
348 path = cleanpath(repo, req.qsparams['file'])
349 path = cleanpath(repo, req.qsparams['file'])
349 if 'node' in req.qsparams:
350 if 'node' in req.qsparams:
350 changeid = req.qsparams['node']
351 changeid = req.qsparams['node']
351 elif 'filenode' in req.qsparams:
352 elif 'filenode' in req.qsparams:
352 changeid = req.qsparams['filenode']
353 changeid = req.qsparams['filenode']
353 else:
354 else:
354 raise ErrorResponse(HTTP_NOT_FOUND, 'node or filenode not given')
355 raise ErrorResponse(HTTP_NOT_FOUND, 'node or filenode not given')
355 try:
356 try:
356 fctx = scmutil.revsymbol(repo, changeid)[path]
357 fctx = scmutil.revsymbol(repo, changeid)[path]
357 except error.RepoError:
358 except error.RepoError:
358 fctx = repo.filectx(path, fileid=changeid)
359 fctx = repo.filectx(path, fileid=changeid)
359
360
360 return fctx
361 return fctx
361
362
362 def linerange(req):
363 def linerange(req):
363 linerange = req.qsparams.getall('linerange')
364 linerange = req.qsparams.getall('linerange')
364 if not linerange:
365 if not linerange:
365 return None
366 return None
366 if len(linerange) > 1:
367 if len(linerange) > 1:
367 raise ErrorResponse(HTTP_BAD_REQUEST,
368 raise ErrorResponse(HTTP_BAD_REQUEST,
368 'redundant linerange parameter')
369 'redundant linerange parameter')
369 try:
370 try:
370 fromline, toline = map(int, linerange[0].split(':', 1))
371 fromline, toline = map(int, linerange[0].split(':', 1))
371 except ValueError:
372 except ValueError:
372 raise ErrorResponse(HTTP_BAD_REQUEST,
373 raise ErrorResponse(HTTP_BAD_REQUEST,
373 'invalid linerange parameter')
374 'invalid linerange parameter')
374 try:
375 try:
375 return util.processlinerange(fromline, toline)
376 return util.processlinerange(fromline, toline)
376 except error.ParseError as exc:
377 except error.ParseError as exc:
377 raise ErrorResponse(HTTP_BAD_REQUEST, pycompat.bytestr(exc))
378 raise ErrorResponse(HTTP_BAD_REQUEST, pycompat.bytestr(exc))
378
379
379 def formatlinerange(fromline, toline):
380 def formatlinerange(fromline, toline):
380 return '%d:%d' % (fromline + 1, toline)
381 return '%d:%d' % (fromline + 1, toline)
381
382
382 def _succsandmarkersgen(context, mapping):
383 def _succsandmarkersgen(context, mapping):
383 repo = context.resource(mapping, 'repo')
384 repo = context.resource(mapping, 'repo')
384 itemmappings = templatekw.showsuccsandmarkers(context, mapping)
385 itemmappings = templatekw.showsuccsandmarkers(context, mapping)
385 for item in itemmappings.tovalue(context, mapping):
386 for item in itemmappings.tovalue(context, mapping):
386 item['successors'] = _siblings(repo[successor]
387 item['successors'] = _siblings(repo[successor]
387 for successor in item['successors'])
388 for successor in item['successors'])
388 yield item
389 yield item
389
390
390 def succsandmarkers(context, mapping):
391 def succsandmarkers(context, mapping):
391 return templateutil.mappinggenerator(_succsandmarkersgen, args=(mapping,))
392 return templateutil.mappinggenerator(_succsandmarkersgen, args=(mapping,))
392
393
393 # teach templater succsandmarkers is switched to (context, mapping) API
394 # teach templater succsandmarkers is switched to (context, mapping) API
394 succsandmarkers._requires = {'repo', 'ctx'}
395 succsandmarkers._requires = {'repo', 'ctx'}
395
396
396 def _whyunstablegen(context, mapping):
397 def _whyunstablegen(context, mapping):
397 repo = context.resource(mapping, 'repo')
398 repo = context.resource(mapping, 'repo')
398 ctx = context.resource(mapping, 'ctx')
399 ctx = context.resource(mapping, 'ctx')
399
400
400 entries = obsutil.whyunstable(repo, ctx)
401 entries = obsutil.whyunstable(repo, ctx)
401 for entry in entries:
402 for entry in entries:
402 if entry.get('divergentnodes'):
403 if entry.get('divergentnodes'):
403 entry['divergentnodes'] = _siblings(entry['divergentnodes'])
404 entry['divergentnodes'] = _siblings(entry['divergentnodes'])
404 yield entry
405 yield entry
405
406
406 def whyunstable(context, mapping):
407 def whyunstable(context, mapping):
407 return templateutil.mappinggenerator(_whyunstablegen, args=(mapping,))
408 return templateutil.mappinggenerator(_whyunstablegen, args=(mapping,))
408
409
409 whyunstable._requires = {'repo', 'ctx'}
410 whyunstable._requires = {'repo', 'ctx'}
410
411
411 # helper to mark a function as a new-style template keyword; can be removed
412 # helper to mark a function as a new-style template keyword; can be removed
412 # once old-style function gets unsupported and new-style becomes the default
413 # once old-style function gets unsupported and new-style becomes the default
413 def _kwfunc(f):
414 def _kwfunc(f):
414 f._requires = ()
415 f._requires = ()
415 return f
416 return f
416
417
417 def commonentry(repo, ctx):
418 def commonentry(repo, ctx):
418 node = ctx.node()
419 node = ctx.node()
419 return {
420 return {
420 # TODO: perhaps ctx.changectx() should be assigned if ctx is a
421 # TODO: perhaps ctx.changectx() should be assigned if ctx is a
421 # filectx, but I'm not pretty sure if that would always work because
422 # filectx, but I'm not pretty sure if that would always work because
422 # fctx.parents() != fctx.changectx.parents() for example.
423 # fctx.parents() != fctx.changectx.parents() for example.
423 'ctx': ctx,
424 'ctx': ctx,
424 'rev': ctx.rev(),
425 'rev': ctx.rev(),
425 'node': hex(node),
426 'node': hex(node),
426 'author': ctx.user(),
427 'author': ctx.user(),
427 'desc': ctx.description(),
428 'desc': ctx.description(),
428 'date': ctx.date(),
429 'date': ctx.date(),
429 'extra': ctx.extra(),
430 'extra': ctx.extra(),
430 'phase': ctx.phasestr(),
431 'phase': ctx.phasestr(),
431 'obsolete': ctx.obsolete(),
432 'obsolete': ctx.obsolete(),
432 'succsandmarkers': succsandmarkers,
433 'succsandmarkers': succsandmarkers,
433 'instabilities': templateutil.hybridlist(ctx.instabilities(),
434 'instabilities': templateutil.hybridlist(ctx.instabilities(),
434 name='instability'),
435 name='instability'),
435 'whyunstable': whyunstable,
436 'whyunstable': whyunstable,
436 'branch': nodebranchnodefault(ctx),
437 'branch': nodebranchnodefault(ctx),
437 'inbranch': nodeinbranch(repo, ctx),
438 'inbranch': nodeinbranch(repo, ctx),
438 'branches': nodebranchdict(repo, ctx),
439 'branches': nodebranchdict(repo, ctx),
439 'tags': nodetagsdict(repo, node),
440 'tags': nodetagsdict(repo, node),
440 'bookmarks': nodebookmarksdict(repo, node),
441 'bookmarks': nodebookmarksdict(repo, node),
441 'parent': _kwfunc(lambda context, mapping: parents(ctx)),
442 'parent': _kwfunc(lambda context, mapping: parents(ctx)),
442 'child': _kwfunc(lambda context, mapping: children(ctx)),
443 'child': _kwfunc(lambda context, mapping: children(ctx)),
443 }
444 }
444
445
445 def changelistentry(web, ctx):
446 def changelistentry(web, ctx):
446 '''Obtain a dictionary to be used for entries in a changelist.
447 '''Obtain a dictionary to be used for entries in a changelist.
447
448
448 This function is called when producing items for the "entries" list passed
449 This function is called when producing items for the "entries" list passed
449 to the "shortlog" and "changelog" templates.
450 to the "shortlog" and "changelog" templates.
450 '''
451 '''
451 repo = web.repo
452 repo = web.repo
452 rev = ctx.rev()
453 rev = ctx.rev()
453 n = ctx.node()
454 n = ctx.node()
454 showtags = showtag(repo, 'changelogtag', n)
455 showtags = showtag(repo, 'changelogtag', n)
455 files = listfilediffs(ctx.files(), n, web.maxfiles)
456 files = listfilediffs(ctx.files(), n, web.maxfiles)
456
457
457 entry = commonentry(repo, ctx)
458 entry = commonentry(repo, ctx)
458 entry.update(
459 entry.update(
459 allparents=_kwfunc(lambda context, mapping: parents(ctx)),
460 allparents=_kwfunc(lambda context, mapping: parents(ctx)),
460 parent=_kwfunc(lambda context, mapping: parents(ctx, rev - 1)),
461 parent=_kwfunc(lambda context, mapping: parents(ctx, rev - 1)),
461 child=_kwfunc(lambda context, mapping: children(ctx, rev + 1)),
462 child=_kwfunc(lambda context, mapping: children(ctx, rev + 1)),
462 changelogtag=showtags,
463 changelogtag=showtags,
463 files=files,
464 files=files,
464 )
465 )
465 return entry
466 return entry
466
467
467 def changelistentries(web, revs, maxcount, parityfn):
468 def changelistentries(web, revs, maxcount, parityfn):
468 """Emit up to N records for an iterable of revisions."""
469 """Emit up to N records for an iterable of revisions."""
469 repo = web.repo
470 repo = web.repo
470
471
471 count = 0
472 count = 0
472 for rev in revs:
473 for rev in revs:
473 if count >= maxcount:
474 if count >= maxcount:
474 break
475 break
475
476
476 count += 1
477 count += 1
477
478
478 entry = changelistentry(web, repo[rev])
479 entry = changelistentry(web, repo[rev])
479 entry['parity'] = next(parityfn)
480 entry['parity'] = next(parityfn)
480
481
481 yield entry
482 yield entry
482
483
483 def symrevorshortnode(req, ctx):
484 def symrevorshortnode(req, ctx):
484 if 'node' in req.qsparams:
485 if 'node' in req.qsparams:
485 return templatefilters.revescape(req.qsparams['node'])
486 return templatefilters.revescape(req.qsparams['node'])
486 else:
487 else:
487 return short(ctx.node())
488 return short(ctx.node())
488
489
489 def _listfilesgen(context, ctx, stripecount):
490 def _listfilesgen(context, ctx, stripecount):
490 parity = paritygen(stripecount)
491 parity = paritygen(stripecount)
491 for blockno, f in enumerate(ctx.files()):
492 for blockno, f in enumerate(ctx.files()):
492 template = 'filenodelink' if f in ctx else 'filenolink'
493 template = 'filenodelink' if f in ctx else 'filenolink'
493 yield context.process(template, {
494 yield context.process(template, {
494 'node': ctx.hex(),
495 'node': ctx.hex(),
495 'file': f,
496 'file': f,
496 'blockno': blockno + 1,
497 'blockno': blockno + 1,
497 'parity': next(parity),
498 'parity': next(parity),
498 })
499 })
499
500
500 def changesetentry(web, ctx):
501 def changesetentry(web, ctx):
501 '''Obtain a dictionary to be used to render the "changeset" template.'''
502 '''Obtain a dictionary to be used to render the "changeset" template.'''
502
503
503 showtags = showtag(web.repo, 'changesettag', ctx.node())
504 showtags = showtag(web.repo, 'changesettag', ctx.node())
504 showbookmarks = showbookmark(web.repo, 'changesetbookmark', ctx.node())
505 showbookmarks = showbookmark(web.repo, 'changesetbookmark', ctx.node())
505 showbranch = nodebranchnodefault(ctx)
506 showbranch = nodebranchnodefault(ctx)
506
507
507 basectx = basechangectx(web.repo, web.req)
508 basectx = basechangectx(web.repo, web.req)
508 if basectx is None:
509 if basectx is None:
509 basectx = ctx.p1()
510 basectx = ctx.p1()
510
511
511 style = web.config('web', 'style')
512 style = web.config('web', 'style')
512 if 'style' in web.req.qsparams:
513 if 'style' in web.req.qsparams:
513 style = web.req.qsparams['style']
514 style = web.req.qsparams['style']
514
515
515 diff = diffs(web, ctx, basectx, None, style)
516 diff = diffs(web, ctx, basectx, None, style)
516
517
517 parity = paritygen(web.stripecount)
518 parity = paritygen(web.stripecount)
518 diffstatsgen = diffstatgen(web.repo.ui, ctx, basectx)
519 diffstatsgen = diffstatgen(web.repo.ui, ctx, basectx)
519 diffstats = diffstat(ctx, diffstatsgen, parity)
520 diffstats = diffstat(ctx, diffstatsgen, parity)
520
521
521 return dict(
522 return dict(
522 diff=diff,
523 diff=diff,
523 symrev=symrevorshortnode(web.req, ctx),
524 symrev=symrevorshortnode(web.req, ctx),
524 basenode=basectx.hex(),
525 basenode=basectx.hex(),
525 changesettag=showtags,
526 changesettag=showtags,
526 changesetbookmark=showbookmarks,
527 changesetbookmark=showbookmarks,
527 changesetbranch=showbranch,
528 changesetbranch=showbranch,
528 files=templateutil.mappedgenerator(_listfilesgen,
529 files=templateutil.mappedgenerator(_listfilesgen,
529 args=(ctx, web.stripecount)),
530 args=(ctx, web.stripecount)),
530 diffsummary=_kwfunc(lambda context, mapping: diffsummary(diffstatsgen)),
531 diffsummary=_kwfunc(lambda context, mapping: diffsummary(diffstatsgen)),
531 diffstat=diffstats,
532 diffstat=diffstats,
532 archives=web.archivelist(ctx.hex()),
533 archives=web.archivelist(ctx.hex()),
533 **pycompat.strkwargs(commonentry(web.repo, ctx)))
534 **pycompat.strkwargs(commonentry(web.repo, ctx)))
534
535
535 def _listfilediffsgen(context, files, node, max):
536 def _listfilediffsgen(context, files, node, max):
536 for f in files[:max]:
537 for f in files[:max]:
537 yield context.process('filedifflink', {'node': hex(node), 'file': f})
538 yield context.process('filedifflink', {'node': hex(node), 'file': f})
538 if len(files) > max:
539 if len(files) > max:
539 yield context.process('fileellipses', {})
540 yield context.process('fileellipses', {})
540
541
541 def listfilediffs(files, node, max):
542 def listfilediffs(files, node, max):
542 return templateutil.mappedgenerator(_listfilediffsgen,
543 return templateutil.mappedgenerator(_listfilediffsgen,
543 args=(files, node, max))
544 args=(files, node, max))
544
545
545 def _prettyprintdifflines(context, lines, blockno, lineidprefix):
546 def _prettyprintdifflines(context, lines, blockno, lineidprefix):
546 for lineno, l in enumerate(lines, 1):
547 for lineno, l in enumerate(lines, 1):
547 difflineno = "%d.%d" % (blockno, lineno)
548 difflineno = "%d.%d" % (blockno, lineno)
548 if l.startswith('+'):
549 if l.startswith('+'):
549 ltype = "difflineplus"
550 ltype = "difflineplus"
550 elif l.startswith('-'):
551 elif l.startswith('-'):
551 ltype = "difflineminus"
552 ltype = "difflineminus"
552 elif l.startswith('@'):
553 elif l.startswith('@'):
553 ltype = "difflineat"
554 ltype = "difflineat"
554 else:
555 else:
555 ltype = "diffline"
556 ltype = "diffline"
556 yield context.process(ltype, {
557 yield context.process(ltype, {
557 'line': l,
558 'line': l,
558 'lineno': lineno,
559 'lineno': lineno,
559 'lineid': lineidprefix + "l%s" % difflineno,
560 'lineid': lineidprefix + "l%s" % difflineno,
560 'linenumber': "% 8s" % difflineno,
561 'linenumber': "% 8s" % difflineno,
561 })
562 })
562
563
563 def _diffsgen(context, repo, ctx, basectx, files, style, stripecount,
564 def _diffsgen(context, repo, ctx, basectx, files, style, stripecount,
564 linerange, lineidprefix):
565 linerange, lineidprefix):
565 if files:
566 if files:
566 m = match.exact(repo.root, repo.getcwd(), files)
567 m = match.exact(repo.root, repo.getcwd(), files)
567 else:
568 else:
568 m = match.always(repo.root, repo.getcwd())
569 m = match.always(repo.root, repo.getcwd())
569
570
570 diffopts = patch.diffopts(repo.ui, untrusted=True)
571 diffopts = patch.diffopts(repo.ui, untrusted=True)
571 node1 = basectx.node()
572 node1 = basectx.node()
572 node2 = ctx.node()
573 node2 = ctx.node()
573 parity = paritygen(stripecount)
574 parity = paritygen(stripecount)
574
575
575 diffhunks = patch.diffhunks(repo, node1, node2, m, opts=diffopts)
576 diffhunks = patch.diffhunks(repo, node1, node2, m, opts=diffopts)
576 for blockno, (fctx1, fctx2, header, hunks) in enumerate(diffhunks, 1):
577 for blockno, (fctx1, fctx2, header, hunks) in enumerate(diffhunks, 1):
577 if style != 'raw':
578 if style != 'raw':
578 header = header[1:]
579 header = header[1:]
579 lines = [h + '\n' for h in header]
580 lines = [h + '\n' for h in header]
580 for hunkrange, hunklines in hunks:
581 for hunkrange, hunklines in hunks:
581 if linerange is not None and hunkrange is not None:
582 if linerange is not None and hunkrange is not None:
582 s1, l1, s2, l2 = hunkrange
583 s1, l1, s2, l2 = hunkrange
583 if not mdiff.hunkinrange((s2, l2), linerange):
584 if not mdiff.hunkinrange((s2, l2), linerange):
584 continue
585 continue
585 lines.extend(hunklines)
586 lines.extend(hunklines)
586 if lines:
587 if lines:
587 l = templateutil.mappedgenerator(_prettyprintdifflines,
588 l = templateutil.mappedgenerator(_prettyprintdifflines,
588 args=(lines, blockno,
589 args=(lines, blockno,
589 lineidprefix))
590 lineidprefix))
590 yield {
591 yield {
591 'parity': next(parity),
592 'parity': next(parity),
592 'blockno': blockno,
593 'blockno': blockno,
593 'lines': l,
594 'lines': l,
594 }
595 }
595
596
596 def diffs(web, ctx, basectx, files, style, linerange=None, lineidprefix=''):
597 def diffs(web, ctx, basectx, files, style, linerange=None, lineidprefix=''):
597 args = (web.repo, ctx, basectx, files, style, web.stripecount,
598 args = (web.repo, ctx, basectx, files, style, web.stripecount,
598 linerange, lineidprefix)
599 linerange, lineidprefix)
599 return templateutil.mappinggenerator(_diffsgen, args=args, name='diffblock')
600 return templateutil.mappinggenerator(_diffsgen, args=args, name='diffblock')
600
601
601 def _compline(type, leftlineno, leftline, rightlineno, rightline):
602 def _compline(type, leftlineno, leftline, rightlineno, rightline):
602 lineid = leftlineno and ("l%d" % leftlineno) or ''
603 lineid = leftlineno and ("l%d" % leftlineno) or ''
603 lineid += rightlineno and ("r%d" % rightlineno) or ''
604 lineid += rightlineno and ("r%d" % rightlineno) or ''
604 llno = '%d' % leftlineno if leftlineno else ''
605 llno = '%d' % leftlineno if leftlineno else ''
605 rlno = '%d' % rightlineno if rightlineno else ''
606 rlno = '%d' % rightlineno if rightlineno else ''
606 return {
607 return {
607 'type': type,
608 'type': type,
608 'lineid': lineid,
609 'lineid': lineid,
609 'leftlineno': leftlineno,
610 'leftlineno': leftlineno,
610 'leftlinenumber': "% 6s" % llno,
611 'leftlinenumber': "% 6s" % llno,
611 'leftline': leftline or '',
612 'leftline': leftline or '',
612 'rightlineno': rightlineno,
613 'rightlineno': rightlineno,
613 'rightlinenumber': "% 6s" % rlno,
614 'rightlinenumber': "% 6s" % rlno,
614 'rightline': rightline or '',
615 'rightline': rightline or '',
615 }
616 }
616
617
617 def _getcompblockgen(context, leftlines, rightlines, opcodes):
618 def _getcompblockgen(context, leftlines, rightlines, opcodes):
618 for type, llo, lhi, rlo, rhi in opcodes:
619 for type, llo, lhi, rlo, rhi in opcodes:
619 len1 = lhi - llo
620 len1 = lhi - llo
620 len2 = rhi - rlo
621 len2 = rhi - rlo
621 count = min(len1, len2)
622 count = min(len1, len2)
622 for i in pycompat.xrange(count):
623 for i in pycompat.xrange(count):
623 yield _compline(type=type,
624 yield _compline(type=type,
624 leftlineno=llo + i + 1,
625 leftlineno=llo + i + 1,
625 leftline=leftlines[llo + i],
626 leftline=leftlines[llo + i],
626 rightlineno=rlo + i + 1,
627 rightlineno=rlo + i + 1,
627 rightline=rightlines[rlo + i])
628 rightline=rightlines[rlo + i])
628 if len1 > len2:
629 if len1 > len2:
629 for i in pycompat.xrange(llo + count, lhi):
630 for i in pycompat.xrange(llo + count, lhi):
630 yield _compline(type=type,
631 yield _compline(type=type,
631 leftlineno=i + 1,
632 leftlineno=i + 1,
632 leftline=leftlines[i],
633 leftline=leftlines[i],
633 rightlineno=None,
634 rightlineno=None,
634 rightline=None)
635 rightline=None)
635 elif len2 > len1:
636 elif len2 > len1:
636 for i in pycompat.xrange(rlo + count, rhi):
637 for i in pycompat.xrange(rlo + count, rhi):
637 yield _compline(type=type,
638 yield _compline(type=type,
638 leftlineno=None,
639 leftlineno=None,
639 leftline=None,
640 leftline=None,
640 rightlineno=i + 1,
641 rightlineno=i + 1,
641 rightline=rightlines[i])
642 rightline=rightlines[i])
642
643
643 def _getcompblock(leftlines, rightlines, opcodes):
644 def _getcompblock(leftlines, rightlines, opcodes):
644 args = (leftlines, rightlines, opcodes)
645 args = (leftlines, rightlines, opcodes)
645 return templateutil.mappinggenerator(_getcompblockgen, args=args,
646 return templateutil.mappinggenerator(_getcompblockgen, args=args,
646 name='comparisonline')
647 name='comparisonline')
647
648
648 def _comparegen(context, contextnum, leftlines, rightlines):
649 def _comparegen(context, contextnum, leftlines, rightlines):
649 '''Generator function that provides side-by-side comparison data.'''
650 '''Generator function that provides side-by-side comparison data.'''
650 s = difflib.SequenceMatcher(None, leftlines, rightlines)
651 s = difflib.SequenceMatcher(None, leftlines, rightlines)
651 if contextnum < 0:
652 if contextnum < 0:
652 l = _getcompblock(leftlines, rightlines, s.get_opcodes())
653 l = _getcompblock(leftlines, rightlines, s.get_opcodes())
653 yield {'lines': l}
654 yield {'lines': l}
654 else:
655 else:
655 for oc in s.get_grouped_opcodes(n=contextnum):
656 for oc in s.get_grouped_opcodes(n=contextnum):
656 l = _getcompblock(leftlines, rightlines, oc)
657 l = _getcompblock(leftlines, rightlines, oc)
657 yield {'lines': l}
658 yield {'lines': l}
658
659
659 def compare(contextnum, leftlines, rightlines):
660 def compare(contextnum, leftlines, rightlines):
660 args = (contextnum, leftlines, rightlines)
661 args = (contextnum, leftlines, rightlines)
661 return templateutil.mappinggenerator(_comparegen, args=args,
662 return templateutil.mappinggenerator(_comparegen, args=args,
662 name='comparisonblock')
663 name='comparisonblock')
663
664
664 def diffstatgen(ui, ctx, basectx):
665 def diffstatgen(ui, ctx, basectx):
665 '''Generator function that provides the diffstat data.'''
666 '''Generator function that provides the diffstat data.'''
666
667
667 diffopts = patch.diffopts(ui, {'noprefix': False})
668 diffopts = patch.diffopts(ui, {'noprefix': False})
668 stats = patch.diffstatdata(
669 stats = patch.diffstatdata(
669 util.iterlines(ctx.diff(basectx, opts=diffopts)))
670 util.iterlines(ctx.diff(basectx, opts=diffopts)))
670 maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats)
671 maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats)
671 while True:
672 while True:
672 yield stats, maxname, maxtotal, addtotal, removetotal, binary
673 yield stats, maxname, maxtotal, addtotal, removetotal, binary
673
674
674 def diffsummary(statgen):
675 def diffsummary(statgen):
675 '''Return a short summary of the diff.'''
676 '''Return a short summary of the diff.'''
676
677
677 stats, maxname, maxtotal, addtotal, removetotal, binary = next(statgen)
678 stats, maxname, maxtotal, addtotal, removetotal, binary = next(statgen)
678 return _(' %d files changed, %d insertions(+), %d deletions(-)\n') % (
679 return _(' %d files changed, %d insertions(+), %d deletions(-)\n') % (
679 len(stats), addtotal, removetotal)
680 len(stats), addtotal, removetotal)
680
681
681 def _diffstattmplgen(context, ctx, statgen, parity):
682 def _diffstattmplgen(context, ctx, statgen, parity):
682 stats, maxname, maxtotal, addtotal, removetotal, binary = next(statgen)
683 stats, maxname, maxtotal, addtotal, removetotal, binary = next(statgen)
683 files = ctx.files()
684 files = ctx.files()
684
685
685 def pct(i):
686 def pct(i):
686 if maxtotal == 0:
687 if maxtotal == 0:
687 return 0
688 return 0
688 return (float(i) / maxtotal) * 100
689 return (float(i) / maxtotal) * 100
689
690
690 fileno = 0
691 fileno = 0
691 for filename, adds, removes, isbinary in stats:
692 for filename, adds, removes, isbinary in stats:
692 template = 'diffstatlink' if filename in files else 'diffstatnolink'
693 template = 'diffstatlink' if filename in files else 'diffstatnolink'
693 total = adds + removes
694 total = adds + removes
694 fileno += 1
695 fileno += 1
695 yield context.process(template, {
696 yield context.process(template, {
696 'node': ctx.hex(),
697 'node': ctx.hex(),
697 'file': filename,
698 'file': filename,
698 'fileno': fileno,
699 'fileno': fileno,
699 'total': total,
700 'total': total,
700 'addpct': pct(adds),
701 'addpct': pct(adds),
701 'removepct': pct(removes),
702 'removepct': pct(removes),
702 'parity': next(parity),
703 'parity': next(parity),
703 })
704 })
704
705
705 def diffstat(ctx, statgen, parity):
706 def diffstat(ctx, statgen, parity):
706 '''Return a diffstat template for each file in the diff.'''
707 '''Return a diffstat template for each file in the diff.'''
707 args = (ctx, statgen, parity)
708 args = (ctx, statgen, parity)
708 return templateutil.mappedgenerator(_diffstattmplgen, args=args)
709 return templateutil.mappedgenerator(_diffstattmplgen, args=args)
709
710
710 class sessionvars(templateutil.wrapped):
711 class sessionvars(templateutil.wrapped):
711 def __init__(self, vars, start='?'):
712 def __init__(self, vars, start='?'):
712 self._start = start
713 self._start = start
713 self._vars = vars
714 self._vars = vars
714
715
715 def __getitem__(self, key):
716 def __getitem__(self, key):
716 return self._vars[key]
717 return self._vars[key]
717
718
718 def __setitem__(self, key, value):
719 def __setitem__(self, key, value):
719 self._vars[key] = value
720 self._vars[key] = value
720
721
721 def __copy__(self):
722 def __copy__(self):
722 return sessionvars(copy.copy(self._vars), self._start)
723 return sessionvars(copy.copy(self._vars), self._start)
723
724
724 def contains(self, context, mapping, item):
725 def contains(self, context, mapping, item):
725 item = templateutil.unwrapvalue(context, mapping, item)
726 item = templateutil.unwrapvalue(context, mapping, item)
726 return item in self._vars
727 return item in self._vars
727
728
728 def getmember(self, context, mapping, key):
729 def getmember(self, context, mapping, key):
729 key = templateutil.unwrapvalue(context, mapping, key)
730 key = templateutil.unwrapvalue(context, mapping, key)
730 return self._vars.get(key)
731 return self._vars.get(key)
731
732
732 def getmin(self, context, mapping):
733 def getmin(self, context, mapping):
733 raise error.ParseError(_('not comparable'))
734 raise error.ParseError(_('not comparable'))
734
735
735 def getmax(self, context, mapping):
736 def getmax(self, context, mapping):
736 raise error.ParseError(_('not comparable'))
737 raise error.ParseError(_('not comparable'))
737
738
738 def filter(self, context, mapping, select):
739 def filter(self, context, mapping, select):
739 # implement if necessary
740 # implement if necessary
740 raise error.ParseError(_('not filterable'))
741 raise error.ParseError(_('not filterable'))
741
742
742 def itermaps(self, context):
743 def itermaps(self, context):
743 separator = self._start
744 separator = self._start
744 for key, value in sorted(self._vars.iteritems()):
745 for key, value in sorted(self._vars.iteritems()):
745 yield {'name': key,
746 yield {'name': key,
746 'value': pycompat.bytestr(value),
747 'value': pycompat.bytestr(value),
747 'separator': separator,
748 'separator': separator,
748 }
749 }
749 separator = '&'
750 separator = '&'
750
751
751 def join(self, context, mapping, sep):
752 def join(self, context, mapping, sep):
752 # could be '{separator}{name}={value|urlescape}'
753 # could be '{separator}{name}={value|urlescape}'
753 raise error.ParseError(_('not displayable without template'))
754 raise error.ParseError(_('not displayable without template'))
754
755
755 def show(self, context, mapping):
756 def show(self, context, mapping):
756 return self.join(context, '')
757 return self.join(context, '')
757
758
758 def tobool(self, context, mapping):
759 def tobool(self, context, mapping):
759 return bool(self._vars)
760 return bool(self._vars)
760
761
761 def tovalue(self, context, mapping):
762 def tovalue(self, context, mapping):
762 return self._vars
763 return self._vars
763
764
764 class wsgiui(uimod.ui):
765 class wsgiui(uimod.ui):
765 # default termwidth breaks under mod_wsgi
766 # default termwidth breaks under mod_wsgi
766 def termwidth(self):
767 def termwidth(self):
767 return 80
768 return 80
768
769
769 def getwebsubs(repo):
770 def getwebsubs(repo):
770 websubtable = []
771 websubtable = []
771 websubdefs = repo.ui.configitems('websub')
772 websubdefs = repo.ui.configitems('websub')
772 # we must maintain interhg backwards compatibility
773 # we must maintain interhg backwards compatibility
773 websubdefs += repo.ui.configitems('interhg')
774 websubdefs += repo.ui.configitems('interhg')
774 for key, pattern in websubdefs:
775 for key, pattern in websubdefs:
775 # grab the delimiter from the character after the "s"
776 # grab the delimiter from the character after the "s"
776 unesc = pattern[1:2]
777 unesc = pattern[1:2]
777 delim = stringutil.reescape(unesc)
778 delim = stringutil.reescape(unesc)
778
779
779 # identify portions of the pattern, taking care to avoid escaped
780 # identify portions of the pattern, taking care to avoid escaped
780 # delimiters. the replace format and flags are optional, but
781 # delimiters. the replace format and flags are optional, but
781 # delimiters are required.
782 # delimiters are required.
782 match = re.match(
783 match = re.match(
783 br'^s%s(.+)(?:(?<=\\\\)|(?<!\\))%s(.*)%s([ilmsux])*$'
784 br'^s%s(.+)(?:(?<=\\\\)|(?<!\\))%s(.*)%s([ilmsux])*$'
784 % (delim, delim, delim), pattern)
785 % (delim, delim, delim), pattern)
785 if not match:
786 if not match:
786 repo.ui.warn(_("websub: invalid pattern for %s: %s\n")
787 repo.ui.warn(_("websub: invalid pattern for %s: %s\n")
787 % (key, pattern))
788 % (key, pattern))
788 continue
789 continue
789
790
790 # we need to unescape the delimiter for regexp and format
791 # we need to unescape the delimiter for regexp and format
791 delim_re = re.compile(br'(?<!\\)\\%s' % delim)
792 delim_re = re.compile(br'(?<!\\)\\%s' % delim)
792 regexp = delim_re.sub(unesc, match.group(1))
793 regexp = delim_re.sub(unesc, match.group(1))
793 format = delim_re.sub(unesc, match.group(2))
794 format = delim_re.sub(unesc, match.group(2))
794
795
795 # the pattern allows for 6 regexp flags, so set them if necessary
796 # the pattern allows for 6 regexp flags, so set them if necessary
796 flagin = match.group(3)
797 flagin = match.group(3)
797 flags = 0
798 flags = 0
798 if flagin:
799 if flagin:
799 for flag in flagin.upper():
800 for flag in flagin.upper():
800 flags |= re.__dict__[flag]
801 flags |= re.__dict__[flag]
801
802
802 try:
803 try:
803 regexp = re.compile(regexp, flags)
804 regexp = re.compile(regexp, flags)
804 websubtable.append((regexp, format))
805 websubtable.append((regexp, format))
805 except re.error:
806 except re.error:
806 repo.ui.warn(_("websub: invalid regexp for %s: %s\n")
807 repo.ui.warn(_("websub: invalid regexp for %s: %s\n")
807 % (key, regexp))
808 % (key, regexp))
808 return websubtable
809 return websubtable
809
810
810 def getgraphnode(repo, ctx):
811 def getgraphnode(repo, ctx):
811 return (templatekw.getgraphnodecurrent(repo, ctx) +
812 return (templatekw.getgraphnodecurrent(repo, ctx) +
812 templatekw.getgraphnodesymbol(ctx))
813 templatekw.getgraphnodesymbol(ctx))
@@ -1,1791 +1,1792 b''
1 #require serve
1 #require serve
2
2
3 hide outer repo and work in dir without '.hg'
3 hide outer repo and work in dir without '.hg'
4 $ hg init
4 $ hg init
5 $ mkdir dir
5 $ mkdir dir
6 $ cd dir
6 $ cd dir
7
7
8 Tests some basic hgwebdir functionality. Tests setting up paths and
8 Tests some basic hgwebdir functionality. Tests setting up paths and
9 collection, different forms of 404s and the subdirectory support.
9 collection, different forms of 404s and the subdirectory support.
10
10
11 $ mkdir webdir
11 $ mkdir webdir
12 $ cd webdir
12 $ cd webdir
13 $ hg init a
13 $ hg init a
14 $ echo a > a/a
14 $ echo a > a/a
15 $ hg --cwd a ci -Ama -d'1 0'
15 $ hg --cwd a ci -Ama -d'1 0'
16 adding a
16 adding a
17
17
18 create a mercurial queue repository
18 create a mercurial queue repository
19
19
20 $ hg --cwd a qinit --config extensions.hgext.mq= -c
20 $ hg --cwd a qinit --config extensions.hgext.mq= -c
21 $ hg init b
21 $ hg init b
22 $ echo b > b/b
22 $ echo b > b/b
23 $ hg --cwd b ci -Amb -d'2 0'
23 $ hg --cwd b ci -Amb -d'2 0'
24 adding b
24 adding b
25
25
26 create a nested repository
26 create a nested repository
27
27
28 $ cd b
28 $ cd b
29 $ hg init d
29 $ hg init d
30 $ echo d > d/d
30 $ echo d > d/d
31 $ hg --cwd d ci -Amd -d'3 0'
31 $ hg --cwd d ci -Amd -d'3 0'
32 adding d
32 adding d
33 $ cd ..
33 $ cd ..
34 $ hg init c
34 $ hg init c
35 $ echo c > c/c
35 $ echo c > c/c
36 $ hg --cwd c ci -Amc -d'3 0'
36 $ hg --cwd c ci -Amc -d'3 0'
37 adding c
37 adding c
38
38
39 create a subdirectory containing repositories and subrepositories
39 create a subdirectory containing repositories and subrepositories
40
40
41 $ mkdir notrepo
41 $ mkdir notrepo
42 $ cd notrepo
42 $ cd notrepo
43 $ hg init e
43 $ hg init e
44 $ echo e > e/e
44 $ echo e > e/e
45 $ hg --cwd e ci -Ame -d'4 0'
45 $ hg --cwd e ci -Ame -d'4 0'
46 adding e
46 adding e
47 $ hg init e/e2
47 $ hg init e/e2
48 $ echo e2 > e/e2/e2
48 $ echo e2 > e/e2/e2
49 $ hg --cwd e/e2 ci -Ame2 -d '4 0'
49 $ hg --cwd e/e2 ci -Ame2 -d '4 0'
50 adding e2
50 adding e2
51 $ hg init f
51 $ hg init f
52 $ echo f > f/f
52 $ echo f > f/f
53 $ hg --cwd f ci -Amf -d'4 0'
53 $ hg --cwd f ci -Amf -d'4 0'
54 adding f
54 adding f
55 $ hg init f/f2
55 $ hg init f/f2
56 $ echo f2 > f/f2/f2
56 $ echo f2 > f/f2/f2
57 $ hg --cwd f/f2 ci -Amf2 -d '4 0'
57 $ hg --cwd f/f2 ci -Amf2 -d '4 0'
58 adding f2
58 adding f2
59 $ echo 'f2 = f2' > f/.hgsub
59 $ echo 'f2 = f2' > f/.hgsub
60 $ hg -R f ci -Am 'add subrepo' -d'4 0'
60 $ hg -R f ci -Am 'add subrepo' -d'4 0'
61 adding .hgsub
61 adding .hgsub
62 $ cat >> f/.hg/hgrc << EOF
62 $ cat >> f/.hg/hgrc << EOF
63 > [web]
63 > [web]
64 > name = fancy name for repo f
64 > name = fancy name for repo f
65 > labels = foo, bar
65 > labels = foo, bar
66 > EOF
66 > EOF
67 $ cd ..
67 $ cd ..
68
68
69 add file under the directory which could be shadowed by another repository
69 add file under the directory which could be shadowed by another repository
70
70
71 $ mkdir notrepo/f/f3
71 $ mkdir notrepo/f/f3
72 $ echo f3/file > notrepo/f/f3/file
72 $ echo f3/file > notrepo/f/f3/file
73 $ hg -R notrepo/f ci -Am 'f3/file'
73 $ hg -R notrepo/f ci -Am 'f3/file'
74 adding f3/file
74 adding f3/file
75 $ hg -R notrepo/f update null
75 $ hg -R notrepo/f update null
76 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
76 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
77 $ hg init notrepo/f/f3
77 $ hg init notrepo/f/f3
78 $ cat <<'EOF' > notrepo/f/f3/.hg/hgrc
78 $ cat <<'EOF' > notrepo/f/f3/.hg/hgrc
79 > [web]
79 > [web]
80 > hidden = true
80 > hidden = true
81 > EOF
81 > EOF
82
82
83 create repository without .hg/store
83 create repository without .hg/store
84
84
85 $ hg init nostore
85 $ hg init nostore
86 $ rm -R nostore/.hg/store
86 $ rm -R nostore/.hg/store
87 $ root=`pwd`
87 $ root=`pwd`
88 $ cd ..
88 $ cd ..
89
89
90 serve
90 serve
91 $ cat > paths.conf <<EOF
91 $ cat > paths.conf <<EOF
92 > [paths]
92 > [paths]
93 > a=$root/a
93 > a=$root/a
94 > b=$root/b
94 > b=$root/b
95 > EOF
95 > EOF
96 $ hg serve -p $HGPORT -d --pid-file=hg.pid --webdir-conf paths.conf \
96 $ hg serve -p $HGPORT -d --pid-file=hg.pid --webdir-conf paths.conf \
97 > -A access-paths.log -E error-paths-1.log
97 > -A access-paths.log -E error-paths-1.log
98 $ cat hg.pid >> $DAEMON_PIDS
98 $ cat hg.pid >> $DAEMON_PIDS
99
99
100 should give a 404 - file does not exist
100 should give a 404 - file does not exist
101
101
102 $ get-with-headers.py localhost:$HGPORT 'a/file/tip/bork?style=raw'
102 $ get-with-headers.py localhost:$HGPORT 'a/file/tip/bork?style=raw'
103 404 Not Found
103 404 Not Found
104
104
105
105
106 error: bork@8580ff50825a: not found in manifest
106 error: bork@8580ff50825a: not found in manifest
107 [1]
107 [1]
108
108
109 should succeed
109 should succeed
110
110
111 $ get-with-headers.py localhost:$HGPORT '?style=raw'
111 $ get-with-headers.py localhost:$HGPORT '?style=raw'
112 200 Script output follows
112 200 Script output follows
113
113
114
114
115 /a/
115 /a/
116 /b/
116 /b/
117
117
118 $ get-with-headers.py localhost:$HGPORT '?style=json'
118 $ get-with-headers.py localhost:$HGPORT '?style=json'
119 200 Script output follows
119 200 Script output follows
120
120
121 {
121 {
122 "entries": [{
122 "entries": [{
123 "name": "a",
123 "name": "a",
124 "description": "unknown",
124 "description": "unknown",
125 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
125 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
126 "lastchange": [*, *], (glob)
126 "lastchange": [*, *], (glob)
127 "labels": []
127 "labels": []
128 }, {
128 }, {
129 "name": "b",
129 "name": "b",
130 "description": "unknown",
130 "description": "unknown",
131 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
131 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
132 "lastchange": [*, *], (glob)
132 "lastchange": [*, *], (glob)
133 "labels": []
133 "labels": []
134 }]
134 }]
135 } (no-eol)
135 } (no-eol)
136
136
137 $ get-with-headers.py localhost:$HGPORT 'a/file/tip/a?style=raw'
137 $ get-with-headers.py localhost:$HGPORT 'a/file/tip/a?style=raw'
138 200 Script output follows
138 200 Script output follows
139
139
140 a
140 a
141 $ get-with-headers.py localhost:$HGPORT 'b/file/tip/b?style=raw'
141 $ get-with-headers.py localhost:$HGPORT 'b/file/tip/b?style=raw'
142 200 Script output follows
142 200 Script output follows
143
143
144 b
144 b
145
145
146 should give a 404 - repo is not published
146 should give a 404 - repo is not published
147
147
148 $ get-with-headers.py localhost:$HGPORT 'c/file/tip/c?style=raw'
148 $ get-with-headers.py localhost:$HGPORT 'c/file/tip/c?style=raw'
149 404 Not Found
149 404 Not Found
150
150
151
151
152 error: repository c/file/tip/c not found
152 error: repository c/file/tip/c not found
153 [1]
153 [1]
154
154
155 atom-log without basedir
155 atom-log without basedir
156
156
157 $ get-with-headers.py localhost:$HGPORT 'a/atom-log' | grep '<link'
157 $ get-with-headers.py localhost:$HGPORT 'a/atom-log' | grep '<link'
158 <link rel="self" href="http://*:$HGPORT/a/atom-log"/> (glob)
158 <link rel="self" href="http://*:$HGPORT/a/atom-log"/> (glob)
159 <link rel="alternate" href="http://*:$HGPORT/a/"/> (glob)
159 <link rel="alternate" href="http://*:$HGPORT/a/"/> (glob)
160 <link href="http://*:$HGPORT/a/rev/8580ff50825a"/> (glob)
160 <link href="http://*:$HGPORT/a/rev/8580ff50825a"/> (glob)
161
161
162 rss-log without basedir
162 rss-log without basedir
163
163
164 $ get-with-headers.py localhost:$HGPORT 'a/rss-log' | grep '<guid'
164 $ get-with-headers.py localhost:$HGPORT 'a/rss-log' | grep '<guid'
165 <guid isPermaLink="true">http://*:$HGPORT/a/rev/8580ff50825a</guid> (glob)
165 <guid isPermaLink="true">http://*:$HGPORT/a/rev/8580ff50825a</guid> (glob)
166 $ cat > paths.conf <<EOF
166 $ cat > paths.conf <<EOF
167 > [paths]
167 > [paths]
168 > t/a/=$root/a
168 > t/a/=$root/a
169 > b=$root/b
169 > b=$root/b
170 > coll=$root/*
170 > coll=$root/*
171 > rcoll=$root/**
171 > rcoll=$root/**
172 > star=*
172 > star=*
173 > starstar=**
173 > starstar=**
174 > astar=webdir/a/*
174 > astar=webdir/a/*
175 > EOF
175 > EOF
176 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
176 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
177 > -A access-paths.log -E error-paths-2.log
177 > -A access-paths.log -E error-paths-2.log
178 $ cat hg.pid >> $DAEMON_PIDS
178 $ cat hg.pid >> $DAEMON_PIDS
179
179
180 should succeed, slashy names
180 should succeed, slashy names
181
181
182 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
182 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
183 200 Script output follows
183 200 Script output follows
184
184
185
185
186 /t/a/
186 /t/a/
187 /b/
187 /b/
188 /coll/a/
188 /coll/a/
189 /coll/a/.hg/patches/
189 /coll/a/.hg/patches/
190 /coll/b/
190 /coll/b/
191 /coll/c/
191 /coll/c/
192 /coll/notrepo/e/
192 /coll/notrepo/e/
193 /coll/notrepo/f/
193 /coll/notrepo/f/
194 /rcoll/a/
194 /rcoll/a/
195 /rcoll/a/.hg/patches/
195 /rcoll/a/.hg/patches/
196 /rcoll/b/
196 /rcoll/b/
197 /rcoll/b/d/
197 /rcoll/b/d/
198 /rcoll/c/
198 /rcoll/c/
199 /rcoll/notrepo/e/
199 /rcoll/notrepo/e/
200 /rcoll/notrepo/e/e2/
200 /rcoll/notrepo/e/e2/
201 /rcoll/notrepo/f/
201 /rcoll/notrepo/f/
202 /rcoll/notrepo/f/f2/
202 /rcoll/notrepo/f/f2/
203 /star/webdir/a/
203 /star/webdir/a/
204 /star/webdir/a/.hg/patches/
204 /star/webdir/a/.hg/patches/
205 /star/webdir/b/
205 /star/webdir/b/
206 /star/webdir/c/
206 /star/webdir/c/
207 /star/webdir/notrepo/e/
207 /star/webdir/notrepo/e/
208 /star/webdir/notrepo/f/
208 /star/webdir/notrepo/f/
209 /starstar/webdir/a/
209 /starstar/webdir/a/
210 /starstar/webdir/a/.hg/patches/
210 /starstar/webdir/a/.hg/patches/
211 /starstar/webdir/b/
211 /starstar/webdir/b/
212 /starstar/webdir/b/d/
212 /starstar/webdir/b/d/
213 /starstar/webdir/c/
213 /starstar/webdir/c/
214 /starstar/webdir/notrepo/e/
214 /starstar/webdir/notrepo/e/
215 /starstar/webdir/notrepo/e/e2/
215 /starstar/webdir/notrepo/e/e2/
216 /starstar/webdir/notrepo/f/
216 /starstar/webdir/notrepo/f/
217 /starstar/webdir/notrepo/f/f2/
217 /starstar/webdir/notrepo/f/f2/
218 /astar/
218 /astar/
219 /astar/.hg/patches/
219 /astar/.hg/patches/
220
220
221
221
222 $ get-with-headers.py localhost:$HGPORT1 '?style=json'
222 $ get-with-headers.py localhost:$HGPORT1 '?style=json'
223 200 Script output follows
223 200 Script output follows
224
224
225 {
225 {
226 "entries": [{
226 "entries": [{
227 "name": "t/a",
227 "name": "t/a",
228 "description": "unknown",
228 "description": "unknown",
229 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
229 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
230 "lastchange": [*, *], (glob)
230 "lastchange": [*, *], (glob)
231 "labels": []
231 "labels": []
232 }, {
232 }, {
233 "name": "b",
233 "name": "b",
234 "description": "unknown",
234 "description": "unknown",
235 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
235 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
236 "lastchange": [*, *], (glob)
236 "lastchange": [*, *], (glob)
237 "labels": []
237 "labels": []
238 }, {
238 }, {
239 "name": "coll/a",
239 "name": "coll/a",
240 "description": "unknown",
240 "description": "unknown",
241 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
241 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
242 "lastchange": [*, *], (glob)
242 "lastchange": [*, *], (glob)
243 "labels": []
243 "labels": []
244 }, {
244 }, {
245 "name": "coll/a/.hg/patches",
245 "name": "coll/a/.hg/patches",
246 "description": "unknown",
246 "description": "unknown",
247 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
247 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
248 "lastchange": [*, *], (glob)
248 "lastchange": [*, *], (glob)
249 "labels": []
249 "labels": []
250 }, {
250 }, {
251 "name": "coll/b",
251 "name": "coll/b",
252 "description": "unknown",
252 "description": "unknown",
253 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
253 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
254 "lastchange": [*, *], (glob)
254 "lastchange": [*, *], (glob)
255 "labels": []
255 "labels": []
256 }, {
256 }, {
257 "name": "coll/c",
257 "name": "coll/c",
258 "description": "unknown",
258 "description": "unknown",
259 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
259 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
260 "lastchange": [*, *], (glob)
260 "lastchange": [*, *], (glob)
261 "labels": []
261 "labels": []
262 }, {
262 }, {
263 "name": "coll/notrepo/e",
263 "name": "coll/notrepo/e",
264 "description": "unknown",
264 "description": "unknown",
265 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
265 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
266 "lastchange": [*, *], (glob)
266 "lastchange": [*, *], (glob)
267 "labels": []
267 "labels": []
268 }, {
268 }, {
269 "name": "fancy name for repo f",
269 "name": "fancy name for repo f",
270 "description": "unknown",
270 "description": "unknown",
271 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
271 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
272 "lastchange": [*, *], (glob)
272 "lastchange": [*, *], (glob)
273 "labels": ["foo", "bar"]
273 "labels": ["foo", "bar"]
274 }, {
274 }, {
275 "name": "rcoll/a",
275 "name": "rcoll/a",
276 "description": "unknown",
276 "description": "unknown",
277 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
277 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
278 "lastchange": [*, *], (glob)
278 "lastchange": [*, *], (glob)
279 "labels": []
279 "labels": []
280 }, {
280 }, {
281 "name": "rcoll/a/.hg/patches",
281 "name": "rcoll/a/.hg/patches",
282 "description": "unknown",
282 "description": "unknown",
283 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
283 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
284 "lastchange": [*, *], (glob)
284 "lastchange": [*, *], (glob)
285 "labels": []
285 "labels": []
286 }, {
286 }, {
287 "name": "rcoll/b",
287 "name": "rcoll/b",
288 "description": "unknown",
288 "description": "unknown",
289 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
289 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
290 "lastchange": [*, *], (glob)
290 "lastchange": [*, *], (glob)
291 "labels": []
291 "labels": []
292 }, {
292 }, {
293 "name": "rcoll/b/d",
293 "name": "rcoll/b/d",
294 "description": "unknown",
294 "description": "unknown",
295 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
295 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
296 "lastchange": [*, *], (glob)
296 "lastchange": [*, *], (glob)
297 "labels": []
297 "labels": []
298 }, {
298 }, {
299 "name": "rcoll/c",
299 "name": "rcoll/c",
300 "description": "unknown",
300 "description": "unknown",
301 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
301 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
302 "lastchange": [*, *], (glob)
302 "lastchange": [*, *], (glob)
303 "labels": []
303 "labels": []
304 }, {
304 }, {
305 "name": "rcoll/notrepo/e",
305 "name": "rcoll/notrepo/e",
306 "description": "unknown",
306 "description": "unknown",
307 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
307 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
308 "lastchange": [*, *], (glob)
308 "lastchange": [*, *], (glob)
309 "labels": []
309 "labels": []
310 }, {
310 }, {
311 "name": "rcoll/notrepo/e/e2",
311 "name": "rcoll/notrepo/e/e2",
312 "description": "unknown",
312 "description": "unknown",
313 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
313 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
314 "lastchange": [*, *], (glob)
314 "lastchange": [*, *], (glob)
315 "labels": []
315 "labels": []
316 }, {
316 }, {
317 "name": "fancy name for repo f",
317 "name": "fancy name for repo f",
318 "description": "unknown",
318 "description": "unknown",
319 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
319 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
320 "lastchange": [*, *], (glob)
320 "lastchange": [*, *], (glob)
321 "labels": ["foo", "bar"]
321 "labels": ["foo", "bar"]
322 }, {
322 }, {
323 "name": "rcoll/notrepo/f/f2",
323 "name": "rcoll/notrepo/f/f2",
324 "description": "unknown",
324 "description": "unknown",
325 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
325 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
326 "lastchange": [*, *], (glob)
326 "lastchange": [*, *], (glob)
327 "labels": []
327 "labels": []
328 }, {
328 }, {
329 "name": "star/webdir/a",
329 "name": "star/webdir/a",
330 "description": "unknown",
330 "description": "unknown",
331 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
331 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
332 "lastchange": [*, *], (glob)
332 "lastchange": [*, *], (glob)
333 "labels": []
333 "labels": []
334 }, {
334 }, {
335 "name": "star/webdir/a/.hg/patches",
335 "name": "star/webdir/a/.hg/patches",
336 "description": "unknown",
336 "description": "unknown",
337 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
337 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
338 "lastchange": [*, *], (glob)
338 "lastchange": [*, *], (glob)
339 "labels": []
339 "labels": []
340 }, {
340 }, {
341 "name": "star/webdir/b",
341 "name": "star/webdir/b",
342 "description": "unknown",
342 "description": "unknown",
343 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
343 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
344 "lastchange": [*, *], (glob)
344 "lastchange": [*, *], (glob)
345 "labels": []
345 "labels": []
346 }, {
346 }, {
347 "name": "star/webdir/c",
347 "name": "star/webdir/c",
348 "description": "unknown",
348 "description": "unknown",
349 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
349 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
350 "lastchange": [*, *], (glob)
350 "lastchange": [*, *], (glob)
351 "labels": []
351 "labels": []
352 }, {
352 }, {
353 "name": "star/webdir/notrepo/e",
353 "name": "star/webdir/notrepo/e",
354 "description": "unknown",
354 "description": "unknown",
355 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
355 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
356 "lastchange": [*, *], (glob)
356 "lastchange": [*, *], (glob)
357 "labels": []
357 "labels": []
358 }, {
358 }, {
359 "name": "fancy name for repo f",
359 "name": "fancy name for repo f",
360 "description": "unknown",
360 "description": "unknown",
361 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
361 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
362 "lastchange": [*, *], (glob)
362 "lastchange": [*, *], (glob)
363 "labels": ["foo", "bar"]
363 "labels": ["foo", "bar"]
364 }, {
364 }, {
365 "name": "starstar/webdir/a",
365 "name": "starstar/webdir/a",
366 "description": "unknown",
366 "description": "unknown",
367 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
367 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
368 "lastchange": [*, *], (glob)
368 "lastchange": [*, *], (glob)
369 "labels": []
369 "labels": []
370 }, {
370 }, {
371 "name": "starstar/webdir/a/.hg/patches",
371 "name": "starstar/webdir/a/.hg/patches",
372 "description": "unknown",
372 "description": "unknown",
373 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
373 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
374 "lastchange": [*, *], (glob)
374 "lastchange": [*, *], (glob)
375 "labels": []
375 "labels": []
376 }, {
376 }, {
377 "name": "starstar/webdir/b",
377 "name": "starstar/webdir/b",
378 "description": "unknown",
378 "description": "unknown",
379 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
379 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
380 "lastchange": [*, *], (glob)
380 "lastchange": [*, *], (glob)
381 "labels": []
381 "labels": []
382 }, {
382 }, {
383 "name": "starstar/webdir/b/d",
383 "name": "starstar/webdir/b/d",
384 "description": "unknown",
384 "description": "unknown",
385 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
385 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
386 "lastchange": [*, *], (glob)
386 "lastchange": [*, *], (glob)
387 "labels": []
387 "labels": []
388 }, {
388 }, {
389 "name": "starstar/webdir/c",
389 "name": "starstar/webdir/c",
390 "description": "unknown",
390 "description": "unknown",
391 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
391 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
392 "lastchange": [*, *], (glob)
392 "lastchange": [*, *], (glob)
393 "labels": []
393 "labels": []
394 }, {
394 }, {
395 "name": "starstar/webdir/notrepo/e",
395 "name": "starstar/webdir/notrepo/e",
396 "description": "unknown",
396 "description": "unknown",
397 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
397 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
398 "lastchange": [*, *], (glob)
398 "lastchange": [*, *], (glob)
399 "labels": []
399 "labels": []
400 }, {
400 }, {
401 "name": "starstar/webdir/notrepo/e/e2",
401 "name": "starstar/webdir/notrepo/e/e2",
402 "description": "unknown",
402 "description": "unknown",
403 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
403 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
404 "lastchange": [*, *], (glob)
404 "lastchange": [*, *], (glob)
405 "labels": []
405 "labels": []
406 }, {
406 }, {
407 "name": "fancy name for repo f",
407 "name": "fancy name for repo f",
408 "description": "unknown",
408 "description": "unknown",
409 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
409 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
410 "lastchange": [*, *], (glob)
410 "lastchange": [*, *], (glob)
411 "labels": ["foo", "bar"]
411 "labels": ["foo", "bar"]
412 }, {
412 }, {
413 "name": "starstar/webdir/notrepo/f/f2",
413 "name": "starstar/webdir/notrepo/f/f2",
414 "description": "unknown",
414 "description": "unknown",
415 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
415 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
416 "lastchange": [*, *], (glob)
416 "lastchange": [*, *], (glob)
417 "labels": []
417 "labels": []
418 }, {
418 }, {
419 "name": "astar",
419 "name": "astar",
420 "description": "unknown",
420 "description": "unknown",
421 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
421 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
422 "lastchange": [*, *], (glob)
422 "lastchange": [*, *], (glob)
423 "labels": []
423 "labels": []
424 }, {
424 }, {
425 "name": "astar/.hg/patches",
425 "name": "astar/.hg/patches",
426 "description": "unknown",
426 "description": "unknown",
427 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
427 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
428 "lastchange": [*, *], (glob)
428 "lastchange": [*, *], (glob)
429 "labels": []
429 "labels": []
430 }]
430 }]
431 } (no-eol)
431 } (no-eol)
432
432
433 $ get-with-headers.py localhost:$HGPORT1 '?style=paper'
433 $ get-with-headers.py localhost:$HGPORT1 '?style=paper'
434 200 Script output follows
434 200 Script output follows
435
435
436 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
436 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
437 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
437 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
438 <head>
438 <head>
439 <link rel="icon" href="/static/hgicon.png" type="image/png" />
439 <link rel="icon" href="/static/hgicon.png" type="image/png" />
440 <meta name="robots" content="index, nofollow" />
440 <meta name="robots" content="index, nofollow" />
441 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
441 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
442 <script type="text/javascript" src="/static/mercurial.js"></script>
442 <script type="text/javascript" src="/static/mercurial.js"></script>
443
443
444 <title>Mercurial repositories index</title>
444 <title>Mercurial repositories index</title>
445 </head>
445 </head>
446 <body>
446 <body>
447
447
448 <div class="container">
448 <div class="container">
449 <div class="menu">
449 <div class="menu">
450 <a href="https://mercurial-scm.org/">
450 <a href="https://mercurial-scm.org/">
451 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
451 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
452 </div>
452 </div>
453 <div class="main">
453 <div class="main">
454 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
454 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
455
455
456 <table class="bigtable">
456 <table class="bigtable">
457 <thead>
457 <thead>
458 <tr>
458 <tr>
459 <th><a href="?sort=name">Name</a></th>
459 <th><a href="?sort=name">Name</a></th>
460 <th><a href="?sort=description">Description</a></th>
460 <th><a href="?sort=description">Description</a></th>
461 <th><a href="?sort=contact">Contact</a></th>
461 <th><a href="?sort=contact">Contact</a></th>
462 <th><a href="?sort=lastchange">Last modified</a></th>
462 <th><a href="?sort=lastchange">Last modified</a></th>
463 <th>&nbsp;</th>
463 <th>&nbsp;</th>
464 <th>&nbsp;</th>
464 <th>&nbsp;</th>
465 </tr>
465 </tr>
466 </thead>
466 </thead>
467 <tbody class="stripes2">
467 <tbody class="stripes2">
468
468
469 <tr>
469 <tr>
470 <td><a href="/t/a/?style=paper">t/a</a></td>
470 <td><a href="/t/a/?style=paper">t/a</a></td>
471 <td>unknown</td>
471 <td>unknown</td>
472 <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>
472 <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>
473 <td class="age">*</td> (glob)
473 <td class="age">*</td> (glob)
474 <td class="indexlinks"></td>
474 <td class="indexlinks"></td>
475 <td>
475 <td>
476 <a href="/t/a/atom-log" title="subscribe to repository atom feed">
476 <a href="/t/a/atom-log" title="subscribe to repository atom feed">
477 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
477 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
478 </a>
478 </a>
479 </td>
479 </td>
480 </tr>
480 </tr>
481
481
482 <tr>
482 <tr>
483 <td><a href="/b/?style=paper">b</a></td>
483 <td><a href="/b/?style=paper">b</a></td>
484 <td>unknown</td>
484 <td>unknown</td>
485 <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>
485 <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>
486 <td class="age">*</td> (glob)
486 <td class="age">*</td> (glob)
487 <td class="indexlinks"></td>
487 <td class="indexlinks"></td>
488 <td>
488 <td>
489 <a href="/b/atom-log" title="subscribe to repository atom feed">
489 <a href="/b/atom-log" title="subscribe to repository atom feed">
490 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
490 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
491 </a>
491 </a>
492 </td>
492 </td>
493 </tr>
493 </tr>
494
494
495 <tr>
495 <tr>
496 <td><a href="/coll/a/?style=paper">coll/a</a></td>
496 <td><a href="/coll/a/?style=paper">coll/a</a></td>
497 <td>unknown</td>
497 <td>unknown</td>
498 <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>
498 <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>
499 <td class="age">*</td> (glob)
499 <td class="age">*</td> (glob)
500 <td class="indexlinks"></td>
500 <td class="indexlinks"></td>
501 <td>
501 <td>
502 <a href="/coll/a/atom-log" title="subscribe to repository atom feed">
502 <a href="/coll/a/atom-log" title="subscribe to repository atom feed">
503 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
503 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
504 </a>
504 </a>
505 </td>
505 </td>
506 </tr>
506 </tr>
507
507
508 <tr>
508 <tr>
509 <td><a href="/coll/a/.hg/patches/?style=paper">coll/a/.hg/patches</a></td>
509 <td><a href="/coll/a/.hg/patches/?style=paper">coll/a/.hg/patches</a></td>
510 <td>unknown</td>
510 <td>unknown</td>
511 <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>
511 <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>
512 <td class="age">*</td> (glob)
512 <td class="age">*</td> (glob)
513 <td class="indexlinks"></td>
513 <td class="indexlinks"></td>
514 <td>
514 <td>
515 <a href="/coll/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
515 <a href="/coll/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
516 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
516 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
517 </a>
517 </a>
518 </td>
518 </td>
519 </tr>
519 </tr>
520
520
521 <tr>
521 <tr>
522 <td><a href="/coll/b/?style=paper">coll/b</a></td>
522 <td><a href="/coll/b/?style=paper">coll/b</a></td>
523 <td>unknown</td>
523 <td>unknown</td>
524 <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>
524 <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>
525 <td class="age">*</td> (glob)
525 <td class="age">*</td> (glob)
526 <td class="indexlinks"></td>
526 <td class="indexlinks"></td>
527 <td>
527 <td>
528 <a href="/coll/b/atom-log" title="subscribe to repository atom feed">
528 <a href="/coll/b/atom-log" title="subscribe to repository atom feed">
529 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
529 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
530 </a>
530 </a>
531 </td>
531 </td>
532 </tr>
532 </tr>
533
533
534 <tr>
534 <tr>
535 <td><a href="/coll/c/?style=paper">coll/c</a></td>
535 <td><a href="/coll/c/?style=paper">coll/c</a></td>
536 <td>unknown</td>
536 <td>unknown</td>
537 <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>
537 <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>
538 <td class="age">*</td> (glob)
538 <td class="age">*</td> (glob)
539 <td class="indexlinks"></td>
539 <td class="indexlinks"></td>
540 <td>
540 <td>
541 <a href="/coll/c/atom-log" title="subscribe to repository atom feed">
541 <a href="/coll/c/atom-log" title="subscribe to repository atom feed">
542 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
542 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
543 </a>
543 </a>
544 </td>
544 </td>
545 </tr>
545 </tr>
546
546
547 <tr>
547 <tr>
548 <td><a href="/coll/notrepo/e/?style=paper">coll/notrepo/e</a></td>
548 <td><a href="/coll/notrepo/e/?style=paper">coll/notrepo/e</a></td>
549 <td>unknown</td>
549 <td>unknown</td>
550 <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>
550 <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>
551 <td class="age">*</td> (glob)
551 <td class="age">*</td> (glob)
552 <td class="indexlinks"></td>
552 <td class="indexlinks"></td>
553 <td>
553 <td>
554 <a href="/coll/notrepo/e/atom-log" title="subscribe to repository atom feed">
554 <a href="/coll/notrepo/e/atom-log" title="subscribe to repository atom feed">
555 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
555 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
556 </a>
556 </a>
557 </td>
557 </td>
558 </tr>
558 </tr>
559
559
560 <tr>
560 <tr>
561 <td><a href="/coll/notrepo/f/?style=paper">fancy name for repo f</a></td>
561 <td><a href="/coll/notrepo/f/?style=paper">fancy name for repo f</a></td>
562 <td>unknown</td>
562 <td>unknown</td>
563 <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>
563 <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>
564 <td class="age">*</td> (glob)
564 <td class="age">*</td> (glob)
565 <td class="indexlinks"></td>
565 <td class="indexlinks"></td>
566 <td>
566 <td>
567 <a href="/coll/notrepo/f/atom-log" title="subscribe to repository atom feed">
567 <a href="/coll/notrepo/f/atom-log" title="subscribe to repository atom feed">
568 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
568 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
569 </a>
569 </a>
570 </td>
570 </td>
571 </tr>
571 </tr>
572
572
573 <tr>
573 <tr>
574 <td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
574 <td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
575 <td>unknown</td>
575 <td>unknown</td>
576 <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>
576 <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>
577 <td class="age">*</td> (glob)
577 <td class="age">*</td> (glob)
578 <td class="indexlinks"></td>
578 <td class="indexlinks"></td>
579 <td>
579 <td>
580 <a href="/rcoll/a/atom-log" title="subscribe to repository atom feed">
580 <a href="/rcoll/a/atom-log" title="subscribe to repository atom feed">
581 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
581 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
582 </a>
582 </a>
583 </td>
583 </td>
584 </tr>
584 </tr>
585
585
586 <tr>
586 <tr>
587 <td><a href="/rcoll/a/.hg/patches/?style=paper">rcoll/a/.hg/patches</a></td>
587 <td><a href="/rcoll/a/.hg/patches/?style=paper">rcoll/a/.hg/patches</a></td>
588 <td>unknown</td>
588 <td>unknown</td>
589 <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>
589 <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>
590 <td class="age">*</td> (glob)
590 <td class="age">*</td> (glob)
591 <td class="indexlinks"></td>
591 <td class="indexlinks"></td>
592 <td>
592 <td>
593 <a href="/rcoll/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
593 <a href="/rcoll/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
594 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
594 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
595 </a>
595 </a>
596 </td>
596 </td>
597 </tr>
597 </tr>
598
598
599 <tr>
599 <tr>
600 <td><a href="/rcoll/b/?style=paper">rcoll/b</a></td>
600 <td><a href="/rcoll/b/?style=paper">rcoll/b</a></td>
601 <td>unknown</td>
601 <td>unknown</td>
602 <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>
602 <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>
603 <td class="age">*</td> (glob)
603 <td class="age">*</td> (glob)
604 <td class="indexlinks"></td>
604 <td class="indexlinks"></td>
605 <td>
605 <td>
606 <a href="/rcoll/b/atom-log" title="subscribe to repository atom feed">
606 <a href="/rcoll/b/atom-log" title="subscribe to repository atom feed">
607 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
607 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
608 </a>
608 </a>
609 </td>
609 </td>
610 </tr>
610 </tr>
611
611
612 <tr>
612 <tr>
613 <td><a href="/rcoll/b/d/?style=paper">rcoll/b/d</a></td>
613 <td><a href="/rcoll/b/d/?style=paper">rcoll/b/d</a></td>
614 <td>unknown</td>
614 <td>unknown</td>
615 <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>
615 <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>
616 <td class="age">*</td> (glob)
616 <td class="age">*</td> (glob)
617 <td class="indexlinks"></td>
617 <td class="indexlinks"></td>
618 <td>
618 <td>
619 <a href="/rcoll/b/d/atom-log" title="subscribe to repository atom feed">
619 <a href="/rcoll/b/d/atom-log" title="subscribe to repository atom feed">
620 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
620 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
621 </a>
621 </a>
622 </td>
622 </td>
623 </tr>
623 </tr>
624
624
625 <tr>
625 <tr>
626 <td><a href="/rcoll/c/?style=paper">rcoll/c</a></td>
626 <td><a href="/rcoll/c/?style=paper">rcoll/c</a></td>
627 <td>unknown</td>
627 <td>unknown</td>
628 <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>
628 <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>
629 <td class="age">*</td> (glob)
629 <td class="age">*</td> (glob)
630 <td class="indexlinks"></td>
630 <td class="indexlinks"></td>
631 <td>
631 <td>
632 <a href="/rcoll/c/atom-log" title="subscribe to repository atom feed">
632 <a href="/rcoll/c/atom-log" title="subscribe to repository atom feed">
633 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
633 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
634 </a>
634 </a>
635 </td>
635 </td>
636 </tr>
636 </tr>
637
637
638 <tr>
638 <tr>
639 <td><a href="/rcoll/notrepo/e/?style=paper">rcoll/notrepo/e</a></td>
639 <td><a href="/rcoll/notrepo/e/?style=paper">rcoll/notrepo/e</a></td>
640 <td>unknown</td>
640 <td>unknown</td>
641 <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>
641 <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>
642 <td class="age">*</td> (glob)
642 <td class="age">*</td> (glob)
643 <td class="indexlinks"></td>
643 <td class="indexlinks"></td>
644 <td>
644 <td>
645 <a href="/rcoll/notrepo/e/atom-log" title="subscribe to repository atom feed">
645 <a href="/rcoll/notrepo/e/atom-log" title="subscribe to repository atom feed">
646 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
646 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
647 </a>
647 </a>
648 </td>
648 </td>
649 </tr>
649 </tr>
650
650
651 <tr>
651 <tr>
652 <td><a href="/rcoll/notrepo/e/e2/?style=paper">rcoll/notrepo/e/e2</a></td>
652 <td><a href="/rcoll/notrepo/e/e2/?style=paper">rcoll/notrepo/e/e2</a></td>
653 <td>unknown</td>
653 <td>unknown</td>
654 <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>
654 <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>
655 <td class="age">*</td> (glob)
655 <td class="age">*</td> (glob)
656 <td class="indexlinks"></td>
656 <td class="indexlinks"></td>
657 <td>
657 <td>
658 <a href="/rcoll/notrepo/e/e2/atom-log" title="subscribe to repository atom feed">
658 <a href="/rcoll/notrepo/e/e2/atom-log" title="subscribe to repository atom feed">
659 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
659 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
660 </a>
660 </a>
661 </td>
661 </td>
662 </tr>
662 </tr>
663
663
664 <tr>
664 <tr>
665 <td><a href="/rcoll/notrepo/f/?style=paper">fancy name for repo f</a></td>
665 <td><a href="/rcoll/notrepo/f/?style=paper">fancy name for repo f</a></td>
666 <td>unknown</td>
666 <td>unknown</td>
667 <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>
667 <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>
668 <td class="age">*</td> (glob)
668 <td class="age">*</td> (glob)
669 <td class="indexlinks"></td>
669 <td class="indexlinks"></td>
670 <td>
670 <td>
671 <a href="/rcoll/notrepo/f/atom-log" title="subscribe to repository atom feed">
671 <a href="/rcoll/notrepo/f/atom-log" title="subscribe to repository atom feed">
672 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
672 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
673 </a>
673 </a>
674 </td>
674 </td>
675 </tr>
675 </tr>
676
676
677 <tr>
677 <tr>
678 <td><a href="/rcoll/notrepo/f/f2/?style=paper">rcoll/notrepo/f/f2</a></td>
678 <td><a href="/rcoll/notrepo/f/f2/?style=paper">rcoll/notrepo/f/f2</a></td>
679 <td>unknown</td>
679 <td>unknown</td>
680 <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>
680 <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>
681 <td class="age">*</td> (glob)
681 <td class="age">*</td> (glob)
682 <td class="indexlinks"></td>
682 <td class="indexlinks"></td>
683 <td>
683 <td>
684 <a href="/rcoll/notrepo/f/f2/atom-log" title="subscribe to repository atom feed">
684 <a href="/rcoll/notrepo/f/f2/atom-log" title="subscribe to repository atom feed">
685 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
685 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
686 </a>
686 </a>
687 </td>
687 </td>
688 </tr>
688 </tr>
689
689
690 <tr>
690 <tr>
691 <td><a href="/star/webdir/a/?style=paper">star/webdir/a</a></td>
691 <td><a href="/star/webdir/a/?style=paper">star/webdir/a</a></td>
692 <td>unknown</td>
692 <td>unknown</td>
693 <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>
693 <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>
694 <td class="age">*</td> (glob)
694 <td class="age">*</td> (glob)
695 <td class="indexlinks"></td>
695 <td class="indexlinks"></td>
696 <td>
696 <td>
697 <a href="/star/webdir/a/atom-log" title="subscribe to repository atom feed">
697 <a href="/star/webdir/a/atom-log" title="subscribe to repository atom feed">
698 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
698 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
699 </a>
699 </a>
700 </td>
700 </td>
701 </tr>
701 </tr>
702
702
703 <tr>
703 <tr>
704 <td><a href="/star/webdir/a/.hg/patches/?style=paper">star/webdir/a/.hg/patches</a></td>
704 <td><a href="/star/webdir/a/.hg/patches/?style=paper">star/webdir/a/.hg/patches</a></td>
705 <td>unknown</td>
705 <td>unknown</td>
706 <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>
706 <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>
707 <td class="age">*</td> (glob)
707 <td class="age">*</td> (glob)
708 <td class="indexlinks"></td>
708 <td class="indexlinks"></td>
709 <td>
709 <td>
710 <a href="/star/webdir/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
710 <a href="/star/webdir/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
711 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
711 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
712 </a>
712 </a>
713 </td>
713 </td>
714 </tr>
714 </tr>
715
715
716 <tr>
716 <tr>
717 <td><a href="/star/webdir/b/?style=paper">star/webdir/b</a></td>
717 <td><a href="/star/webdir/b/?style=paper">star/webdir/b</a></td>
718 <td>unknown</td>
718 <td>unknown</td>
719 <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>
719 <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>
720 <td class="age">*</td> (glob)
720 <td class="age">*</td> (glob)
721 <td class="indexlinks"></td>
721 <td class="indexlinks"></td>
722 <td>
722 <td>
723 <a href="/star/webdir/b/atom-log" title="subscribe to repository atom feed">
723 <a href="/star/webdir/b/atom-log" title="subscribe to repository atom feed">
724 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
724 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
725 </a>
725 </a>
726 </td>
726 </td>
727 </tr>
727 </tr>
728
728
729 <tr>
729 <tr>
730 <td><a href="/star/webdir/c/?style=paper">star/webdir/c</a></td>
730 <td><a href="/star/webdir/c/?style=paper">star/webdir/c</a></td>
731 <td>unknown</td>
731 <td>unknown</td>
732 <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>
732 <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>
733 <td class="age">*</td> (glob)
733 <td class="age">*</td> (glob)
734 <td class="indexlinks"></td>
734 <td class="indexlinks"></td>
735 <td>
735 <td>
736 <a href="/star/webdir/c/atom-log" title="subscribe to repository atom feed">
736 <a href="/star/webdir/c/atom-log" title="subscribe to repository atom feed">
737 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
737 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
738 </a>
738 </a>
739 </td>
739 </td>
740 </tr>
740 </tr>
741
741
742 <tr>
742 <tr>
743 <td><a href="/star/webdir/notrepo/e/?style=paper">star/webdir/notrepo/e</a></td>
743 <td><a href="/star/webdir/notrepo/e/?style=paper">star/webdir/notrepo/e</a></td>
744 <td>unknown</td>
744 <td>unknown</td>
745 <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>
745 <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>
746 <td class="age">*</td> (glob)
746 <td class="age">*</td> (glob)
747 <td class="indexlinks"></td>
747 <td class="indexlinks"></td>
748 <td>
748 <td>
749 <a href="/star/webdir/notrepo/e/atom-log" title="subscribe to repository atom feed">
749 <a href="/star/webdir/notrepo/e/atom-log" title="subscribe to repository atom feed">
750 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
750 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
751 </a>
751 </a>
752 </td>
752 </td>
753 </tr>
753 </tr>
754
754
755 <tr>
755 <tr>
756 <td><a href="/star/webdir/notrepo/f/?style=paper">fancy name for repo f</a></td>
756 <td><a href="/star/webdir/notrepo/f/?style=paper">fancy name for repo f</a></td>
757 <td>unknown</td>
757 <td>unknown</td>
758 <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>
758 <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>
759 <td class="age">*</td> (glob)
759 <td class="age">*</td> (glob)
760 <td class="indexlinks"></td>
760 <td class="indexlinks"></td>
761 <td>
761 <td>
762 <a href="/star/webdir/notrepo/f/atom-log" title="subscribe to repository atom feed">
762 <a href="/star/webdir/notrepo/f/atom-log" title="subscribe to repository atom feed">
763 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
763 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
764 </a>
764 </a>
765 </td>
765 </td>
766 </tr>
766 </tr>
767
767
768 <tr>
768 <tr>
769 <td><a href="/starstar/webdir/a/?style=paper">starstar/webdir/a</a></td>
769 <td><a href="/starstar/webdir/a/?style=paper">starstar/webdir/a</a></td>
770 <td>unknown</td>
770 <td>unknown</td>
771 <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>
771 <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>
772 <td class="age">*</td> (glob)
772 <td class="age">*</td> (glob)
773 <td class="indexlinks"></td>
773 <td class="indexlinks"></td>
774 <td>
774 <td>
775 <a href="/starstar/webdir/a/atom-log" title="subscribe to repository atom feed">
775 <a href="/starstar/webdir/a/atom-log" title="subscribe to repository atom feed">
776 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
776 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
777 </a>
777 </a>
778 </td>
778 </td>
779 </tr>
779 </tr>
780
780
781 <tr>
781 <tr>
782 <td><a href="/starstar/webdir/a/.hg/patches/?style=paper">starstar/webdir/a/.hg/patches</a></td>
782 <td><a href="/starstar/webdir/a/.hg/patches/?style=paper">starstar/webdir/a/.hg/patches</a></td>
783 <td>unknown</td>
783 <td>unknown</td>
784 <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>
784 <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>
785 <td class="age">*</td> (glob)
785 <td class="age">*</td> (glob)
786 <td class="indexlinks"></td>
786 <td class="indexlinks"></td>
787 <td>
787 <td>
788 <a href="/starstar/webdir/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
788 <a href="/starstar/webdir/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
789 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
789 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
790 </a>
790 </a>
791 </td>
791 </td>
792 </tr>
792 </tr>
793
793
794 <tr>
794 <tr>
795 <td><a href="/starstar/webdir/b/?style=paper">starstar/webdir/b</a></td>
795 <td><a href="/starstar/webdir/b/?style=paper">starstar/webdir/b</a></td>
796 <td>unknown</td>
796 <td>unknown</td>
797 <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>
797 <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>
798 <td class="age">*</td> (glob)
798 <td class="age">*</td> (glob)
799 <td class="indexlinks"></td>
799 <td class="indexlinks"></td>
800 <td>
800 <td>
801 <a href="/starstar/webdir/b/atom-log" title="subscribe to repository atom feed">
801 <a href="/starstar/webdir/b/atom-log" title="subscribe to repository atom feed">
802 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
802 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
803 </a>
803 </a>
804 </td>
804 </td>
805 </tr>
805 </tr>
806
806
807 <tr>
807 <tr>
808 <td><a href="/starstar/webdir/b/d/?style=paper">starstar/webdir/b/d</a></td>
808 <td><a href="/starstar/webdir/b/d/?style=paper">starstar/webdir/b/d</a></td>
809 <td>unknown</td>
809 <td>unknown</td>
810 <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>
810 <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>
811 <td class="age">*</td> (glob)
811 <td class="age">*</td> (glob)
812 <td class="indexlinks"></td>
812 <td class="indexlinks"></td>
813 <td>
813 <td>
814 <a href="/starstar/webdir/b/d/atom-log" title="subscribe to repository atom feed">
814 <a href="/starstar/webdir/b/d/atom-log" title="subscribe to repository atom feed">
815 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
815 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
816 </a>
816 </a>
817 </td>
817 </td>
818 </tr>
818 </tr>
819
819
820 <tr>
820 <tr>
821 <td><a href="/starstar/webdir/c/?style=paper">starstar/webdir/c</a></td>
821 <td><a href="/starstar/webdir/c/?style=paper">starstar/webdir/c</a></td>
822 <td>unknown</td>
822 <td>unknown</td>
823 <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>
823 <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>
824 <td class="age">*</td> (glob)
824 <td class="age">*</td> (glob)
825 <td class="indexlinks"></td>
825 <td class="indexlinks"></td>
826 <td>
826 <td>
827 <a href="/starstar/webdir/c/atom-log" title="subscribe to repository atom feed">
827 <a href="/starstar/webdir/c/atom-log" title="subscribe to repository atom feed">
828 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
828 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
829 </a>
829 </a>
830 </td>
830 </td>
831 </tr>
831 </tr>
832
832
833 <tr>
833 <tr>
834 <td><a href="/starstar/webdir/notrepo/e/?style=paper">starstar/webdir/notrepo/e</a></td>
834 <td><a href="/starstar/webdir/notrepo/e/?style=paper">starstar/webdir/notrepo/e</a></td>
835 <td>unknown</td>
835 <td>unknown</td>
836 <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>
836 <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>
837 <td class="age">*</td> (glob)
837 <td class="age">*</td> (glob)
838 <td class="indexlinks"></td>
838 <td class="indexlinks"></td>
839 <td>
839 <td>
840 <a href="/starstar/webdir/notrepo/e/atom-log" title="subscribe to repository atom feed">
840 <a href="/starstar/webdir/notrepo/e/atom-log" title="subscribe to repository atom feed">
841 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
841 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
842 </a>
842 </a>
843 </td>
843 </td>
844 </tr>
844 </tr>
845
845
846 <tr>
846 <tr>
847 <td><a href="/starstar/webdir/notrepo/e/e2/?style=paper">starstar/webdir/notrepo/e/e2</a></td>
847 <td><a href="/starstar/webdir/notrepo/e/e2/?style=paper">starstar/webdir/notrepo/e/e2</a></td>
848 <td>unknown</td>
848 <td>unknown</td>
849 <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>
849 <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>
850 <td class="age">*</td> (glob)
850 <td class="age">*</td> (glob)
851 <td class="indexlinks"></td>
851 <td class="indexlinks"></td>
852 <td>
852 <td>
853 <a href="/starstar/webdir/notrepo/e/e2/atom-log" title="subscribe to repository atom feed">
853 <a href="/starstar/webdir/notrepo/e/e2/atom-log" title="subscribe to repository atom feed">
854 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
854 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
855 </a>
855 </a>
856 </td>
856 </td>
857 </tr>
857 </tr>
858
858
859 <tr>
859 <tr>
860 <td><a href="/starstar/webdir/notrepo/f/?style=paper">fancy name for repo f</a></td>
860 <td><a href="/starstar/webdir/notrepo/f/?style=paper">fancy name for repo f</a></td>
861 <td>unknown</td>
861 <td>unknown</td>
862 <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>
862 <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>
863 <td class="age">*</td> (glob)
863 <td class="age">*</td> (glob)
864 <td class="indexlinks"></td>
864 <td class="indexlinks"></td>
865 <td>
865 <td>
866 <a href="/starstar/webdir/notrepo/f/atom-log" title="subscribe to repository atom feed">
866 <a href="/starstar/webdir/notrepo/f/atom-log" title="subscribe to repository atom feed">
867 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
867 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
868 </a>
868 </a>
869 </td>
869 </td>
870 </tr>
870 </tr>
871
871
872 <tr>
872 <tr>
873 <td><a href="/starstar/webdir/notrepo/f/f2/?style=paper">starstar/webdir/notrepo/f/f2</a></td>
873 <td><a href="/starstar/webdir/notrepo/f/f2/?style=paper">starstar/webdir/notrepo/f/f2</a></td>
874 <td>unknown</td>
874 <td>unknown</td>
875 <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>
875 <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>
876 <td class="age">*</td> (glob)
876 <td class="age">*</td> (glob)
877 <td class="indexlinks"></td>
877 <td class="indexlinks"></td>
878 <td>
878 <td>
879 <a href="/starstar/webdir/notrepo/f/f2/atom-log" title="subscribe to repository atom feed">
879 <a href="/starstar/webdir/notrepo/f/f2/atom-log" title="subscribe to repository atom feed">
880 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
880 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
881 </a>
881 </a>
882 </td>
882 </td>
883 </tr>
883 </tr>
884
884
885 <tr>
885 <tr>
886 <td><a href="/astar/?style=paper">astar</a></td>
886 <td><a href="/astar/?style=paper">astar</a></td>
887 <td>unknown</td>
887 <td>unknown</td>
888 <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>
888 <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>
889 <td class="age">*</td> (glob)
889 <td class="age">*</td> (glob)
890 <td class="indexlinks"></td>
890 <td class="indexlinks"></td>
891 <td>
891 <td>
892 <a href="/astar/atom-log" title="subscribe to repository atom feed">
892 <a href="/astar/atom-log" title="subscribe to repository atom feed">
893 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
893 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
894 </a>
894 </a>
895 </td>
895 </td>
896 </tr>
896 </tr>
897
897
898 <tr>
898 <tr>
899 <td><a href="/astar/.hg/patches/?style=paper">astar/.hg/patches</a></td>
899 <td><a href="/astar/.hg/patches/?style=paper">astar/.hg/patches</a></td>
900 <td>unknown</td>
900 <td>unknown</td>
901 <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>
901 <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>
902 <td class="age">*</td> (glob)
902 <td class="age">*</td> (glob)
903 <td class="indexlinks"></td>
903 <td class="indexlinks"></td>
904 <td>
904 <td>
905 <a href="/astar/.hg/patches/atom-log" title="subscribe to repository atom feed">
905 <a href="/astar/.hg/patches/atom-log" title="subscribe to repository atom feed">
906 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
906 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
907 </a>
907 </a>
908 </td>
908 </td>
909 </tr>
909 </tr>
910
910
911 </tbody>
911 </tbody>
912 </table>
912 </table>
913 </div>
913 </div>
914 </div>
914 </div>
915
915
916
916
917 </body>
917 </body>
918 </html>
918 </html>
919
919
920 $ get-with-headers.py localhost:$HGPORT1 't?style=raw'
920 $ get-with-headers.py localhost:$HGPORT1 't?style=raw'
921 200 Script output follows
921 200 Script output follows
922
922
923
923
924 /t/a/
924 /t/a/
925
925
926 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
926 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
927 200 Script output follows
927 200 Script output follows
928
928
929
929
930 /t/a/
930 /t/a/
931
931
932 $ get-with-headers.py localhost:$HGPORT1 't/?style=paper'
932 $ get-with-headers.py localhost:$HGPORT1 't/?style=paper'
933 200 Script output follows
933 200 Script output follows
934
934
935 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
935 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
936 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
936 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
937 <head>
937 <head>
938 <link rel="icon" href="/static/hgicon.png" type="image/png" />
938 <link rel="icon" href="/static/hgicon.png" type="image/png" />
939 <meta name="robots" content="index, nofollow" />
939 <meta name="robots" content="index, nofollow" />
940 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
940 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
941 <script type="text/javascript" src="/static/mercurial.js"></script>
941 <script type="text/javascript" src="/static/mercurial.js"></script>
942
942
943 <title>Mercurial repositories index</title>
943 <title>Mercurial repositories index</title>
944 </head>
944 </head>
945 <body>
945 <body>
946
946
947 <div class="container">
947 <div class="container">
948 <div class="menu">
948 <div class="menu">
949 <a href="https://mercurial-scm.org/">
949 <a href="https://mercurial-scm.org/">
950 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
950 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
951 </div>
951 </div>
952 <div class="main">
952 <div class="main">
953 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/t">t</a> </h2>
953 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/t">t</a> </h2>
954
954
955 <table class="bigtable">
955 <table class="bigtable">
956 <thead>
956 <thead>
957 <tr>
957 <tr>
958 <th><a href="?sort=name">Name</a></th>
958 <th><a href="?sort=name">Name</a></th>
959 <th><a href="?sort=description">Description</a></th>
959 <th><a href="?sort=description">Description</a></th>
960 <th><a href="?sort=contact">Contact</a></th>
960 <th><a href="?sort=contact">Contact</a></th>
961 <th><a href="?sort=lastchange">Last modified</a></th>
961 <th><a href="?sort=lastchange">Last modified</a></th>
962 <th>&nbsp;</th>
962 <th>&nbsp;</th>
963 <th>&nbsp;</th>
963 <th>&nbsp;</th>
964 </tr>
964 </tr>
965 </thead>
965 </thead>
966 <tbody class="stripes2">
966 <tbody class="stripes2">
967
967
968 <tr>
968 <tr>
969 <td><a href="/t/a/?style=paper">a</a></td>
969 <td><a href="/t/a/?style=paper">a</a></td>
970 <td>unknown</td>
970 <td>unknown</td>
971 <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>
971 <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>
972 <td class="age">*</td> (glob)
972 <td class="age">*</td> (glob)
973 <td class="indexlinks"></td>
973 <td class="indexlinks"></td>
974 <td>
974 <td>
975 <a href="/t/a/atom-log" title="subscribe to repository atom feed">
975 <a href="/t/a/atom-log" title="subscribe to repository atom feed">
976 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
976 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
977 </a>
977 </a>
978 </td>
978 </td>
979 </tr>
979 </tr>
980
980
981 </tbody>
981 </tbody>
982 </table>
982 </table>
983 </div>
983 </div>
984 </div>
984 </div>
985
985
986
986
987 </body>
987 </body>
988 </html>
988 </html>
989
989
990 $ get-with-headers.py localhost:$HGPORT1 't/a?style=atom'
990 $ get-with-headers.py localhost:$HGPORT1 't/a?style=atom'
991 200 Script output follows
991 200 Script output follows
992
992
993 <?xml version="1.0" encoding="ascii"?>
993 <?xml version="1.0" encoding="ascii"?>
994 <feed xmlns="http://www.w3.org/2005/Atom">
994 <feed xmlns="http://www.w3.org/2005/Atom">
995 <!-- Changelog -->
995 <!-- Changelog -->
996 <id>http://*:$HGPORT1/t/a/</id> (glob)
996 <id>http://*:$HGPORT1/t/a/</id> (glob)
997 <link rel="self" href="http://*:$HGPORT1/t/a/atom-log"/> (glob)
997 <link rel="self" href="http://*:$HGPORT1/t/a/atom-log"/> (glob)
998 <link rel="alternate" href="http://*:$HGPORT1/t/a/"/> (glob)
998 <link rel="alternate" href="http://*:$HGPORT1/t/a/"/> (glob)
999 <title>t/a Changelog</title>
999 <title>t/a Changelog</title>
1000 <updated>1970-01-01T00:00:01+00:00</updated>
1000 <updated>1970-01-01T00:00:01+00:00</updated>
1001
1001
1002 <entry>
1002 <entry>
1003 <title>[default] a</title>
1003 <title>[default] a</title>
1004 <id>http://*:$HGPORT1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id> (glob)
1004 <id>http://*:$HGPORT1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id> (glob)
1005 <link href="http://*:$HGPORT1/t/a/rev/8580ff50825a"/> (glob)
1005 <link href="http://*:$HGPORT1/t/a/rev/8580ff50825a"/> (glob)
1006 <author>
1006 <author>
1007 <name>test</name>
1007 <name>test</name>
1008 <email>&#116;&#101;&#115;&#116;</email>
1008 <email>&#116;&#101;&#115;&#116;</email>
1009 </author>
1009 </author>
1010 <updated>1970-01-01T00:00:01+00:00</updated>
1010 <updated>1970-01-01T00:00:01+00:00</updated>
1011 <published>1970-01-01T00:00:01+00:00</published>
1011 <published>1970-01-01T00:00:01+00:00</published>
1012 <content type="xhtml">
1012 <content type="xhtml">
1013 <table xmlns="http://www.w3.org/1999/xhtml">
1013 <table xmlns="http://www.w3.org/1999/xhtml">
1014 <tr>
1014 <tr>
1015 <th style="text-align:left;">changeset</th>
1015 <th style="text-align:left;">changeset</th>
1016 <td>8580ff50825a</td>
1016 <td>8580ff50825a</td>
1017 </tr>
1017 </tr>
1018 <tr>
1018 <tr>
1019 <th style="text-align:left;">branch</th>
1019 <th style="text-align:left;">branch</th>
1020 <td>default</td>
1020 <td>default</td>
1021 </tr>
1021 </tr>
1022 <tr>
1022 <tr>
1023 <th style="text-align:left;">bookmark</th>
1023 <th style="text-align:left;">bookmark</th>
1024 <td></td>
1024 <td></td>
1025 </tr>
1025 </tr>
1026 <tr>
1026 <tr>
1027 <th style="text-align:left;">tag</th>
1027 <th style="text-align:left;">tag</th>
1028 <td>tip</td>
1028 <td>tip</td>
1029 </tr>
1029 </tr>
1030 <tr>
1030 <tr>
1031 <th style="text-align:left;">user</th>
1031 <th style="text-align:left;">user</th>
1032 <td>&#116;&#101;&#115;&#116;</td>
1032 <td>&#116;&#101;&#115;&#116;</td>
1033 </tr>
1033 </tr>
1034 <tr>
1034 <tr>
1035 <th style="text-align:left;vertical-align:top;">description</th>
1035 <th style="text-align:left;vertical-align:top;">description</th>
1036 <td>a</td>
1036 <td>a</td>
1037 </tr>
1037 </tr>
1038 <tr>
1038 <tr>
1039 <th style="text-align:left;vertical-align:top;">files</th>
1039 <th style="text-align:left;vertical-align:top;">files</th>
1040 <td>a<br /></td>
1040 <td>a<br /></td>
1041 </tr>
1041 </tr>
1042 </table>
1042 </table>
1043 </content>
1043 </content>
1044 </entry>
1044 </entry>
1045
1045
1046 </feed>
1046 </feed>
1047 $ get-with-headers.py localhost:$HGPORT1 't/a/?style=atom'
1047 $ get-with-headers.py localhost:$HGPORT1 't/a/?style=atom'
1048 200 Script output follows
1048 200 Script output follows
1049
1049
1050 <?xml version="1.0" encoding="ascii"?>
1050 <?xml version="1.0" encoding="ascii"?>
1051 <feed xmlns="http://www.w3.org/2005/Atom">
1051 <feed xmlns="http://www.w3.org/2005/Atom">
1052 <!-- Changelog -->
1052 <!-- Changelog -->
1053 <id>http://*:$HGPORT1/t/a/</id> (glob)
1053 <id>http://*:$HGPORT1/t/a/</id> (glob)
1054 <link rel="self" href="http://*:$HGPORT1/t/a/atom-log"/> (glob)
1054 <link rel="self" href="http://*:$HGPORT1/t/a/atom-log"/> (glob)
1055 <link rel="alternate" href="http://*:$HGPORT1/t/a/"/> (glob)
1055 <link rel="alternate" href="http://*:$HGPORT1/t/a/"/> (glob)
1056 <title>t/a Changelog</title>
1056 <title>t/a Changelog</title>
1057 <updated>1970-01-01T00:00:01+00:00</updated>
1057 <updated>1970-01-01T00:00:01+00:00</updated>
1058
1058
1059 <entry>
1059 <entry>
1060 <title>[default] a</title>
1060 <title>[default] a</title>
1061 <id>http://*:$HGPORT1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id> (glob)
1061 <id>http://*:$HGPORT1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id> (glob)
1062 <link href="http://*:$HGPORT1/t/a/rev/8580ff50825a"/> (glob)
1062 <link href="http://*:$HGPORT1/t/a/rev/8580ff50825a"/> (glob)
1063 <author>
1063 <author>
1064 <name>test</name>
1064 <name>test</name>
1065 <email>&#116;&#101;&#115;&#116;</email>
1065 <email>&#116;&#101;&#115;&#116;</email>
1066 </author>
1066 </author>
1067 <updated>1970-01-01T00:00:01+00:00</updated>
1067 <updated>1970-01-01T00:00:01+00:00</updated>
1068 <published>1970-01-01T00:00:01+00:00</published>
1068 <published>1970-01-01T00:00:01+00:00</published>
1069 <content type="xhtml">
1069 <content type="xhtml">
1070 <table xmlns="http://www.w3.org/1999/xhtml">
1070 <table xmlns="http://www.w3.org/1999/xhtml">
1071 <tr>
1071 <tr>
1072 <th style="text-align:left;">changeset</th>
1072 <th style="text-align:left;">changeset</th>
1073 <td>8580ff50825a</td>
1073 <td>8580ff50825a</td>
1074 </tr>
1074 </tr>
1075 <tr>
1075 <tr>
1076 <th style="text-align:left;">branch</th>
1076 <th style="text-align:left;">branch</th>
1077 <td>default</td>
1077 <td>default</td>
1078 </tr>
1078 </tr>
1079 <tr>
1079 <tr>
1080 <th style="text-align:left;">bookmark</th>
1080 <th style="text-align:left;">bookmark</th>
1081 <td></td>
1081 <td></td>
1082 </tr>
1082 </tr>
1083 <tr>
1083 <tr>
1084 <th style="text-align:left;">tag</th>
1084 <th style="text-align:left;">tag</th>
1085 <td>tip</td>
1085 <td>tip</td>
1086 </tr>
1086 </tr>
1087 <tr>
1087 <tr>
1088 <th style="text-align:left;">user</th>
1088 <th style="text-align:left;">user</th>
1089 <td>&#116;&#101;&#115;&#116;</td>
1089 <td>&#116;&#101;&#115;&#116;</td>
1090 </tr>
1090 </tr>
1091 <tr>
1091 <tr>
1092 <th style="text-align:left;vertical-align:top;">description</th>
1092 <th style="text-align:left;vertical-align:top;">description</th>
1093 <td>a</td>
1093 <td>a</td>
1094 </tr>
1094 </tr>
1095 <tr>
1095 <tr>
1096 <th style="text-align:left;vertical-align:top;">files</th>
1096 <th style="text-align:left;vertical-align:top;">files</th>
1097 <td>a<br /></td>
1097 <td>a<br /></td>
1098 </tr>
1098 </tr>
1099 </table>
1099 </table>
1100 </content>
1100 </content>
1101 </entry>
1101 </entry>
1102
1102
1103 </feed>
1103 </feed>
1104 $ get-with-headers.py localhost:$HGPORT1 't/a/file/tip/a?style=raw'
1104 $ get-with-headers.py localhost:$HGPORT1 't/a/file/tip/a?style=raw'
1105 200 Script output follows
1105 200 Script output follows
1106
1106
1107 a
1107 a
1108
1108
1109 Test [paths] '*' extension
1109 Test [paths] '*' extension
1110
1110
1111 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1111 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1112 200 Script output follows
1112 200 Script output follows
1113
1113
1114
1114
1115 /coll/a/
1115 /coll/a/
1116 /coll/a/.hg/patches/
1116 /coll/a/.hg/patches/
1117 /coll/b/
1117 /coll/b/
1118 /coll/c/
1118 /coll/c/
1119 /coll/notrepo/e/
1119 /coll/notrepo/e/
1120 /coll/notrepo/f/
1120 /coll/notrepo/f/
1121
1121
1122 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1122 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1123 200 Script output follows
1123 200 Script output follows
1124
1124
1125 a
1125 a
1126
1126
1127 Test [paths] '**' extension
1127 Test [paths] '**' extension
1128
1128
1129 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1129 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1130 200 Script output follows
1130 200 Script output follows
1131
1131
1132
1132
1133 /rcoll/a/
1133 /rcoll/a/
1134 /rcoll/a/.hg/patches/
1134 /rcoll/a/.hg/patches/
1135 /rcoll/b/
1135 /rcoll/b/
1136 /rcoll/b/d/
1136 /rcoll/b/d/
1137 /rcoll/c/
1137 /rcoll/c/
1138 /rcoll/notrepo/e/
1138 /rcoll/notrepo/e/
1139 /rcoll/notrepo/e/e2/
1139 /rcoll/notrepo/e/e2/
1140 /rcoll/notrepo/f/
1140 /rcoll/notrepo/f/
1141 /rcoll/notrepo/f/f2/
1141 /rcoll/notrepo/f/f2/
1142
1142
1143 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1143 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1144 200 Script output follows
1144 200 Script output follows
1145
1145
1146 d
1146 d
1147
1147
1148 Test collapse = True
1148 Test collapse = True
1149
1149
1150 $ killdaemons.py
1150 $ killdaemons.py
1151 $ cat >> paths.conf <<EOF
1151 $ cat >> paths.conf <<EOF
1152 > [web]
1152 > [web]
1153 > collapse=true
1153 > collapse=true
1154 > descend = true
1154 > descend = true
1155 > EOF
1155 > EOF
1156 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1156 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1157 > -A access-paths.log -E error-paths-3.log
1157 > -A access-paths.log -E error-paths-3.log
1158 $ cat hg.pid >> $DAEMON_PIDS
1158 $ cat hg.pid >> $DAEMON_PIDS
1159 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1159 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1160 200 Script output follows
1160 200 Script output follows
1161
1161
1162
1162
1163 /coll/a/
1163 /coll/a/
1164 /coll/a/.hg/patches/
1164 /coll/a/.hg/patches/
1165 /coll/b/
1165 /coll/b/
1166 /coll/c/
1166 /coll/c/
1167 /coll/notrepo/
1167 /coll/notrepo/
1168
1168
1169 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1169 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1170 200 Script output follows
1170 200 Script output follows
1171
1171
1172 a
1172 a
1173 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1173 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1174 200 Script output follows
1174 200 Script output follows
1175
1175
1176
1176
1177 /rcoll/a/
1177 /rcoll/a/
1178 /rcoll/a/.hg/patches/
1178 /rcoll/a/.hg/patches/
1179 /rcoll/b/
1179 /rcoll/b/
1180 /rcoll/b/d/
1180 /rcoll/b/d/
1181 /rcoll/c/
1181 /rcoll/c/
1182 /rcoll/notrepo/
1182 /rcoll/notrepo/
1183
1183
1184 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1184 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1185 200 Script output follows
1185 200 Script output follows
1186
1186
1187 d
1187 d
1188
1188
1189 Test intermediate directories
1189 Test intermediate directories
1190
1190
1191 Hide the subrepo parent
1191 Hide the subrepo parent
1192
1192
1193 $ cp $root/notrepo/f/.hg/hgrc $root/notrepo/f/.hg/hgrc.bak
1193 $ cp $root/notrepo/f/.hg/hgrc $root/notrepo/f/.hg/hgrc.bak
1194 $ cat >> $root/notrepo/f/.hg/hgrc << EOF
1194 $ cat >> $root/notrepo/f/.hg/hgrc << EOF
1195 > [web]
1195 > [web]
1196 > hidden = True
1196 > hidden = True
1197 > EOF
1197 > EOF
1198
1198
1199 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1199 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1200 200 Script output follows
1200 200 Script output follows
1201
1201
1202
1202
1203 /rcoll/notrepo/e/
1203 /rcoll/notrepo/e/
1204 /rcoll/notrepo/e/e2/
1204 /rcoll/notrepo/e/e2/
1205
1205
1206
1206
1207 Subrepo parent not hidden
1207 Subrepo parent not hidden
1208 $ mv $root/notrepo/f/.hg/hgrc.bak $root/notrepo/f/.hg/hgrc
1208 $ mv $root/notrepo/f/.hg/hgrc.bak $root/notrepo/f/.hg/hgrc
1209
1209
1210 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1210 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1211 200 Script output follows
1211 200 Script output follows
1212
1212
1213
1213
1214 /rcoll/notrepo/e/
1214 /rcoll/notrepo/e/
1215 /rcoll/notrepo/e/e2/
1215 /rcoll/notrepo/e/e2/
1216 /rcoll/notrepo/f/
1216 /rcoll/notrepo/f/
1217 /rcoll/notrepo/f/f2/
1217 /rcoll/notrepo/f/f2/
1218
1218
1219
1219
1220 Test repositories inside intermediate directories
1220 Test repositories inside intermediate directories
1221
1221
1222 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/e/file/tip/e?style=raw'
1222 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/e/file/tip/e?style=raw'
1223 200 Script output follows
1223 200 Script output follows
1224
1224
1225 e
1225 e
1226
1226
1227 Test subrepositories inside intermediate directories
1227 Test subrepositories inside intermediate directories
1228
1228
1229 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/f2/file/tip/f2?style=raw'
1229 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/f2/file/tip/f2?style=raw'
1230 200 Script output follows
1230 200 Script output follows
1231
1231
1232 f2
1232 f2
1233
1233
1234 Test accessing file that is shadowed by another repository
1234 Test accessing file that could be shadowed by another repository if the URL
1235 path were audited as a working-directory path:
1235
1236
1236 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/f3/file?style=raw'
1237 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/f3/file?style=raw'
1237 403 Forbidden
1238 200 Script output follows
1238
1239
1239
1240 error: path 'f3/file' is inside nested repo 'f3'
1240 f3/file
1241 [1]
1241
1242 Test accessing working-directory file that is shadowed by another repository
1242
1243
1243 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/ffffffffffff/f3/file?style=raw'
1244 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/ffffffffffff/f3/file?style=raw'
1244 403 Forbidden
1245 403 Forbidden
1245
1246
1246
1247
1247 error: path 'f3/file' is inside nested repo 'f3'
1248 error: path 'f3/file' is inside nested repo 'f3'
1248 [1]
1249 [1]
1249
1250
1250 Test accessing invalid paths:
1251 Test accessing invalid paths:
1251
1252
1252 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/..?style=raw'
1253 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/..?style=raw'
1253 403 Forbidden
1254 403 Forbidden
1254
1255
1255
1256
1256 error: .. not under root '$TESTTMP/dir/webdir/notrepo/f'
1257 error: .. not under root '$TESTTMP/dir/webdir/notrepo/f'
1257 [1]
1258 [1]
1258
1259
1259 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/.hg/hgrc?style=raw'
1260 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/.hg/hgrc?style=raw'
1260 403 Forbidden
1261 403 Forbidden
1261
1262
1262
1263
1263 error: path contains illegal component: .hg/hgrc
1264 error: path contains illegal component: .hg/hgrc
1264 [1]
1265 [1]
1265
1266
1266 Test descend = False
1267 Test descend = False
1267
1268
1268 $ killdaemons.py
1269 $ killdaemons.py
1269 $ cat >> paths.conf <<EOF
1270 $ cat >> paths.conf <<EOF
1270 > descend=false
1271 > descend=false
1271 > EOF
1272 > EOF
1272 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1273 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1273 > -A access-paths.log -E error-paths-4.log
1274 > -A access-paths.log -E error-paths-4.log
1274 $ cat hg.pid >> $DAEMON_PIDS
1275 $ cat hg.pid >> $DAEMON_PIDS
1275 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1276 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1276 200 Script output follows
1277 200 Script output follows
1277
1278
1278
1279
1279 /coll/a/
1280 /coll/a/
1280 /coll/b/
1281 /coll/b/
1281 /coll/c/
1282 /coll/c/
1282
1283
1283 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1284 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1284 200 Script output follows
1285 200 Script output follows
1285
1286
1286 a
1287 a
1287 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1288 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1288 200 Script output follows
1289 200 Script output follows
1289
1290
1290
1291
1291 /rcoll/a/
1292 /rcoll/a/
1292 /rcoll/b/
1293 /rcoll/b/
1293 /rcoll/c/
1294 /rcoll/c/
1294
1295
1295 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1296 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1296 200 Script output follows
1297 200 Script output follows
1297
1298
1298 d
1299 d
1299
1300
1300 Test intermediate directories
1301 Test intermediate directories
1301
1302
1302 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1303 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1303 200 Script output follows
1304 200 Script output follows
1304
1305
1305
1306
1306 /rcoll/notrepo/e/
1307 /rcoll/notrepo/e/
1307 /rcoll/notrepo/f/
1308 /rcoll/notrepo/f/
1308
1309
1309
1310
1310 Test repositories inside intermediate directories
1311 Test repositories inside intermediate directories
1311
1312
1312 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/e/file/tip/e?style=raw'
1313 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/e/file/tip/e?style=raw'
1313 200 Script output follows
1314 200 Script output follows
1314
1315
1315 e
1316 e
1316
1317
1317 Test subrepositories inside intermediate directories
1318 Test subrepositories inside intermediate directories
1318
1319
1319 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/f2/file/tip/f2?style=raw'
1320 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/f2/file/tip/f2?style=raw'
1320 200 Script output follows
1321 200 Script output follows
1321
1322
1322 f2
1323 f2
1323
1324
1324 Test [paths] '*' in a repo root
1325 Test [paths] '*' in a repo root
1325
1326
1326 $ hg id http://localhost:$HGPORT1/astar
1327 $ hg id http://localhost:$HGPORT1/astar
1327 8580ff50825a
1328 8580ff50825a
1328
1329
1329 $ killdaemons.py
1330 $ killdaemons.py
1330 $ cat > paths.conf <<EOF
1331 $ cat > paths.conf <<EOF
1331 > [paths]
1332 > [paths]
1332 > t/a = $root/a
1333 > t/a = $root/a
1333 > t/b = $root/b
1334 > t/b = $root/b
1334 > c = $root/c
1335 > c = $root/c
1335 > EOF
1336 > EOF
1336 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1337 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1337 > -A access-paths.log -E error-paths-5.log
1338 > -A access-paths.log -E error-paths-5.log
1338 $ cat hg.pid >> $DAEMON_PIDS
1339 $ cat hg.pid >> $DAEMON_PIDS
1339 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1340 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1340 200 Script output follows
1341 200 Script output follows
1341
1342
1342
1343
1343 /t/a/
1344 /t/a/
1344 /t/b/
1345 /t/b/
1345 /c/
1346 /c/
1346
1347
1347 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1348 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1348 200 Script output follows
1349 200 Script output follows
1349
1350
1350
1351
1351 /t/a/
1352 /t/a/
1352 /t/b/
1353 /t/b/
1353
1354
1354
1355
1355 Test collapse = True
1356 Test collapse = True
1356
1357
1357 $ killdaemons.py
1358 $ killdaemons.py
1358 $ cat >> paths.conf <<EOF
1359 $ cat >> paths.conf <<EOF
1359 > [web]
1360 > [web]
1360 > collapse=true
1361 > collapse=true
1361 > EOF
1362 > EOF
1362 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1363 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1363 > -A access-paths.log -E error-paths-6.log
1364 > -A access-paths.log -E error-paths-6.log
1364 $ cat hg.pid >> $DAEMON_PIDS
1365 $ cat hg.pid >> $DAEMON_PIDS
1365 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1366 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1366 200 Script output follows
1367 200 Script output follows
1367
1368
1368
1369
1369 /t/
1370 /t/
1370 /c/
1371 /c/
1371
1372
1372 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1373 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1373 200 Script output follows
1374 200 Script output follows
1374
1375
1375
1376
1376 /t/a/
1377 /t/a/
1377 /t/b/
1378 /t/b/
1378
1379
1379
1380
1380 test descend = False
1381 test descend = False
1381
1382
1382 $ killdaemons.py
1383 $ killdaemons.py
1383 $ cat >> paths.conf <<EOF
1384 $ cat >> paths.conf <<EOF
1384 > descend=false
1385 > descend=false
1385 > EOF
1386 > EOF
1386 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1387 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1387 > -A access-paths.log -E error-paths-7.log
1388 > -A access-paths.log -E error-paths-7.log
1388 $ cat hg.pid >> $DAEMON_PIDS
1389 $ cat hg.pid >> $DAEMON_PIDS
1389 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1390 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1390 200 Script output follows
1391 200 Script output follows
1391
1392
1392
1393
1393 /c/
1394 /c/
1394
1395
1395 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1396 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1396 200 Script output follows
1397 200 Script output follows
1397
1398
1398
1399
1399 /t/a/
1400 /t/a/
1400 /t/b/
1401 /t/b/
1401
1402
1402 $ killdaemons.py
1403 $ killdaemons.py
1403 $ cat > paths.conf <<EOF
1404 $ cat > paths.conf <<EOF
1404 > [paths]
1405 > [paths]
1405 > nostore = $root/nostore
1406 > nostore = $root/nostore
1406 > inexistent = $root/inexistent
1407 > inexistent = $root/inexistent
1407 > EOF
1408 > EOF
1408 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1409 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1409 > -A access-paths.log -E error-paths-8.log
1410 > -A access-paths.log -E error-paths-8.log
1410 $ cat hg.pid >> $DAEMON_PIDS
1411 $ cat hg.pid >> $DAEMON_PIDS
1411
1412
1412 test inexistent and inaccessible repo should be ignored silently
1413 test inexistent and inaccessible repo should be ignored silently
1413
1414
1414 $ get-with-headers.py localhost:$HGPORT1 ''
1415 $ get-with-headers.py localhost:$HGPORT1 ''
1415 200 Script output follows
1416 200 Script output follows
1416
1417
1417 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1418 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1418 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1419 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1419 <head>
1420 <head>
1420 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1421 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1421 <meta name="robots" content="index, nofollow" />
1422 <meta name="robots" content="index, nofollow" />
1422 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1423 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1423 <script type="text/javascript" src="/static/mercurial.js"></script>
1424 <script type="text/javascript" src="/static/mercurial.js"></script>
1424
1425
1425 <title>Mercurial repositories index</title>
1426 <title>Mercurial repositories index</title>
1426 </head>
1427 </head>
1427 <body>
1428 <body>
1428
1429
1429 <div class="container">
1430 <div class="container">
1430 <div class="menu">
1431 <div class="menu">
1431 <a href="https://mercurial-scm.org/">
1432 <a href="https://mercurial-scm.org/">
1432 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
1433 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
1433 </div>
1434 </div>
1434 <div class="main">
1435 <div class="main">
1435 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1436 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1436
1437
1437 <table class="bigtable">
1438 <table class="bigtable">
1438 <thead>
1439 <thead>
1439 <tr>
1440 <tr>
1440 <th><a href="?sort=name">Name</a></th>
1441 <th><a href="?sort=name">Name</a></th>
1441 <th><a href="?sort=description">Description</a></th>
1442 <th><a href="?sort=description">Description</a></th>
1442 <th><a href="?sort=contact">Contact</a></th>
1443 <th><a href="?sort=contact">Contact</a></th>
1443 <th><a href="?sort=lastchange">Last modified</a></th>
1444 <th><a href="?sort=lastchange">Last modified</a></th>
1444 <th>&nbsp;</th>
1445 <th>&nbsp;</th>
1445 <th>&nbsp;</th>
1446 <th>&nbsp;</th>
1446 </tr>
1447 </tr>
1447 </thead>
1448 </thead>
1448 <tbody class="stripes2">
1449 <tbody class="stripes2">
1449
1450
1450 </tbody>
1451 </tbody>
1451 </table>
1452 </table>
1452 </div>
1453 </div>
1453 </div>
1454 </div>
1454
1455
1455
1456
1456 </body>
1457 </body>
1457 </html>
1458 </html>
1458
1459
1459
1460
1460 test listening address/port specified by web-conf (issue4699):
1461 test listening address/port specified by web-conf (issue4699):
1461
1462
1462 $ killdaemons.py
1463 $ killdaemons.py
1463 $ cat >> paths.conf <<EOF
1464 $ cat >> paths.conf <<EOF
1464 > [web]
1465 > [web]
1465 > address = localhost
1466 > address = localhost
1466 > port = $HGPORT1
1467 > port = $HGPORT1
1467 > EOF
1468 > EOF
1468 $ hg serve -d --pid-file=hg.pid --web-conf paths.conf \
1469 $ hg serve -d --pid-file=hg.pid --web-conf paths.conf \
1469 > -A access-paths.log -E error-paths-9.log
1470 > -A access-paths.log -E error-paths-9.log
1470 listening at http://*:$HGPORT1/ (bound to *$LOCALIP*:$HGPORT1) (glob) (?)
1471 listening at http://*:$HGPORT1/ (bound to *$LOCALIP*:$HGPORT1) (glob) (?)
1471 $ cat hg.pid >> $DAEMON_PIDS
1472 $ cat hg.pid >> $DAEMON_PIDS
1472 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1473 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1473 200 Script output follows
1474 200 Script output follows
1474
1475
1475
1476
1476
1477
1477 test --port option overrides web.port:
1478 test --port option overrides web.port:
1478
1479
1479 $ killdaemons.py
1480 $ killdaemons.py
1480 $ hg serve -p $HGPORT2 -d -v --pid-file=hg.pid --web-conf paths.conf \
1481 $ hg serve -p $HGPORT2 -d -v --pid-file=hg.pid --web-conf paths.conf \
1481 > -A access-paths.log -E error-paths-10.log
1482 > -A access-paths.log -E error-paths-10.log
1482 listening at http://*:$HGPORT2/ (bound to *$LOCALIP*:$HGPORT2) (glob) (?)
1483 listening at http://*:$HGPORT2/ (bound to *$LOCALIP*:$HGPORT2) (glob) (?)
1483 $ cat hg.pid >> $DAEMON_PIDS
1484 $ cat hg.pid >> $DAEMON_PIDS
1484 $ get-with-headers.py localhost:$HGPORT2 '?style=raw'
1485 $ get-with-headers.py localhost:$HGPORT2 '?style=raw'
1485 200 Script output follows
1486 200 Script output follows
1486
1487
1487
1488
1488
1489
1489
1490
1490 $ killdaemons.py
1491 $ killdaemons.py
1491 $ cat > collections.conf <<EOF
1492 $ cat > collections.conf <<EOF
1492 > [collections]
1493 > [collections]
1493 > $root=$root
1494 > $root=$root
1494 > EOF
1495 > EOF
1495 $ hg serve --config web.baseurl=http://hg.example.com:8080/ -p $HGPORT2 -d \
1496 $ hg serve --config web.baseurl=http://hg.example.com:8080/ -p $HGPORT2 -d \
1496 > --pid-file=hg.pid --webdir-conf collections.conf \
1497 > --pid-file=hg.pid --webdir-conf collections.conf \
1497 > -A access-collections.log -E error-collections.log
1498 > -A access-collections.log -E error-collections.log
1498 $ cat hg.pid >> $DAEMON_PIDS
1499 $ cat hg.pid >> $DAEMON_PIDS
1499
1500
1500 collections: should succeed
1501 collections: should succeed
1501
1502
1502 $ get-with-headers.py localhost:$HGPORT2 '?style=raw'
1503 $ get-with-headers.py localhost:$HGPORT2 '?style=raw'
1503 200 Script output follows
1504 200 Script output follows
1504
1505
1505
1506
1506 /a/
1507 /a/
1507 /a/.hg/patches/
1508 /a/.hg/patches/
1508 /b/
1509 /b/
1509 /c/
1510 /c/
1510 /notrepo/e/
1511 /notrepo/e/
1511 /notrepo/f/
1512 /notrepo/f/
1512
1513
1513 $ get-with-headers.py localhost:$HGPORT2 'a/file/tip/a?style=raw'
1514 $ get-with-headers.py localhost:$HGPORT2 'a/file/tip/a?style=raw'
1514 200 Script output follows
1515 200 Script output follows
1515
1516
1516 a
1517 a
1517 $ get-with-headers.py localhost:$HGPORT2 'b/file/tip/b?style=raw'
1518 $ get-with-headers.py localhost:$HGPORT2 'b/file/tip/b?style=raw'
1518 200 Script output follows
1519 200 Script output follows
1519
1520
1520 b
1521 b
1521 $ get-with-headers.py localhost:$HGPORT2 'c/file/tip/c?style=raw'
1522 $ get-with-headers.py localhost:$HGPORT2 'c/file/tip/c?style=raw'
1522 200 Script output follows
1523 200 Script output follows
1523
1524
1524 c
1525 c
1525
1526
1526 atom-log with basedir /
1527 atom-log with basedir /
1527
1528
1528 $ get-with-headers.py localhost:$HGPORT2 'a/atom-log' | grep '<link'
1529 $ get-with-headers.py localhost:$HGPORT2 'a/atom-log' | grep '<link'
1529 <link rel="self" href="http://hg.example.com:8080/a/atom-log"/>
1530 <link rel="self" href="http://hg.example.com:8080/a/atom-log"/>
1530 <link rel="alternate" href="http://hg.example.com:8080/a/"/>
1531 <link rel="alternate" href="http://hg.example.com:8080/a/"/>
1531 <link href="http://hg.example.com:8080/a/rev/8580ff50825a"/>
1532 <link href="http://hg.example.com:8080/a/rev/8580ff50825a"/>
1532
1533
1533 rss-log with basedir /
1534 rss-log with basedir /
1534
1535
1535 $ get-with-headers.py localhost:$HGPORT2 'a/rss-log' | grep '<guid'
1536 $ get-with-headers.py localhost:$HGPORT2 'a/rss-log' | grep '<guid'
1536 <guid isPermaLink="true">http://hg.example.com:8080/a/rev/8580ff50825a</guid>
1537 <guid isPermaLink="true">http://hg.example.com:8080/a/rev/8580ff50825a</guid>
1537 $ killdaemons.py
1538 $ killdaemons.py
1538 $ hg serve --config web.baseurl=http://hg.example.com:8080/foo/ -p $HGPORT2 -d \
1539 $ hg serve --config web.baseurl=http://hg.example.com:8080/foo/ -p $HGPORT2 -d \
1539 > --pid-file=hg.pid --webdir-conf collections.conf \
1540 > --pid-file=hg.pid --webdir-conf collections.conf \
1540 > -A access-collections-2.log -E error-collections-2.log
1541 > -A access-collections-2.log -E error-collections-2.log
1541 $ cat hg.pid >> $DAEMON_PIDS
1542 $ cat hg.pid >> $DAEMON_PIDS
1542
1543
1543 atom-log with basedir /foo/
1544 atom-log with basedir /foo/
1544
1545
1545 $ get-with-headers.py localhost:$HGPORT2 'a/atom-log' | grep '<link'
1546 $ get-with-headers.py localhost:$HGPORT2 'a/atom-log' | grep '<link'
1546 <link rel="self" href="http://hg.example.com:8080/foo/a/atom-log"/>
1547 <link rel="self" href="http://hg.example.com:8080/foo/a/atom-log"/>
1547 <link rel="alternate" href="http://hg.example.com:8080/foo/a/"/>
1548 <link rel="alternate" href="http://hg.example.com:8080/foo/a/"/>
1548 <link href="http://hg.example.com:8080/foo/a/rev/8580ff50825a"/>
1549 <link href="http://hg.example.com:8080/foo/a/rev/8580ff50825a"/>
1549
1550
1550 rss-log with basedir /foo/
1551 rss-log with basedir /foo/
1551
1552
1552 $ get-with-headers.py localhost:$HGPORT2 'a/rss-log' | grep '<guid'
1553 $ get-with-headers.py localhost:$HGPORT2 'a/rss-log' | grep '<guid'
1553 <guid isPermaLink="true">http://hg.example.com:8080/foo/a/rev/8580ff50825a</guid>
1554 <guid isPermaLink="true">http://hg.example.com:8080/foo/a/rev/8580ff50825a</guid>
1554
1555
1555 Path refreshing works as expected
1556 Path refreshing works as expected
1556
1557
1557 $ killdaemons.py
1558 $ killdaemons.py
1558 $ mkdir $root/refreshtest
1559 $ mkdir $root/refreshtest
1559 $ hg init $root/refreshtest/a
1560 $ hg init $root/refreshtest/a
1560 $ cat > paths.conf << EOF
1561 $ cat > paths.conf << EOF
1561 > [paths]
1562 > [paths]
1562 > / = $root/refreshtest/*
1563 > / = $root/refreshtest/*
1563 > EOF
1564 > EOF
1564 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1565 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1565 $ cat hg.pid >> $DAEMON_PIDS
1566 $ cat hg.pid >> $DAEMON_PIDS
1566
1567
1567 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1568 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1568 200 Script output follows
1569 200 Script output follows
1569
1570
1570
1571
1571 /a/
1572 /a/
1572
1573
1573
1574
1574 By default refreshing occurs every 20s and a new repo won't be listed
1575 By default refreshing occurs every 20s and a new repo won't be listed
1575 immediately.
1576 immediately.
1576
1577
1577 $ hg init $root/refreshtest/b
1578 $ hg init $root/refreshtest/b
1578 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1579 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1579 200 Script output follows
1580 200 Script output follows
1580
1581
1581
1582
1582 /a/
1583 /a/
1583
1584
1584
1585
1585 Restart the server with no refresh interval. New repo should appear
1586 Restart the server with no refresh interval. New repo should appear
1586 immediately.
1587 immediately.
1587
1588
1588 $ killdaemons.py
1589 $ killdaemons.py
1589 $ cat > paths.conf << EOF
1590 $ cat > paths.conf << EOF
1590 > [web]
1591 > [web]
1591 > refreshinterval = -1
1592 > refreshinterval = -1
1592 > [paths]
1593 > [paths]
1593 > / = $root/refreshtest/*
1594 > / = $root/refreshtest/*
1594 > EOF
1595 > EOF
1595 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1596 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1596 $ cat hg.pid >> $DAEMON_PIDS
1597 $ cat hg.pid >> $DAEMON_PIDS
1597
1598
1598 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1599 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1599 200 Script output follows
1600 200 Script output follows
1600
1601
1601
1602
1602 /a/
1603 /a/
1603 /b/
1604 /b/
1604
1605
1605
1606
1606 $ hg init $root/refreshtest/c
1607 $ hg init $root/refreshtest/c
1607 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1608 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1608 200 Script output follows
1609 200 Script output follows
1609
1610
1610
1611
1611 /a/
1612 /a/
1612 /b/
1613 /b/
1613 /c/
1614 /c/
1614
1615
1615 $ killdaemons.py
1616 $ killdaemons.py
1616 $ cat > paths.conf << EOF
1617 $ cat > paths.conf << EOF
1617 > [paths]
1618 > [paths]
1618 > /dir1/a_repo = $root/a
1619 > /dir1/a_repo = $root/a
1619 > /dir1/a_repo/b_repo = $root/b
1620 > /dir1/a_repo/b_repo = $root/b
1620 > /dir1/dir2/index = $root/b
1621 > /dir1/dir2/index = $root/b
1621 > EOF
1622 > EOF
1622 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1623 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1623 $ cat hg.pid >> $DAEMON_PIDS
1624 $ cat hg.pid >> $DAEMON_PIDS
1624
1625
1625 $ echo 'index file' > $root/a/index
1626 $ echo 'index file' > $root/a/index
1626 $ hg --cwd $root/a ci -Am 'add index file'
1627 $ hg --cwd $root/a ci -Am 'add index file'
1627 adding index
1628 adding index
1628
1629
1629 $ get-with-headers.py localhost:$HGPORT1 '' | grep 'a_repo'
1630 $ get-with-headers.py localhost:$HGPORT1 '' | grep 'a_repo'
1630 <td><a href="/dir1/a_repo/">dir1/a_repo</a></td>
1631 <td><a href="/dir1/a_repo/">dir1/a_repo</a></td>
1631 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1632 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1632 <td><a href="/dir1/a_repo/b_repo/">dir1/a_repo/b_repo</a></td>
1633 <td><a href="/dir1/a_repo/b_repo/">dir1/a_repo/b_repo</a></td>
1633 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1634 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1634
1635
1635 $ get-with-headers.py localhost:$HGPORT1 'index' | grep 'a_repo'
1636 $ get-with-headers.py localhost:$HGPORT1 'index' | grep 'a_repo'
1636 <td><a href="/dir1/a_repo/">dir1/a_repo</a></td>
1637 <td><a href="/dir1/a_repo/">dir1/a_repo</a></td>
1637 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1638 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1638 <td><a href="/dir1/a_repo/b_repo/">dir1/a_repo/b_repo</a></td>
1639 <td><a href="/dir1/a_repo/b_repo/">dir1/a_repo/b_repo</a></td>
1639 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1640 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1640
1641
1641 $ get-with-headers.py localhost:$HGPORT1 'dir1' | grep 'a_repo'
1642 $ get-with-headers.py localhost:$HGPORT1 'dir1' | grep 'a_repo'
1642 <td><a href="/dir1/a_repo/">a_repo</a></td>
1643 <td><a href="/dir1/a_repo/">a_repo</a></td>
1643 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1644 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1644 <td><a href="/dir1/a_repo/b_repo/">a_repo/b_repo</a></td>
1645 <td><a href="/dir1/a_repo/b_repo/">a_repo/b_repo</a></td>
1645 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1646 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1646
1647
1647 $ get-with-headers.py localhost:$HGPORT1 'dir1/index' | grep 'a_repo'
1648 $ get-with-headers.py localhost:$HGPORT1 'dir1/index' | grep 'a_repo'
1648 <td><a href="/dir1/a_repo/">a_repo</a></td>
1649 <td><a href="/dir1/a_repo/">a_repo</a></td>
1649 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1650 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1650 <td><a href="/dir1/a_repo/b_repo/">a_repo/b_repo</a></td>
1651 <td><a href="/dir1/a_repo/b_repo/">a_repo/b_repo</a></td>
1651 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1652 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1652
1653
1653 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo' | grep 'a_repo'
1654 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo' | grep 'a_repo'
1654 <link rel="icon" href="/dir1/a_repo/static/hgicon.png" type="image/png" />
1655 <link rel="icon" href="/dir1/a_repo/static/hgicon.png" type="image/png" />
1655 <link rel="stylesheet" href="/dir1/a_repo/static/style-paper.css" type="text/css" />
1656 <link rel="stylesheet" href="/dir1/a_repo/static/style-paper.css" type="text/css" />
1656 <script type="text/javascript" src="/dir1/a_repo/static/mercurial.js"></script>
1657 <script type="text/javascript" src="/dir1/a_repo/static/mercurial.js"></script>
1657 <title>dir1/a_repo: log</title>
1658 <title>dir1/a_repo: log</title>
1658 href="/dir1/a_repo/atom-log" title="Atom feed for dir1/a_repo" />
1659 href="/dir1/a_repo/atom-log" title="Atom feed for dir1/a_repo" />
1659 href="/dir1/a_repo/rss-log" title="RSS feed for dir1/a_repo" />
1660 href="/dir1/a_repo/rss-log" title="RSS feed for dir1/a_repo" />
1660 <img src="/dir1/a_repo/static/hglogo.png" alt="mercurial" /></a>
1661 <img src="/dir1/a_repo/static/hglogo.png" alt="mercurial" /></a>
1661 <li><a href="/dir1/a_repo/graph/tip">graph</a></li>
1662 <li><a href="/dir1/a_repo/graph/tip">graph</a></li>
1662 <li><a href="/dir1/a_repo/tags">tags</a></li>
1663 <li><a href="/dir1/a_repo/tags">tags</a></li>
1663 <li><a href="/dir1/a_repo/bookmarks">bookmarks</a></li>
1664 <li><a href="/dir1/a_repo/bookmarks">bookmarks</a></li>
1664 <li><a href="/dir1/a_repo/branches">branches</a></li>
1665 <li><a href="/dir1/a_repo/branches">branches</a></li>
1665 <li><a href="/dir1/a_repo/rev/tip">changeset</a></li>
1666 <li><a href="/dir1/a_repo/rev/tip">changeset</a></li>
1666 <li><a href="/dir1/a_repo/file/tip">browse</a></li>
1667 <li><a href="/dir1/a_repo/file/tip">browse</a></li>
1667 <li><a href="/dir1/a_repo/help">help</a></li>
1668 <li><a href="/dir1/a_repo/help">help</a></li>
1668 <a href="/dir1/a_repo/atom-log" title="subscribe to atom feed">
1669 <a href="/dir1/a_repo/atom-log" title="subscribe to atom feed">
1669 <img class="atom-logo" src="/dir1/a_repo/static/feed-icon-14x14.png" alt="atom feed" />
1670 <img class="atom-logo" src="/dir1/a_repo/static/feed-icon-14x14.png" alt="atom feed" />
1670 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/a_repo">a_repo</a> </h2>
1671 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/a_repo">a_repo</a> </h2>
1671 <form class="search" action="/dir1/a_repo/log">
1672 <form class="search" action="/dir1/a_repo/log">
1672 number or hash, or <a href="/dir1/a_repo/help/revsets">revset expression</a>.</div>
1673 number or hash, or <a href="/dir1/a_repo/help/revsets">revset expression</a>.</div>
1673 <a href="/dir1/a_repo/shortlog/tip?revcount=30">less</a>
1674 <a href="/dir1/a_repo/shortlog/tip?revcount=30">less</a>
1674 <a href="/dir1/a_repo/shortlog/tip?revcount=120">more</a>
1675 <a href="/dir1/a_repo/shortlog/tip?revcount=120">more</a>
1675 | rev 1: <a href="/dir1/a_repo/shortlog/8580ff50825a">(0)</a> <a href="/dir1/a_repo/shortlog/tip">tip</a>
1676 | rev 1: <a href="/dir1/a_repo/shortlog/8580ff50825a">(0)</a> <a href="/dir1/a_repo/shortlog/tip">tip</a>
1676 <a href="/dir1/a_repo/rev/71a89161f014">add index file</a>
1677 <a href="/dir1/a_repo/rev/71a89161f014">add index file</a>
1677 <a href="/dir1/a_repo/rev/8580ff50825a">a</a>
1678 <a href="/dir1/a_repo/rev/8580ff50825a">a</a>
1678 <a href="/dir1/a_repo/shortlog/tip?revcount=30">less</a>
1679 <a href="/dir1/a_repo/shortlog/tip?revcount=30">less</a>
1679 <a href="/dir1/a_repo/shortlog/tip?revcount=120">more</a>
1680 <a href="/dir1/a_repo/shortlog/tip?revcount=120">more</a>
1680 | rev 1: <a href="/dir1/a_repo/shortlog/8580ff50825a">(0)</a> <a href="/dir1/a_repo/shortlog/tip">tip</a>
1681 | rev 1: <a href="/dir1/a_repo/shortlog/8580ff50825a">(0)</a> <a href="/dir1/a_repo/shortlog/tip">tip</a>
1681 '/dir1/a_repo/shortlog/%next%',
1682 '/dir1/a_repo/shortlog/%next%',
1682
1683
1683 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/index' | grep 'a_repo'
1684 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/index' | grep 'a_repo'
1684 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/a_repo">a_repo</a> </h2>
1685 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/a_repo">a_repo</a> </h2>
1685 <td><a href="/dir1/a_repo/b_repo/">b_repo</a></td>
1686 <td><a href="/dir1/a_repo/b_repo/">b_repo</a></td>
1686 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1687 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1687
1688
1688 Files named 'index' are not blocked
1689 Files named 'index' are not blocked
1689
1690
1690 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/raw-file/tip/index'
1691 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/raw-file/tip/index'
1691 200 Script output follows
1692 200 Script output follows
1692
1693
1693 index file
1694 index file
1694
1695
1695 Repos named 'index' take precedence over the index file
1696 Repos named 'index' take precedence over the index file
1696
1697
1697 $ get-with-headers.py localhost:$HGPORT1 'dir1/dir2/index' | grep 'index'
1698 $ get-with-headers.py localhost:$HGPORT1 'dir1/dir2/index' | grep 'index'
1698 <link rel="icon" href="/dir1/dir2/index/static/hgicon.png" type="image/png" />
1699 <link rel="icon" href="/dir1/dir2/index/static/hgicon.png" type="image/png" />
1699 <meta name="robots" content="index, nofollow" />
1700 <meta name="robots" content="index, nofollow" />
1700 <link rel="stylesheet" href="/dir1/dir2/index/static/style-paper.css" type="text/css" />
1701 <link rel="stylesheet" href="/dir1/dir2/index/static/style-paper.css" type="text/css" />
1701 <script type="text/javascript" src="/dir1/dir2/index/static/mercurial.js"></script>
1702 <script type="text/javascript" src="/dir1/dir2/index/static/mercurial.js"></script>
1702 <title>dir1/dir2/index: log</title>
1703 <title>dir1/dir2/index: log</title>
1703 href="/dir1/dir2/index/atom-log" title="Atom feed for dir1/dir2/index" />
1704 href="/dir1/dir2/index/atom-log" title="Atom feed for dir1/dir2/index" />
1704 href="/dir1/dir2/index/rss-log" title="RSS feed for dir1/dir2/index" />
1705 href="/dir1/dir2/index/rss-log" title="RSS feed for dir1/dir2/index" />
1705 <img src="/dir1/dir2/index/static/hglogo.png" alt="mercurial" /></a>
1706 <img src="/dir1/dir2/index/static/hglogo.png" alt="mercurial" /></a>
1706 <li><a href="/dir1/dir2/index/graph/tip">graph</a></li>
1707 <li><a href="/dir1/dir2/index/graph/tip">graph</a></li>
1707 <li><a href="/dir1/dir2/index/tags">tags</a></li>
1708 <li><a href="/dir1/dir2/index/tags">tags</a></li>
1708 <li><a href="/dir1/dir2/index/bookmarks">bookmarks</a></li>
1709 <li><a href="/dir1/dir2/index/bookmarks">bookmarks</a></li>
1709 <li><a href="/dir1/dir2/index/branches">branches</a></li>
1710 <li><a href="/dir1/dir2/index/branches">branches</a></li>
1710 <li><a href="/dir1/dir2/index/rev/tip">changeset</a></li>
1711 <li><a href="/dir1/dir2/index/rev/tip">changeset</a></li>
1711 <li><a href="/dir1/dir2/index/file/tip">browse</a></li>
1712 <li><a href="/dir1/dir2/index/file/tip">browse</a></li>
1712 <li><a href="/dir1/dir2/index/help">help</a></li>
1713 <li><a href="/dir1/dir2/index/help">help</a></li>
1713 <a href="/dir1/dir2/index/atom-log" title="subscribe to atom feed">
1714 <a href="/dir1/dir2/index/atom-log" title="subscribe to atom feed">
1714 <img class="atom-logo" src="/dir1/dir2/index/static/feed-icon-14x14.png" alt="atom feed" />
1715 <img class="atom-logo" src="/dir1/dir2/index/static/feed-icon-14x14.png" alt="atom feed" />
1715 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/dir2">dir2</a> &gt; <a href="/dir1/dir2/index">index</a> </h2>
1716 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/dir2">dir2</a> &gt; <a href="/dir1/dir2/index">index</a> </h2>
1716 <form class="search" action="/dir1/dir2/index/log">
1717 <form class="search" action="/dir1/dir2/index/log">
1717 number or hash, or <a href="/dir1/dir2/index/help/revsets">revset expression</a>.</div>
1718 number or hash, or <a href="/dir1/dir2/index/help/revsets">revset expression</a>.</div>
1718 <a href="/dir1/dir2/index/shortlog/tip?revcount=30">less</a>
1719 <a href="/dir1/dir2/index/shortlog/tip?revcount=30">less</a>
1719 <a href="/dir1/dir2/index/shortlog/tip?revcount=120">more</a>
1720 <a href="/dir1/dir2/index/shortlog/tip?revcount=120">more</a>
1720 | rev 0: <a href="/dir1/dir2/index/shortlog/39505516671b">(0)</a> <a href="/dir1/dir2/index/shortlog/tip">tip</a>
1721 | rev 0: <a href="/dir1/dir2/index/shortlog/39505516671b">(0)</a> <a href="/dir1/dir2/index/shortlog/tip">tip</a>
1721 <a href="/dir1/dir2/index/rev/39505516671b">b</a>
1722 <a href="/dir1/dir2/index/rev/39505516671b">b</a>
1722 <a href="/dir1/dir2/index/shortlog/tip?revcount=30">less</a>
1723 <a href="/dir1/dir2/index/shortlog/tip?revcount=30">less</a>
1723 <a href="/dir1/dir2/index/shortlog/tip?revcount=120">more</a>
1724 <a href="/dir1/dir2/index/shortlog/tip?revcount=120">more</a>
1724 | rev 0: <a href="/dir1/dir2/index/shortlog/39505516671b">(0)</a> <a href="/dir1/dir2/index/shortlog/tip">tip</a>
1725 | rev 0: <a href="/dir1/dir2/index/shortlog/39505516671b">(0)</a> <a href="/dir1/dir2/index/shortlog/tip">tip</a>
1725 '/dir1/dir2/index/shortlog/%next%',
1726 '/dir1/dir2/index/shortlog/%next%',
1726
1727
1727 $ killdaemons.py
1728 $ killdaemons.py
1728
1729
1729 $ cat > paths.conf << EOF
1730 $ cat > paths.conf << EOF
1730 > [paths]
1731 > [paths]
1731 > / = $root/a
1732 > / = $root/a
1732 > EOF
1733 > EOF
1733 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1734 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1734 $ cat hg.pid >> $DAEMON_PIDS
1735 $ cat hg.pid >> $DAEMON_PIDS
1735
1736
1736 $ hg id http://localhost:$HGPORT1
1737 $ hg id http://localhost:$HGPORT1
1737 71a89161f014
1738 71a89161f014
1738
1739
1739 $ get-with-headers.py localhost:$HGPORT1 '' | grep 'index'
1740 $ get-with-headers.py localhost:$HGPORT1 '' | grep 'index'
1740 <meta name="robots" content="index, nofollow" />
1741 <meta name="robots" content="index, nofollow" />
1741 <a href="/rev/71a89161f014">add index file</a>
1742 <a href="/rev/71a89161f014">add index file</a>
1742
1743
1743 $ killdaemons.py
1744 $ killdaemons.py
1744
1745
1745 paths errors 1
1746 paths errors 1
1746
1747
1747 $ cat error-paths-1.log
1748 $ cat error-paths-1.log
1748
1749
1749 paths errors 2
1750 paths errors 2
1750
1751
1751 $ cat error-paths-2.log
1752 $ cat error-paths-2.log
1752
1753
1753 paths errors 3
1754 paths errors 3
1754
1755
1755 $ cat error-paths-3.log
1756 $ cat error-paths-3.log
1756
1757
1757 paths errors 4
1758 paths errors 4
1758
1759
1759 $ cat error-paths-4.log
1760 $ cat error-paths-4.log
1760
1761
1761 paths errors 5
1762 paths errors 5
1762
1763
1763 $ cat error-paths-5.log
1764 $ cat error-paths-5.log
1764
1765
1765 paths errors 6
1766 paths errors 6
1766
1767
1767 $ cat error-paths-6.log
1768 $ cat error-paths-6.log
1768
1769
1769 paths errors 7
1770 paths errors 7
1770
1771
1771 $ cat error-paths-7.log
1772 $ cat error-paths-7.log
1772
1773
1773 paths errors 8
1774 paths errors 8
1774
1775
1775 $ cat error-paths-8.log
1776 $ cat error-paths-8.log
1776
1777
1777 paths errors 9
1778 paths errors 9
1778
1779
1779 $ cat error-paths-9.log
1780 $ cat error-paths-9.log
1780
1781
1781 paths errors 10
1782 paths errors 10
1782
1783
1783 $ cat error-paths-10.log
1784 $ cat error-paths-10.log
1784
1785
1785 collections errors
1786 collections errors
1786
1787
1787 $ cat error-collections.log
1788 $ cat error-collections.log
1788
1789
1789 collections errors 2
1790 collections errors 2
1790
1791
1791 $ cat error-collections-2.log
1792 $ cat error-collections-2.log
General Comments 0
You need to be logged in to leave comments. Login now