##// END OF EJS Templates
hgweb: map Abort to 403 error to report inaccessible path for example...
Yuya Nishihara -
r39506:17ca967e default
parent child Browse files
Show More
@@ -1,471 +1,475 b''
1 1 # hgweb/hgweb_mod.py - Web interface for a repository.
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from __future__ import absolute_import
10 10
11 11 import contextlib
12 12 import os
13 13
14 14 from .common import (
15 15 ErrorResponse,
16 16 HTTP_BAD_REQUEST,
17 17 cspvalues,
18 18 permhooks,
19 19 statusmessage,
20 20 )
21 21
22 22 from .. import (
23 23 encoding,
24 24 error,
25 25 formatter,
26 26 hg,
27 27 hook,
28 28 profiling,
29 29 pycompat,
30 30 registrar,
31 31 repoview,
32 32 templatefilters,
33 33 templater,
34 34 templateutil,
35 35 ui as uimod,
36 36 util,
37 37 wireprotoserver,
38 38 )
39 39
40 40 from . import (
41 41 request as requestmod,
42 42 webcommands,
43 43 webutil,
44 44 wsgicgi,
45 45 )
46 46
47 47 def getstyle(req, configfn, templatepath):
48 48 styles = (
49 49 req.qsparams.get('style', None),
50 50 configfn('web', 'style'),
51 51 'paper',
52 52 )
53 53 return styles, templater.stylemap(styles, templatepath)
54 54
55 55 def makebreadcrumb(url, prefix=''):
56 56 '''Return a 'URL breadcrumb' list
57 57
58 58 A 'URL breadcrumb' is a list of URL-name pairs,
59 59 corresponding to each of the path items on a URL.
60 60 This can be used to create path navigation entries.
61 61 '''
62 62 if url.endswith('/'):
63 63 url = url[:-1]
64 64 if prefix:
65 65 url = '/' + prefix + url
66 66 relpath = url
67 67 if relpath.startswith('/'):
68 68 relpath = relpath[1:]
69 69
70 70 breadcrumb = []
71 71 urlel = url
72 72 pathitems = [''] + relpath.split('/')
73 73 for pathel in reversed(pathitems):
74 74 if not pathel or not urlel:
75 75 break
76 76 breadcrumb.append({'url': urlel, 'name': pathel})
77 77 urlel = os.path.dirname(urlel)
78 78 return templateutil.mappinglist(reversed(breadcrumb))
79 79
80 80 class requestcontext(object):
81 81 """Holds state/context for an individual request.
82 82
83 83 Servers can be multi-threaded. Holding state on the WSGI application
84 84 is prone to race conditions. Instances of this class exist to hold
85 85 mutable and race-free state for requests.
86 86 """
87 87 def __init__(self, app, repo, req, res):
88 88 self.repo = repo
89 89 self.reponame = app.reponame
90 90 self.req = req
91 91 self.res = res
92 92
93 93 self.maxchanges = self.configint('web', 'maxchanges')
94 94 self.stripecount = self.configint('web', 'stripes')
95 95 self.maxshortchanges = self.configint('web', 'maxshortchanges')
96 96 self.maxfiles = self.configint('web', 'maxfiles')
97 97 self.allowpull = self.configbool('web', 'allow-pull')
98 98
99 99 # we use untrusted=False to prevent a repo owner from using
100 100 # web.templates in .hg/hgrc to get access to any file readable
101 101 # by the user running the CGI script
102 102 self.templatepath = self.config('web', 'templates', untrusted=False)
103 103
104 104 # This object is more expensive to build than simple config values.
105 105 # It is shared across requests. The app will replace the object
106 106 # if it is updated. Since this is a reference and nothing should
107 107 # modify the underlying object, it should be constant for the lifetime
108 108 # of the request.
109 109 self.websubtable = app.websubtable
110 110
111 111 self.csp, self.nonce = cspvalues(self.repo.ui)
112 112
113 113 # Trust the settings from the .hg/hgrc files by default.
114 114 def config(self, section, name, default=uimod._unset, untrusted=True):
115 115 return self.repo.ui.config(section, name, default,
116 116 untrusted=untrusted)
117 117
118 118 def configbool(self, section, name, default=uimod._unset, untrusted=True):
119 119 return self.repo.ui.configbool(section, name, default,
120 120 untrusted=untrusted)
121 121
122 122 def configint(self, section, name, default=uimod._unset, untrusted=True):
123 123 return self.repo.ui.configint(section, name, default,
124 124 untrusted=untrusted)
125 125
126 126 def configlist(self, section, name, default=uimod._unset, untrusted=True):
127 127 return self.repo.ui.configlist(section, name, default,
128 128 untrusted=untrusted)
129 129
130 130 def archivelist(self, nodeid):
131 131 return webutil.archivelist(self.repo.ui, nodeid)
132 132
133 133 def templater(self, req):
134 134 # determine scheme, port and server name
135 135 # this is needed to create absolute urls
136 136 logourl = self.config('web', 'logourl')
137 137 logoimg = self.config('web', 'logoimg')
138 138 staticurl = (self.config('web', 'staticurl')
139 139 or req.apppath.rstrip('/') + '/static/')
140 140 if not staticurl.endswith('/'):
141 141 staticurl += '/'
142 142
143 143 # figure out which style to use
144 144
145 145 vars = {}
146 146 styles, (style, mapfile) = getstyle(req, self.config,
147 147 self.templatepath)
148 148 if style == styles[0]:
149 149 vars['style'] = style
150 150
151 151 sessionvars = webutil.sessionvars(vars, '?')
152 152
153 153 if not self.reponame:
154 154 self.reponame = (self.config('web', 'name', '')
155 155 or req.reponame
156 156 or req.apppath
157 157 or self.repo.root)
158 158
159 159 filters = {}
160 160 templatefilter = registrar.templatefilter(filters)
161 161 @templatefilter('websub', intype=bytes)
162 162 def websubfilter(text):
163 163 return templatefilters.websub(text, self.websubtable)
164 164
165 165 # create the templater
166 166 # TODO: export all keywords: defaults = templatekw.keywords.copy()
167 167 defaults = {
168 168 'url': req.apppath + '/',
169 169 'logourl': logourl,
170 170 'logoimg': logoimg,
171 171 'staticurl': staticurl,
172 172 'urlbase': req.advertisedbaseurl,
173 173 'repo': self.reponame,
174 174 'encoding': encoding.encoding,
175 175 'sessionvars': sessionvars,
176 176 'pathdef': makebreadcrumb(req.apppath),
177 177 'style': style,
178 178 'nonce': self.nonce,
179 179 }
180 180 templatekeyword = registrar.templatekeyword(defaults)
181 181 @templatekeyword('motd', requires=())
182 182 def motd(context, mapping):
183 183 yield self.config('web', 'motd')
184 184
185 185 tres = formatter.templateresources(self.repo.ui, self.repo)
186 186 tmpl = templater.templater.frommapfile(mapfile,
187 187 filters=filters,
188 188 defaults=defaults,
189 189 resources=tres)
190 190 return tmpl
191 191
192 192 def sendtemplate(self, name, **kwargs):
193 193 """Helper function to send a response generated from a template."""
194 194 kwargs = pycompat.byteskwargs(kwargs)
195 195 self.res.setbodygen(self.tmpl.generate(name, kwargs))
196 196 return self.res.sendresponse()
197 197
198 198 class hgweb(object):
199 199 """HTTP server for individual repositories.
200 200
201 201 Instances of this class serve HTTP responses for a particular
202 202 repository.
203 203
204 204 Instances are typically used as WSGI applications.
205 205
206 206 Some servers are multi-threaded. On these servers, there may
207 207 be multiple active threads inside __call__.
208 208 """
209 209 def __init__(self, repo, name=None, baseui=None):
210 210 if isinstance(repo, bytes):
211 211 if baseui:
212 212 u = baseui.copy()
213 213 else:
214 214 u = uimod.ui.load()
215 215 r = hg.repository(u, repo)
216 216 else:
217 217 # we trust caller to give us a private copy
218 218 r = repo
219 219
220 220 r.ui.setconfig('ui', 'report_untrusted', 'off', 'hgweb')
221 221 r.baseui.setconfig('ui', 'report_untrusted', 'off', 'hgweb')
222 222 r.ui.setconfig('ui', 'nontty', 'true', 'hgweb')
223 223 r.baseui.setconfig('ui', 'nontty', 'true', 'hgweb')
224 224 # resolve file patterns relative to repo root
225 225 r.ui.setconfig('ui', 'forcecwd', r.root, 'hgweb')
226 226 r.baseui.setconfig('ui', 'forcecwd', r.root, 'hgweb')
227 227 # it's unlikely that we can replace signal handlers in WSGI server,
228 228 # and mod_wsgi issues a big warning. a plain hgweb process (with no
229 229 # threading) could replace signal handlers, but we don't bother
230 230 # conditionally enabling it.
231 231 r.ui.setconfig('ui', 'signal-safe-lock', 'false', 'hgweb')
232 232 r.baseui.setconfig('ui', 'signal-safe-lock', 'false', 'hgweb')
233 233 # displaying bundling progress bar while serving feel wrong and may
234 234 # break some wsgi implementation.
235 235 r.ui.setconfig('progress', 'disable', 'true', 'hgweb')
236 236 r.baseui.setconfig('progress', 'disable', 'true', 'hgweb')
237 237 self._repos = [hg.cachedlocalrepo(self._webifyrepo(r))]
238 238 self._lastrepo = self._repos[0]
239 239 hook.redirect(True)
240 240 self.reponame = name
241 241
242 242 def _webifyrepo(self, repo):
243 243 repo = getwebview(repo)
244 244 self.websubtable = webutil.getwebsubs(repo)
245 245 return repo
246 246
247 247 @contextlib.contextmanager
248 248 def _obtainrepo(self):
249 249 """Obtain a repo unique to the caller.
250 250
251 251 Internally we maintain a stack of cachedlocalrepo instances
252 252 to be handed out. If one is available, we pop it and return it,
253 253 ensuring it is up to date in the process. If one is not available,
254 254 we clone the most recently used repo instance and return it.
255 255
256 256 It is currently possible for the stack to grow without bounds
257 257 if the server allows infinite threads. However, servers should
258 258 have a thread limit, thus establishing our limit.
259 259 """
260 260 if self._repos:
261 261 cached = self._repos.pop()
262 262 r, created = cached.fetch()
263 263 else:
264 264 cached = self._lastrepo.copy()
265 265 r, created = cached.fetch()
266 266 if created:
267 267 r = self._webifyrepo(r)
268 268
269 269 self._lastrepo = cached
270 270 self.mtime = cached.mtime
271 271 try:
272 272 yield r
273 273 finally:
274 274 self._repos.append(cached)
275 275
276 276 def run(self):
277 277 """Start a server from CGI environment.
278 278
279 279 Modern servers should be using WSGI and should avoid this
280 280 method, if possible.
281 281 """
282 282 if not encoding.environ.get('GATEWAY_INTERFACE',
283 283 '').startswith("CGI/1."):
284 284 raise RuntimeError("This function is only intended to be "
285 285 "called while running as a CGI script.")
286 286 wsgicgi.launch(self)
287 287
288 288 def __call__(self, env, respond):
289 289 """Run the WSGI application.
290 290
291 291 This may be called by multiple threads.
292 292 """
293 293 req = requestmod.parserequestfromenv(env)
294 294 res = requestmod.wsgiresponse(req, respond)
295 295
296 296 return self.run_wsgi(req, res)
297 297
298 298 def run_wsgi(self, req, res):
299 299 """Internal method to run the WSGI application.
300 300
301 301 This is typically only called by Mercurial. External consumers
302 302 should be using instances of this class as the WSGI application.
303 303 """
304 304 with self._obtainrepo() as repo:
305 305 profile = repo.ui.configbool('profiling', 'enabled')
306 306 with profiling.profile(repo.ui, enabled=profile):
307 307 for r in self._runwsgi(req, res, repo):
308 308 yield r
309 309
310 310 def _runwsgi(self, req, res, repo):
311 311 rctx = requestcontext(self, repo, req, res)
312 312
313 313 # This state is global across all threads.
314 314 encoding.encoding = rctx.config('web', 'encoding')
315 315 rctx.repo.ui.environ = req.rawenv
316 316
317 317 if rctx.csp:
318 318 # hgwebdir may have added CSP header. Since we generate our own,
319 319 # replace it.
320 320 res.headers['Content-Security-Policy'] = rctx.csp
321 321
322 322 # /api/* is reserved for various API implementations. Dispatch
323 323 # accordingly. But URL paths can conflict with subrepos and virtual
324 324 # repos in hgwebdir. So until we have a workaround for this, only
325 325 # expose the URLs if the feature is enabled.
326 326 apienabled = rctx.repo.ui.configbool('experimental', 'web.apiserver')
327 327 if apienabled and req.dispatchparts and req.dispatchparts[0] == b'api':
328 328 wireprotoserver.handlewsgiapirequest(rctx, req, res,
329 329 self.check_perm)
330 330 return res.sendresponse()
331 331
332 332 handled = wireprotoserver.handlewsgirequest(
333 333 rctx, req, res, self.check_perm)
334 334 if handled:
335 335 return res.sendresponse()
336 336
337 337 # Old implementations of hgweb supported dispatching the request via
338 338 # the initial query string parameter instead of using PATH_INFO.
339 339 # If PATH_INFO is present (signaled by ``req.dispatchpath`` having
340 340 # a value), we use it. Otherwise fall back to the query string.
341 341 if req.dispatchpath is not None:
342 342 query = req.dispatchpath
343 343 else:
344 344 query = req.querystring.partition('&')[0].partition(';')[0]
345 345
346 346 # translate user-visible url structure to internal structure
347 347
348 348 args = query.split('/', 2)
349 349 if 'cmd' not in req.qsparams and args and args[0]:
350 350 cmd = args.pop(0)
351 351 style = cmd.rfind('-')
352 352 if style != -1:
353 353 req.qsparams['style'] = cmd[:style]
354 354 cmd = cmd[style + 1:]
355 355
356 356 # avoid accepting e.g. style parameter as command
357 357 if util.safehasattr(webcommands, cmd):
358 358 req.qsparams['cmd'] = cmd
359 359
360 360 if cmd == 'static':
361 361 req.qsparams['file'] = '/'.join(args)
362 362 else:
363 363 if args and args[0]:
364 364 node = args.pop(0).replace('%2F', '/')
365 365 req.qsparams['node'] = node
366 366 if args:
367 367 if 'file' in req.qsparams:
368 368 del req.qsparams['file']
369 369 for a in args:
370 370 req.qsparams.add('file', a)
371 371
372 372 ua = req.headers.get('User-Agent', '')
373 373 if cmd == 'rev' and 'mercurial' in ua:
374 374 req.qsparams['style'] = 'raw'
375 375
376 376 if cmd == 'archive':
377 377 fn = req.qsparams['node']
378 378 for type_, spec in webutil.archivespecs.iteritems():
379 379 ext = spec[2]
380 380 if fn.endswith(ext):
381 381 req.qsparams['node'] = fn[:-len(ext)]
382 382 req.qsparams['type'] = type_
383 383 else:
384 384 cmd = req.qsparams.get('cmd', '')
385 385
386 386 # process the web interface request
387 387
388 388 try:
389 389 rctx.tmpl = rctx.templater(req)
390 390 ctype = rctx.tmpl.render('mimetype',
391 391 {'encoding': encoding.encoding})
392 392
393 393 # check read permissions non-static content
394 394 if cmd != 'static':
395 395 self.check_perm(rctx, req, None)
396 396
397 397 if cmd == '':
398 398 req.qsparams['cmd'] = rctx.tmpl.render('default', {})
399 399 cmd = req.qsparams['cmd']
400 400
401 401 # Don't enable caching if using a CSP nonce because then it wouldn't
402 402 # be a nonce.
403 403 if rctx.configbool('web', 'cache') and not rctx.nonce:
404 404 tag = 'W/"%d"' % self.mtime
405 405 if req.headers.get('If-None-Match') == tag:
406 406 res.status = '304 Not Modified'
407 407 # Content-Type may be defined globally. It isn't valid on a
408 408 # 304, so discard it.
409 409 try:
410 410 del res.headers[b'Content-Type']
411 411 except KeyError:
412 412 pass
413 413 # Response body not allowed on 304.
414 414 res.setbodybytes('')
415 415 return res.sendresponse()
416 416
417 417 res.headers['ETag'] = tag
418 418
419 419 if cmd not in webcommands.__all__:
420 420 msg = 'no such method: %s' % cmd
421 421 raise ErrorResponse(HTTP_BAD_REQUEST, msg)
422 422 else:
423 423 # Set some globals appropriate for web handlers. Commands can
424 424 # override easily enough.
425 425 res.status = '200 Script output follows'
426 426 res.headers['Content-Type'] = ctype
427 427 return getattr(webcommands, cmd)(rctx)
428 428
429 429 except (error.LookupError, error.RepoLookupError) as err:
430 430 msg = pycompat.bytestr(err)
431 431 if (util.safehasattr(err, 'name') and
432 432 not isinstance(err, error.ManifestLookupError)):
433 433 msg = 'revision not found: %s' % err.name
434 434
435 435 res.status = '404 Not Found'
436 436 res.headers['Content-Type'] = ctype
437 437 return rctx.sendtemplate('error', error=msg)
438 438 except (error.RepoError, error.RevlogError) as e:
439 439 res.status = '500 Internal Server Error'
440 440 res.headers['Content-Type'] = ctype
441 441 return rctx.sendtemplate('error', error=pycompat.bytestr(e))
442 except error.Abort as e:
443 res.status = '403 Forbidden'
444 res.headers['Content-Type'] = ctype
445 return rctx.sendtemplate('error', error=pycompat.bytestr(e))
442 446 except ErrorResponse as e:
443 447 for k, v in e.headers:
444 448 res.headers[k] = v
445 449 res.status = statusmessage(e.code, pycompat.bytestr(e))
446 450 res.headers['Content-Type'] = ctype
447 451 return rctx.sendtemplate('error', error=pycompat.bytestr(e))
448 452
449 453 def check_perm(self, rctx, req, op):
450 454 for permhook in permhooks:
451 455 permhook(rctx, req, op)
452 456
453 457 def getwebview(repo):
454 458 """The 'web.view' config controls changeset filter to hgweb. Possible
455 459 values are ``served``, ``visible`` and ``all``. Default is ``served``.
456 460 The ``served`` filter only shows changesets that can be pulled from the
457 461 hgweb instance. The``visible`` filter includes secret changesets but
458 462 still excludes "hidden" one.
459 463
460 464 See the repoview module for details.
461 465
462 466 The option has been around undocumented since Mercurial 2.5, but no
463 467 user ever asked about it. So we better keep it undocumented for now."""
464 468 # experimental config: web.view
465 469 viewconfig = repo.ui.config('web', 'view', untrusted=True)
466 470 if viewconfig == 'all':
467 471 return repo.unfiltered()
468 472 elif viewconfig in repoview.filtertable:
469 473 return repo.filtered(viewconfig)
470 474 else:
471 475 return repo.filtered('served')
@@ -1,1745 +1,1791 b''
1 1 #require serve
2 2
3 3 hide outer repo and work in dir without '.hg'
4 4 $ hg init
5 5 $ mkdir dir
6 6 $ cd dir
7 7
8 8 Tests some basic hgwebdir functionality. Tests setting up paths and
9 9 collection, different forms of 404s and the subdirectory support.
10 10
11 11 $ mkdir webdir
12 12 $ cd webdir
13 13 $ hg init a
14 14 $ echo a > a/a
15 15 $ hg --cwd a ci -Ama -d'1 0'
16 16 adding a
17 17
18 18 create a mercurial queue repository
19 19
20 20 $ hg --cwd a qinit --config extensions.hgext.mq= -c
21 21 $ hg init b
22 22 $ echo b > b/b
23 23 $ hg --cwd b ci -Amb -d'2 0'
24 24 adding b
25 25
26 26 create a nested repository
27 27
28 28 $ cd b
29 29 $ hg init d
30 30 $ echo d > d/d
31 31 $ hg --cwd d ci -Amd -d'3 0'
32 32 adding d
33 33 $ cd ..
34 34 $ hg init c
35 35 $ echo c > c/c
36 36 $ hg --cwd c ci -Amc -d'3 0'
37 37 adding c
38 38
39 39 create a subdirectory containing repositories and subrepositories
40 40
41 41 $ mkdir notrepo
42 42 $ cd notrepo
43 43 $ hg init e
44 44 $ echo e > e/e
45 45 $ hg --cwd e ci -Ame -d'4 0'
46 46 adding e
47 47 $ hg init e/e2
48 48 $ echo e2 > e/e2/e2
49 49 $ hg --cwd e/e2 ci -Ame2 -d '4 0'
50 50 adding e2
51 51 $ hg init f
52 52 $ echo f > f/f
53 53 $ hg --cwd f ci -Amf -d'4 0'
54 54 adding f
55 55 $ hg init f/f2
56 56 $ echo f2 > f/f2/f2
57 57 $ hg --cwd f/f2 ci -Amf2 -d '4 0'
58 58 adding f2
59 59 $ echo 'f2 = f2' > f/.hgsub
60 60 $ hg -R f ci -Am 'add subrepo' -d'4 0'
61 61 adding .hgsub
62 62 $ cat >> f/.hg/hgrc << EOF
63 63 > [web]
64 64 > name = fancy name for repo f
65 65 > labels = foo, bar
66 66 > EOF
67 67 $ cd ..
68 68
69 add file under the directory which could be shadowed by another repository
70
71 $ mkdir notrepo/f/f3
72 $ echo f3/file > notrepo/f/f3/file
73 $ hg -R notrepo/f ci -Am 'f3/file'
74 adding f3/file
75 $ hg -R notrepo/f update null
76 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
77 $ hg init notrepo/f/f3
78 $ cat <<'EOF' > notrepo/f/f3/.hg/hgrc
79 > [web]
80 > hidden = true
81 > EOF
82
69 83 create repository without .hg/store
70 84
71 85 $ hg init nostore
72 86 $ rm -R nostore/.hg/store
73 87 $ root=`pwd`
74 88 $ cd ..
75 89
76 90 serve
77 91 $ cat > paths.conf <<EOF
78 92 > [paths]
79 93 > a=$root/a
80 94 > b=$root/b
81 95 > EOF
82 96 $ hg serve -p $HGPORT -d --pid-file=hg.pid --webdir-conf paths.conf \
83 97 > -A access-paths.log -E error-paths-1.log
84 98 $ cat hg.pid >> $DAEMON_PIDS
85 99
86 100 should give a 404 - file does not exist
87 101
88 102 $ get-with-headers.py localhost:$HGPORT 'a/file/tip/bork?style=raw'
89 103 404 Not Found
90 104
91 105
92 106 error: bork@8580ff50825a: not found in manifest
93 107 [1]
94 108
95 109 should succeed
96 110
97 111 $ get-with-headers.py localhost:$HGPORT '?style=raw'
98 112 200 Script output follows
99 113
100 114
101 115 /a/
102 116 /b/
103 117
104 118 $ get-with-headers.py localhost:$HGPORT '?style=json'
105 119 200 Script output follows
106 120
107 121 {
108 122 "entries": [{
109 123 "name": "a",
110 124 "description": "unknown",
111 125 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
112 126 "lastchange": [*, *], (glob)
113 127 "labels": []
114 128 }, {
115 129 "name": "b",
116 130 "description": "unknown",
117 131 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
118 132 "lastchange": [*, *], (glob)
119 133 "labels": []
120 134 }]
121 135 } (no-eol)
122 136
123 137 $ get-with-headers.py localhost:$HGPORT 'a/file/tip/a?style=raw'
124 138 200 Script output follows
125 139
126 140 a
127 141 $ get-with-headers.py localhost:$HGPORT 'b/file/tip/b?style=raw'
128 142 200 Script output follows
129 143
130 144 b
131 145
132 146 should give a 404 - repo is not published
133 147
134 148 $ get-with-headers.py localhost:$HGPORT 'c/file/tip/c?style=raw'
135 149 404 Not Found
136 150
137 151
138 152 error: repository c/file/tip/c not found
139 153 [1]
140 154
141 155 atom-log without basedir
142 156
143 157 $ get-with-headers.py localhost:$HGPORT 'a/atom-log' | grep '<link'
144 158 <link rel="self" href="http://*:$HGPORT/a/atom-log"/> (glob)
145 159 <link rel="alternate" href="http://*:$HGPORT/a/"/> (glob)
146 160 <link href="http://*:$HGPORT/a/rev/8580ff50825a"/> (glob)
147 161
148 162 rss-log without basedir
149 163
150 164 $ get-with-headers.py localhost:$HGPORT 'a/rss-log' | grep '<guid'
151 165 <guid isPermaLink="true">http://*:$HGPORT/a/rev/8580ff50825a</guid> (glob)
152 166 $ cat > paths.conf <<EOF
153 167 > [paths]
154 168 > t/a/=$root/a
155 169 > b=$root/b
156 170 > coll=$root/*
157 171 > rcoll=$root/**
158 172 > star=*
159 173 > starstar=**
160 174 > astar=webdir/a/*
161 175 > EOF
162 176 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
163 177 > -A access-paths.log -E error-paths-2.log
164 178 $ cat hg.pid >> $DAEMON_PIDS
165 179
166 180 should succeed, slashy names
167 181
168 182 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
169 183 200 Script output follows
170 184
171 185
172 186 /t/a/
173 187 /b/
174 188 /coll/a/
175 189 /coll/a/.hg/patches/
176 190 /coll/b/
177 191 /coll/c/
178 192 /coll/notrepo/e/
179 193 /coll/notrepo/f/
180 194 /rcoll/a/
181 195 /rcoll/a/.hg/patches/
182 196 /rcoll/b/
183 197 /rcoll/b/d/
184 198 /rcoll/c/
185 199 /rcoll/notrepo/e/
186 200 /rcoll/notrepo/e/e2/
187 201 /rcoll/notrepo/f/
188 202 /rcoll/notrepo/f/f2/
189 203 /star/webdir/a/
190 204 /star/webdir/a/.hg/patches/
191 205 /star/webdir/b/
192 206 /star/webdir/c/
193 207 /star/webdir/notrepo/e/
194 208 /star/webdir/notrepo/f/
195 209 /starstar/webdir/a/
196 210 /starstar/webdir/a/.hg/patches/
197 211 /starstar/webdir/b/
198 212 /starstar/webdir/b/d/
199 213 /starstar/webdir/c/
200 214 /starstar/webdir/notrepo/e/
201 215 /starstar/webdir/notrepo/e/e2/
202 216 /starstar/webdir/notrepo/f/
203 217 /starstar/webdir/notrepo/f/f2/
204 218 /astar/
205 219 /astar/.hg/patches/
206 220
207 221
208 222 $ get-with-headers.py localhost:$HGPORT1 '?style=json'
209 223 200 Script output follows
210 224
211 225 {
212 226 "entries": [{
213 227 "name": "t/a",
214 228 "description": "unknown",
215 229 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
216 230 "lastchange": [*, *], (glob)
217 231 "labels": []
218 232 }, {
219 233 "name": "b",
220 234 "description": "unknown",
221 235 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
222 236 "lastchange": [*, *], (glob)
223 237 "labels": []
224 238 }, {
225 239 "name": "coll/a",
226 240 "description": "unknown",
227 241 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
228 242 "lastchange": [*, *], (glob)
229 243 "labels": []
230 244 }, {
231 245 "name": "coll/a/.hg/patches",
232 246 "description": "unknown",
233 247 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
234 248 "lastchange": [*, *], (glob)
235 249 "labels": []
236 250 }, {
237 251 "name": "coll/b",
238 252 "description": "unknown",
239 253 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
240 254 "lastchange": [*, *], (glob)
241 255 "labels": []
242 256 }, {
243 257 "name": "coll/c",
244 258 "description": "unknown",
245 259 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
246 260 "lastchange": [*, *], (glob)
247 261 "labels": []
248 262 }, {
249 263 "name": "coll/notrepo/e",
250 264 "description": "unknown",
251 265 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
252 266 "lastchange": [*, *], (glob)
253 267 "labels": []
254 268 }, {
255 269 "name": "fancy name for repo f",
256 270 "description": "unknown",
257 271 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
258 272 "lastchange": [*, *], (glob)
259 273 "labels": ["foo", "bar"]
260 274 }, {
261 275 "name": "rcoll/a",
262 276 "description": "unknown",
263 277 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
264 278 "lastchange": [*, *], (glob)
265 279 "labels": []
266 280 }, {
267 281 "name": "rcoll/a/.hg/patches",
268 282 "description": "unknown",
269 283 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
270 284 "lastchange": [*, *], (glob)
271 285 "labels": []
272 286 }, {
273 287 "name": "rcoll/b",
274 288 "description": "unknown",
275 289 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
276 290 "lastchange": [*, *], (glob)
277 291 "labels": []
278 292 }, {
279 293 "name": "rcoll/b/d",
280 294 "description": "unknown",
281 295 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
282 296 "lastchange": [*, *], (glob)
283 297 "labels": []
284 298 }, {
285 299 "name": "rcoll/c",
286 300 "description": "unknown",
287 301 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
288 302 "lastchange": [*, *], (glob)
289 303 "labels": []
290 304 }, {
291 305 "name": "rcoll/notrepo/e",
292 306 "description": "unknown",
293 307 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
294 308 "lastchange": [*, *], (glob)
295 309 "labels": []
296 310 }, {
297 311 "name": "rcoll/notrepo/e/e2",
298 312 "description": "unknown",
299 313 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
300 314 "lastchange": [*, *], (glob)
301 315 "labels": []
302 316 }, {
303 317 "name": "fancy name for repo f",
304 318 "description": "unknown",
305 319 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
306 320 "lastchange": [*, *], (glob)
307 321 "labels": ["foo", "bar"]
308 322 }, {
309 323 "name": "rcoll/notrepo/f/f2",
310 324 "description": "unknown",
311 325 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
312 326 "lastchange": [*, *], (glob)
313 327 "labels": []
314 328 }, {
315 329 "name": "star/webdir/a",
316 330 "description": "unknown",
317 331 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
318 332 "lastchange": [*, *], (glob)
319 333 "labels": []
320 334 }, {
321 335 "name": "star/webdir/a/.hg/patches",
322 336 "description": "unknown",
323 337 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
324 338 "lastchange": [*, *], (glob)
325 339 "labels": []
326 340 }, {
327 341 "name": "star/webdir/b",
328 342 "description": "unknown",
329 343 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
330 344 "lastchange": [*, *], (glob)
331 345 "labels": []
332 346 }, {
333 347 "name": "star/webdir/c",
334 348 "description": "unknown",
335 349 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
336 350 "lastchange": [*, *], (glob)
337 351 "labels": []
338 352 }, {
339 353 "name": "star/webdir/notrepo/e",
340 354 "description": "unknown",
341 355 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
342 356 "lastchange": [*, *], (glob)
343 357 "labels": []
344 358 }, {
345 359 "name": "fancy name for repo f",
346 360 "description": "unknown",
347 361 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
348 362 "lastchange": [*, *], (glob)
349 363 "labels": ["foo", "bar"]
350 364 }, {
351 365 "name": "starstar/webdir/a",
352 366 "description": "unknown",
353 367 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
354 368 "lastchange": [*, *], (glob)
355 369 "labels": []
356 370 }, {
357 371 "name": "starstar/webdir/a/.hg/patches",
358 372 "description": "unknown",
359 373 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
360 374 "lastchange": [*, *], (glob)
361 375 "labels": []
362 376 }, {
363 377 "name": "starstar/webdir/b",
364 378 "description": "unknown",
365 379 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
366 380 "lastchange": [*, *], (glob)
367 381 "labels": []
368 382 }, {
369 383 "name": "starstar/webdir/b/d",
370 384 "description": "unknown",
371 385 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
372 386 "lastchange": [*, *], (glob)
373 387 "labels": []
374 388 }, {
375 389 "name": "starstar/webdir/c",
376 390 "description": "unknown",
377 391 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
378 392 "lastchange": [*, *], (glob)
379 393 "labels": []
380 394 }, {
381 395 "name": "starstar/webdir/notrepo/e",
382 396 "description": "unknown",
383 397 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
384 398 "lastchange": [*, *], (glob)
385 399 "labels": []
386 400 }, {
387 401 "name": "starstar/webdir/notrepo/e/e2",
388 402 "description": "unknown",
389 403 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
390 404 "lastchange": [*, *], (glob)
391 405 "labels": []
392 406 }, {
393 407 "name": "fancy name for repo f",
394 408 "description": "unknown",
395 409 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
396 410 "lastchange": [*, *], (glob)
397 411 "labels": ["foo", "bar"]
398 412 }, {
399 413 "name": "starstar/webdir/notrepo/f/f2",
400 414 "description": "unknown",
401 415 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
402 416 "lastchange": [*, *], (glob)
403 417 "labels": []
404 418 }, {
405 419 "name": "astar",
406 420 "description": "unknown",
407 421 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
408 422 "lastchange": [*, *], (glob)
409 423 "labels": []
410 424 }, {
411 425 "name": "astar/.hg/patches",
412 426 "description": "unknown",
413 427 "contact": "Foo Bar \u003cfoo.bar@example.com\u003e",
414 428 "lastchange": [*, *], (glob)
415 429 "labels": []
416 430 }]
417 431 } (no-eol)
418 432
419 433 $ get-with-headers.py localhost:$HGPORT1 '?style=paper'
420 434 200 Script output follows
421 435
422 436 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
423 437 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
424 438 <head>
425 439 <link rel="icon" href="/static/hgicon.png" type="image/png" />
426 440 <meta name="robots" content="index, nofollow" />
427 441 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
428 442 <script type="text/javascript" src="/static/mercurial.js"></script>
429 443
430 444 <title>Mercurial repositories index</title>
431 445 </head>
432 446 <body>
433 447
434 448 <div class="container">
435 449 <div class="menu">
436 450 <a href="https://mercurial-scm.org/">
437 451 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
438 452 </div>
439 453 <div class="main">
440 454 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
441 455
442 456 <table class="bigtable">
443 457 <thead>
444 458 <tr>
445 459 <th><a href="?sort=name">Name</a></th>
446 460 <th><a href="?sort=description">Description</a></th>
447 461 <th><a href="?sort=contact">Contact</a></th>
448 462 <th><a href="?sort=lastchange">Last modified</a></th>
449 463 <th>&nbsp;</th>
450 464 <th>&nbsp;</th>
451 465 </tr>
452 466 </thead>
453 467 <tbody class="stripes2">
454 468
455 469 <tr>
456 470 <td><a href="/t/a/?style=paper">t/a</a></td>
457 471 <td>unknown</td>
458 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>
459 473 <td class="age">*</td> (glob)
460 474 <td class="indexlinks"></td>
461 475 <td>
462 476 <a href="/t/a/atom-log" title="subscribe to repository atom feed">
463 477 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
464 478 </a>
465 479 </td>
466 480 </tr>
467 481
468 482 <tr>
469 483 <td><a href="/b/?style=paper">b</a></td>
470 484 <td>unknown</td>
471 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>
472 486 <td class="age">*</td> (glob)
473 487 <td class="indexlinks"></td>
474 488 <td>
475 489 <a href="/b/atom-log" title="subscribe to repository atom feed">
476 490 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
477 491 </a>
478 492 </td>
479 493 </tr>
480 494
481 495 <tr>
482 496 <td><a href="/coll/a/?style=paper">coll/a</a></td>
483 497 <td>unknown</td>
484 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>
485 499 <td class="age">*</td> (glob)
486 500 <td class="indexlinks"></td>
487 501 <td>
488 502 <a href="/coll/a/atom-log" title="subscribe to repository atom feed">
489 503 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
490 504 </a>
491 505 </td>
492 506 </tr>
493 507
494 508 <tr>
495 509 <td><a href="/coll/a/.hg/patches/?style=paper">coll/a/.hg/patches</a></td>
496 510 <td>unknown</td>
497 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>
498 512 <td class="age">*</td> (glob)
499 513 <td class="indexlinks"></td>
500 514 <td>
501 515 <a href="/coll/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
502 516 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
503 517 </a>
504 518 </td>
505 519 </tr>
506 520
507 521 <tr>
508 522 <td><a href="/coll/b/?style=paper">coll/b</a></td>
509 523 <td>unknown</td>
510 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>
511 525 <td class="age">*</td> (glob)
512 526 <td class="indexlinks"></td>
513 527 <td>
514 528 <a href="/coll/b/atom-log" title="subscribe to repository atom feed">
515 529 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
516 530 </a>
517 531 </td>
518 532 </tr>
519 533
520 534 <tr>
521 535 <td><a href="/coll/c/?style=paper">coll/c</a></td>
522 536 <td>unknown</td>
523 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>
524 538 <td class="age">*</td> (glob)
525 539 <td class="indexlinks"></td>
526 540 <td>
527 541 <a href="/coll/c/atom-log" title="subscribe to repository atom feed">
528 542 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
529 543 </a>
530 544 </td>
531 545 </tr>
532 546
533 547 <tr>
534 548 <td><a href="/coll/notrepo/e/?style=paper">coll/notrepo/e</a></td>
535 549 <td>unknown</td>
536 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>
537 551 <td class="age">*</td> (glob)
538 552 <td class="indexlinks"></td>
539 553 <td>
540 554 <a href="/coll/notrepo/e/atom-log" title="subscribe to repository atom feed">
541 555 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
542 556 </a>
543 557 </td>
544 558 </tr>
545 559
546 560 <tr>
547 561 <td><a href="/coll/notrepo/f/?style=paper">fancy name for repo f</a></td>
548 562 <td>unknown</td>
549 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>
550 564 <td class="age">*</td> (glob)
551 565 <td class="indexlinks"></td>
552 566 <td>
553 567 <a href="/coll/notrepo/f/atom-log" title="subscribe to repository atom feed">
554 568 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
555 569 </a>
556 570 </td>
557 571 </tr>
558 572
559 573 <tr>
560 574 <td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
561 575 <td>unknown</td>
562 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>
563 577 <td class="age">*</td> (glob)
564 578 <td class="indexlinks"></td>
565 579 <td>
566 580 <a href="/rcoll/a/atom-log" title="subscribe to repository atom feed">
567 581 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
568 582 </a>
569 583 </td>
570 584 </tr>
571 585
572 586 <tr>
573 587 <td><a href="/rcoll/a/.hg/patches/?style=paper">rcoll/a/.hg/patches</a></td>
574 588 <td>unknown</td>
575 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>
576 590 <td class="age">*</td> (glob)
577 591 <td class="indexlinks"></td>
578 592 <td>
579 593 <a href="/rcoll/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
580 594 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
581 595 </a>
582 596 </td>
583 597 </tr>
584 598
585 599 <tr>
586 600 <td><a href="/rcoll/b/?style=paper">rcoll/b</a></td>
587 601 <td>unknown</td>
588 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>
589 603 <td class="age">*</td> (glob)
590 604 <td class="indexlinks"></td>
591 605 <td>
592 606 <a href="/rcoll/b/atom-log" title="subscribe to repository atom feed">
593 607 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
594 608 </a>
595 609 </td>
596 610 </tr>
597 611
598 612 <tr>
599 613 <td><a href="/rcoll/b/d/?style=paper">rcoll/b/d</a></td>
600 614 <td>unknown</td>
601 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>
602 616 <td class="age">*</td> (glob)
603 617 <td class="indexlinks"></td>
604 618 <td>
605 619 <a href="/rcoll/b/d/atom-log" title="subscribe to repository atom feed">
606 620 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
607 621 </a>
608 622 </td>
609 623 </tr>
610 624
611 625 <tr>
612 626 <td><a href="/rcoll/c/?style=paper">rcoll/c</a></td>
613 627 <td>unknown</td>
614 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>
615 629 <td class="age">*</td> (glob)
616 630 <td class="indexlinks"></td>
617 631 <td>
618 632 <a href="/rcoll/c/atom-log" title="subscribe to repository atom feed">
619 633 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
620 634 </a>
621 635 </td>
622 636 </tr>
623 637
624 638 <tr>
625 639 <td><a href="/rcoll/notrepo/e/?style=paper">rcoll/notrepo/e</a></td>
626 640 <td>unknown</td>
627 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>
628 642 <td class="age">*</td> (glob)
629 643 <td class="indexlinks"></td>
630 644 <td>
631 645 <a href="/rcoll/notrepo/e/atom-log" title="subscribe to repository atom feed">
632 646 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
633 647 </a>
634 648 </td>
635 649 </tr>
636 650
637 651 <tr>
638 652 <td><a href="/rcoll/notrepo/e/e2/?style=paper">rcoll/notrepo/e/e2</a></td>
639 653 <td>unknown</td>
640 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>
641 655 <td class="age">*</td> (glob)
642 656 <td class="indexlinks"></td>
643 657 <td>
644 658 <a href="/rcoll/notrepo/e/e2/atom-log" title="subscribe to repository atom feed">
645 659 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
646 660 </a>
647 661 </td>
648 662 </tr>
649 663
650 664 <tr>
651 665 <td><a href="/rcoll/notrepo/f/?style=paper">fancy name for repo f</a></td>
652 666 <td>unknown</td>
653 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>
654 668 <td class="age">*</td> (glob)
655 669 <td class="indexlinks"></td>
656 670 <td>
657 671 <a href="/rcoll/notrepo/f/atom-log" title="subscribe to repository atom feed">
658 672 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
659 673 </a>
660 674 </td>
661 675 </tr>
662 676
663 677 <tr>
664 678 <td><a href="/rcoll/notrepo/f/f2/?style=paper">rcoll/notrepo/f/f2</a></td>
665 679 <td>unknown</td>
666 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>
667 681 <td class="age">*</td> (glob)
668 682 <td class="indexlinks"></td>
669 683 <td>
670 684 <a href="/rcoll/notrepo/f/f2/atom-log" title="subscribe to repository atom feed">
671 685 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
672 686 </a>
673 687 </td>
674 688 </tr>
675 689
676 690 <tr>
677 691 <td><a href="/star/webdir/a/?style=paper">star/webdir/a</a></td>
678 692 <td>unknown</td>
679 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>
680 694 <td class="age">*</td> (glob)
681 695 <td class="indexlinks"></td>
682 696 <td>
683 697 <a href="/star/webdir/a/atom-log" title="subscribe to repository atom feed">
684 698 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
685 699 </a>
686 700 </td>
687 701 </tr>
688 702
689 703 <tr>
690 704 <td><a href="/star/webdir/a/.hg/patches/?style=paper">star/webdir/a/.hg/patches</a></td>
691 705 <td>unknown</td>
692 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>
693 707 <td class="age">*</td> (glob)
694 708 <td class="indexlinks"></td>
695 709 <td>
696 710 <a href="/star/webdir/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
697 711 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
698 712 </a>
699 713 </td>
700 714 </tr>
701 715
702 716 <tr>
703 717 <td><a href="/star/webdir/b/?style=paper">star/webdir/b</a></td>
704 718 <td>unknown</td>
705 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>
706 720 <td class="age">*</td> (glob)
707 721 <td class="indexlinks"></td>
708 722 <td>
709 723 <a href="/star/webdir/b/atom-log" title="subscribe to repository atom feed">
710 724 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
711 725 </a>
712 726 </td>
713 727 </tr>
714 728
715 729 <tr>
716 730 <td><a href="/star/webdir/c/?style=paper">star/webdir/c</a></td>
717 731 <td>unknown</td>
718 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>
719 733 <td class="age">*</td> (glob)
720 734 <td class="indexlinks"></td>
721 735 <td>
722 736 <a href="/star/webdir/c/atom-log" title="subscribe to repository atom feed">
723 737 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
724 738 </a>
725 739 </td>
726 740 </tr>
727 741
728 742 <tr>
729 743 <td><a href="/star/webdir/notrepo/e/?style=paper">star/webdir/notrepo/e</a></td>
730 744 <td>unknown</td>
731 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>
732 746 <td class="age">*</td> (glob)
733 747 <td class="indexlinks"></td>
734 748 <td>
735 749 <a href="/star/webdir/notrepo/e/atom-log" title="subscribe to repository atom feed">
736 750 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
737 751 </a>
738 752 </td>
739 753 </tr>
740 754
741 755 <tr>
742 756 <td><a href="/star/webdir/notrepo/f/?style=paper">fancy name for repo f</a></td>
743 757 <td>unknown</td>
744 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>
745 759 <td class="age">*</td> (glob)
746 760 <td class="indexlinks"></td>
747 761 <td>
748 762 <a href="/star/webdir/notrepo/f/atom-log" title="subscribe to repository atom feed">
749 763 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
750 764 </a>
751 765 </td>
752 766 </tr>
753 767
754 768 <tr>
755 769 <td><a href="/starstar/webdir/a/?style=paper">starstar/webdir/a</a></td>
756 770 <td>unknown</td>
757 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>
758 772 <td class="age">*</td> (glob)
759 773 <td class="indexlinks"></td>
760 774 <td>
761 775 <a href="/starstar/webdir/a/atom-log" title="subscribe to repository atom feed">
762 776 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
763 777 </a>
764 778 </td>
765 779 </tr>
766 780
767 781 <tr>
768 782 <td><a href="/starstar/webdir/a/.hg/patches/?style=paper">starstar/webdir/a/.hg/patches</a></td>
769 783 <td>unknown</td>
770 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>
771 785 <td class="age">*</td> (glob)
772 786 <td class="indexlinks"></td>
773 787 <td>
774 788 <a href="/starstar/webdir/a/.hg/patches/atom-log" title="subscribe to repository atom feed">
775 789 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
776 790 </a>
777 791 </td>
778 792 </tr>
779 793
780 794 <tr>
781 795 <td><a href="/starstar/webdir/b/?style=paper">starstar/webdir/b</a></td>
782 796 <td>unknown</td>
783 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>
784 798 <td class="age">*</td> (glob)
785 799 <td class="indexlinks"></td>
786 800 <td>
787 801 <a href="/starstar/webdir/b/atom-log" title="subscribe to repository atom feed">
788 802 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
789 803 </a>
790 804 </td>
791 805 </tr>
792 806
793 807 <tr>
794 808 <td><a href="/starstar/webdir/b/d/?style=paper">starstar/webdir/b/d</a></td>
795 809 <td>unknown</td>
796 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>
797 811 <td class="age">*</td> (glob)
798 812 <td class="indexlinks"></td>
799 813 <td>
800 814 <a href="/starstar/webdir/b/d/atom-log" title="subscribe to repository atom feed">
801 815 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
802 816 </a>
803 817 </td>
804 818 </tr>
805 819
806 820 <tr>
807 821 <td><a href="/starstar/webdir/c/?style=paper">starstar/webdir/c</a></td>
808 822 <td>unknown</td>
809 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>
810 824 <td class="age">*</td> (glob)
811 825 <td class="indexlinks"></td>
812 826 <td>
813 827 <a href="/starstar/webdir/c/atom-log" title="subscribe to repository atom feed">
814 828 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
815 829 </a>
816 830 </td>
817 831 </tr>
818 832
819 833 <tr>
820 834 <td><a href="/starstar/webdir/notrepo/e/?style=paper">starstar/webdir/notrepo/e</a></td>
821 835 <td>unknown</td>
822 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>
823 837 <td class="age">*</td> (glob)
824 838 <td class="indexlinks"></td>
825 839 <td>
826 840 <a href="/starstar/webdir/notrepo/e/atom-log" title="subscribe to repository atom feed">
827 841 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
828 842 </a>
829 843 </td>
830 844 </tr>
831 845
832 846 <tr>
833 847 <td><a href="/starstar/webdir/notrepo/e/e2/?style=paper">starstar/webdir/notrepo/e/e2</a></td>
834 848 <td>unknown</td>
835 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>
836 850 <td class="age">*</td> (glob)
837 851 <td class="indexlinks"></td>
838 852 <td>
839 853 <a href="/starstar/webdir/notrepo/e/e2/atom-log" title="subscribe to repository atom feed">
840 854 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
841 855 </a>
842 856 </td>
843 857 </tr>
844 858
845 859 <tr>
846 860 <td><a href="/starstar/webdir/notrepo/f/?style=paper">fancy name for repo f</a></td>
847 861 <td>unknown</td>
848 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>
849 863 <td class="age">*</td> (glob)
850 864 <td class="indexlinks"></td>
851 865 <td>
852 866 <a href="/starstar/webdir/notrepo/f/atom-log" title="subscribe to repository atom feed">
853 867 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
854 868 </a>
855 869 </td>
856 870 </tr>
857 871
858 872 <tr>
859 873 <td><a href="/starstar/webdir/notrepo/f/f2/?style=paper">starstar/webdir/notrepo/f/f2</a></td>
860 874 <td>unknown</td>
861 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>
862 876 <td class="age">*</td> (glob)
863 877 <td class="indexlinks"></td>
864 878 <td>
865 879 <a href="/starstar/webdir/notrepo/f/f2/atom-log" title="subscribe to repository atom feed">
866 880 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
867 881 </a>
868 882 </td>
869 883 </tr>
870 884
871 885 <tr>
872 886 <td><a href="/astar/?style=paper">astar</a></td>
873 887 <td>unknown</td>
874 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>
875 889 <td class="age">*</td> (glob)
876 890 <td class="indexlinks"></td>
877 891 <td>
878 892 <a href="/astar/atom-log" title="subscribe to repository atom feed">
879 893 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
880 894 </a>
881 895 </td>
882 896 </tr>
883 897
884 898 <tr>
885 899 <td><a href="/astar/.hg/patches/?style=paper">astar/.hg/patches</a></td>
886 900 <td>unknown</td>
887 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>
888 902 <td class="age">*</td> (glob)
889 903 <td class="indexlinks"></td>
890 904 <td>
891 905 <a href="/astar/.hg/patches/atom-log" title="subscribe to repository atom feed">
892 906 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
893 907 </a>
894 908 </td>
895 909 </tr>
896 910
897 911 </tbody>
898 912 </table>
899 913 </div>
900 914 </div>
901 915
902 916
903 917 </body>
904 918 </html>
905 919
906 920 $ get-with-headers.py localhost:$HGPORT1 't?style=raw'
907 921 200 Script output follows
908 922
909 923
910 924 /t/a/
911 925
912 926 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
913 927 200 Script output follows
914 928
915 929
916 930 /t/a/
917 931
918 932 $ get-with-headers.py localhost:$HGPORT1 't/?style=paper'
919 933 200 Script output follows
920 934
921 935 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
922 936 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
923 937 <head>
924 938 <link rel="icon" href="/static/hgicon.png" type="image/png" />
925 939 <meta name="robots" content="index, nofollow" />
926 940 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
927 941 <script type="text/javascript" src="/static/mercurial.js"></script>
928 942
929 943 <title>Mercurial repositories index</title>
930 944 </head>
931 945 <body>
932 946
933 947 <div class="container">
934 948 <div class="menu">
935 949 <a href="https://mercurial-scm.org/">
936 950 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
937 951 </div>
938 952 <div class="main">
939 953 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/t">t</a> </h2>
940 954
941 955 <table class="bigtable">
942 956 <thead>
943 957 <tr>
944 958 <th><a href="?sort=name">Name</a></th>
945 959 <th><a href="?sort=description">Description</a></th>
946 960 <th><a href="?sort=contact">Contact</a></th>
947 961 <th><a href="?sort=lastchange">Last modified</a></th>
948 962 <th>&nbsp;</th>
949 963 <th>&nbsp;</th>
950 964 </tr>
951 965 </thead>
952 966 <tbody class="stripes2">
953 967
954 968 <tr>
955 969 <td><a href="/t/a/?style=paper">a</a></td>
956 970 <td>unknown</td>
957 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>
958 972 <td class="age">*</td> (glob)
959 973 <td class="indexlinks"></td>
960 974 <td>
961 975 <a href="/t/a/atom-log" title="subscribe to repository atom feed">
962 976 <img class="atom-logo" src="/static/feed-icon-14x14.png" alt="subscribe to repository atom feed">
963 977 </a>
964 978 </td>
965 979 </tr>
966 980
967 981 </tbody>
968 982 </table>
969 983 </div>
970 984 </div>
971 985
972 986
973 987 </body>
974 988 </html>
975 989
976 990 $ get-with-headers.py localhost:$HGPORT1 't/a?style=atom'
977 991 200 Script output follows
978 992
979 993 <?xml version="1.0" encoding="ascii"?>
980 994 <feed xmlns="http://www.w3.org/2005/Atom">
981 995 <!-- Changelog -->
982 996 <id>http://*:$HGPORT1/t/a/</id> (glob)
983 997 <link rel="self" href="http://*:$HGPORT1/t/a/atom-log"/> (glob)
984 998 <link rel="alternate" href="http://*:$HGPORT1/t/a/"/> (glob)
985 999 <title>t/a Changelog</title>
986 1000 <updated>1970-01-01T00:00:01+00:00</updated>
987 1001
988 1002 <entry>
989 1003 <title>[default] a</title>
990 1004 <id>http://*:$HGPORT1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id> (glob)
991 1005 <link href="http://*:$HGPORT1/t/a/rev/8580ff50825a"/> (glob)
992 1006 <author>
993 1007 <name>test</name>
994 1008 <email>&#116;&#101;&#115;&#116;</email>
995 1009 </author>
996 1010 <updated>1970-01-01T00:00:01+00:00</updated>
997 1011 <published>1970-01-01T00:00:01+00:00</published>
998 1012 <content type="xhtml">
999 1013 <table xmlns="http://www.w3.org/1999/xhtml">
1000 1014 <tr>
1001 1015 <th style="text-align:left;">changeset</th>
1002 1016 <td>8580ff50825a</td>
1003 1017 </tr>
1004 1018 <tr>
1005 1019 <th style="text-align:left;">branch</th>
1006 1020 <td>default</td>
1007 1021 </tr>
1008 1022 <tr>
1009 1023 <th style="text-align:left;">bookmark</th>
1010 1024 <td></td>
1011 1025 </tr>
1012 1026 <tr>
1013 1027 <th style="text-align:left;">tag</th>
1014 1028 <td>tip</td>
1015 1029 </tr>
1016 1030 <tr>
1017 1031 <th style="text-align:left;">user</th>
1018 1032 <td>&#116;&#101;&#115;&#116;</td>
1019 1033 </tr>
1020 1034 <tr>
1021 1035 <th style="text-align:left;vertical-align:top;">description</th>
1022 1036 <td>a</td>
1023 1037 </tr>
1024 1038 <tr>
1025 1039 <th style="text-align:left;vertical-align:top;">files</th>
1026 1040 <td>a<br /></td>
1027 1041 </tr>
1028 1042 </table>
1029 1043 </content>
1030 1044 </entry>
1031 1045
1032 1046 </feed>
1033 1047 $ get-with-headers.py localhost:$HGPORT1 't/a/?style=atom'
1034 1048 200 Script output follows
1035 1049
1036 1050 <?xml version="1.0" encoding="ascii"?>
1037 1051 <feed xmlns="http://www.w3.org/2005/Atom">
1038 1052 <!-- Changelog -->
1039 1053 <id>http://*:$HGPORT1/t/a/</id> (glob)
1040 1054 <link rel="self" href="http://*:$HGPORT1/t/a/atom-log"/> (glob)
1041 1055 <link rel="alternate" href="http://*:$HGPORT1/t/a/"/> (glob)
1042 1056 <title>t/a Changelog</title>
1043 1057 <updated>1970-01-01T00:00:01+00:00</updated>
1044 1058
1045 1059 <entry>
1046 1060 <title>[default] a</title>
1047 1061 <id>http://*:$HGPORT1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id> (glob)
1048 1062 <link href="http://*:$HGPORT1/t/a/rev/8580ff50825a"/> (glob)
1049 1063 <author>
1050 1064 <name>test</name>
1051 1065 <email>&#116;&#101;&#115;&#116;</email>
1052 1066 </author>
1053 1067 <updated>1970-01-01T00:00:01+00:00</updated>
1054 1068 <published>1970-01-01T00:00:01+00:00</published>
1055 1069 <content type="xhtml">
1056 1070 <table xmlns="http://www.w3.org/1999/xhtml">
1057 1071 <tr>
1058 1072 <th style="text-align:left;">changeset</th>
1059 1073 <td>8580ff50825a</td>
1060 1074 </tr>
1061 1075 <tr>
1062 1076 <th style="text-align:left;">branch</th>
1063 1077 <td>default</td>
1064 1078 </tr>
1065 1079 <tr>
1066 1080 <th style="text-align:left;">bookmark</th>
1067 1081 <td></td>
1068 1082 </tr>
1069 1083 <tr>
1070 1084 <th style="text-align:left;">tag</th>
1071 1085 <td>tip</td>
1072 1086 </tr>
1073 1087 <tr>
1074 1088 <th style="text-align:left;">user</th>
1075 1089 <td>&#116;&#101;&#115;&#116;</td>
1076 1090 </tr>
1077 1091 <tr>
1078 1092 <th style="text-align:left;vertical-align:top;">description</th>
1079 1093 <td>a</td>
1080 1094 </tr>
1081 1095 <tr>
1082 1096 <th style="text-align:left;vertical-align:top;">files</th>
1083 1097 <td>a<br /></td>
1084 1098 </tr>
1085 1099 </table>
1086 1100 </content>
1087 1101 </entry>
1088 1102
1089 1103 </feed>
1090 1104 $ get-with-headers.py localhost:$HGPORT1 't/a/file/tip/a?style=raw'
1091 1105 200 Script output follows
1092 1106
1093 1107 a
1094 1108
1095 1109 Test [paths] '*' extension
1096 1110
1097 1111 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1098 1112 200 Script output follows
1099 1113
1100 1114
1101 1115 /coll/a/
1102 1116 /coll/a/.hg/patches/
1103 1117 /coll/b/
1104 1118 /coll/c/
1105 1119 /coll/notrepo/e/
1106 1120 /coll/notrepo/f/
1107 1121
1108 1122 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1109 1123 200 Script output follows
1110 1124
1111 1125 a
1112 1126
1113 1127 Test [paths] '**' extension
1114 1128
1115 1129 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1116 1130 200 Script output follows
1117 1131
1118 1132
1119 1133 /rcoll/a/
1120 1134 /rcoll/a/.hg/patches/
1121 1135 /rcoll/b/
1122 1136 /rcoll/b/d/
1123 1137 /rcoll/c/
1124 1138 /rcoll/notrepo/e/
1125 1139 /rcoll/notrepo/e/e2/
1126 1140 /rcoll/notrepo/f/
1127 1141 /rcoll/notrepo/f/f2/
1128 1142
1129 1143 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1130 1144 200 Script output follows
1131 1145
1132 1146 d
1133 1147
1134 1148 Test collapse = True
1135 1149
1136 1150 $ killdaemons.py
1137 1151 $ cat >> paths.conf <<EOF
1138 1152 > [web]
1139 1153 > collapse=true
1140 1154 > descend = true
1141 1155 > EOF
1142 1156 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1143 1157 > -A access-paths.log -E error-paths-3.log
1144 1158 $ cat hg.pid >> $DAEMON_PIDS
1145 1159 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1146 1160 200 Script output follows
1147 1161
1148 1162
1149 1163 /coll/a/
1150 1164 /coll/a/.hg/patches/
1151 1165 /coll/b/
1152 1166 /coll/c/
1153 1167 /coll/notrepo/
1154 1168
1155 1169 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1156 1170 200 Script output follows
1157 1171
1158 1172 a
1159 1173 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1160 1174 200 Script output follows
1161 1175
1162 1176
1163 1177 /rcoll/a/
1164 1178 /rcoll/a/.hg/patches/
1165 1179 /rcoll/b/
1166 1180 /rcoll/b/d/
1167 1181 /rcoll/c/
1168 1182 /rcoll/notrepo/
1169 1183
1170 1184 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1171 1185 200 Script output follows
1172 1186
1173 1187 d
1174 1188
1175 1189 Test intermediate directories
1176 1190
1177 1191 Hide the subrepo parent
1178 1192
1179 1193 $ cp $root/notrepo/f/.hg/hgrc $root/notrepo/f/.hg/hgrc.bak
1180 1194 $ cat >> $root/notrepo/f/.hg/hgrc << EOF
1181 1195 > [web]
1182 1196 > hidden = True
1183 1197 > EOF
1184 1198
1185 1199 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1186 1200 200 Script output follows
1187 1201
1188 1202
1189 1203 /rcoll/notrepo/e/
1190 1204 /rcoll/notrepo/e/e2/
1191 1205
1192 1206
1193 1207 Subrepo parent not hidden
1194 1208 $ mv $root/notrepo/f/.hg/hgrc.bak $root/notrepo/f/.hg/hgrc
1195 1209
1196 1210 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1197 1211 200 Script output follows
1198 1212
1199 1213
1200 1214 /rcoll/notrepo/e/
1201 1215 /rcoll/notrepo/e/e2/
1202 1216 /rcoll/notrepo/f/
1203 1217 /rcoll/notrepo/f/f2/
1204 1218
1205 1219
1206 1220 Test repositories inside intermediate directories
1207 1221
1208 1222 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/e/file/tip/e?style=raw'
1209 1223 200 Script output follows
1210 1224
1211 1225 e
1212 1226
1213 1227 Test subrepositories inside intermediate directories
1214 1228
1215 1229 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/f2/file/tip/f2?style=raw'
1216 1230 200 Script output follows
1217 1231
1218 1232 f2
1219 1233
1234 Test accessing file that is shadowed by another repository
1235
1236 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/f3/file?style=raw'
1237 403 Forbidden
1238
1239
1240 error: path 'f3/file' is inside nested repo 'f3'
1241 [1]
1242
1243 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/ffffffffffff/f3/file?style=raw'
1244 403 Forbidden
1245
1246
1247 error: path 'f3/file' is inside nested repo 'f3'
1248 [1]
1249
1250 Test accessing invalid paths:
1251
1252 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/..?style=raw'
1253 403 Forbidden
1254
1255
1256 error: .. not under root '$TESTTMP/dir/webdir/notrepo/f'
1257 [1]
1258
1259 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/file/tip/.hg/hgrc?style=raw'
1260 403 Forbidden
1261
1262
1263 error: path contains illegal component: .hg/hgrc
1264 [1]
1265
1220 1266 Test descend = False
1221 1267
1222 1268 $ killdaemons.py
1223 1269 $ cat >> paths.conf <<EOF
1224 1270 > descend=false
1225 1271 > EOF
1226 1272 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1227 1273 > -A access-paths.log -E error-paths-4.log
1228 1274 $ cat hg.pid >> $DAEMON_PIDS
1229 1275 $ get-with-headers.py localhost:$HGPORT1 'coll/?style=raw'
1230 1276 200 Script output follows
1231 1277
1232 1278
1233 1279 /coll/a/
1234 1280 /coll/b/
1235 1281 /coll/c/
1236 1282
1237 1283 $ get-with-headers.py localhost:$HGPORT1 'coll/a/file/tip/a?style=raw'
1238 1284 200 Script output follows
1239 1285
1240 1286 a
1241 1287 $ get-with-headers.py localhost:$HGPORT1 'rcoll/?style=raw'
1242 1288 200 Script output follows
1243 1289
1244 1290
1245 1291 /rcoll/a/
1246 1292 /rcoll/b/
1247 1293 /rcoll/c/
1248 1294
1249 1295 $ get-with-headers.py localhost:$HGPORT1 'rcoll/b/d/file/tip/d?style=raw'
1250 1296 200 Script output follows
1251 1297
1252 1298 d
1253 1299
1254 1300 Test intermediate directories
1255 1301
1256 1302 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/?style=raw'
1257 1303 200 Script output follows
1258 1304
1259 1305
1260 1306 /rcoll/notrepo/e/
1261 1307 /rcoll/notrepo/f/
1262 1308
1263 1309
1264 1310 Test repositories inside intermediate directories
1265 1311
1266 1312 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/e/file/tip/e?style=raw'
1267 1313 200 Script output follows
1268 1314
1269 1315 e
1270 1316
1271 1317 Test subrepositories inside intermediate directories
1272 1318
1273 1319 $ get-with-headers.py localhost:$HGPORT1 'rcoll/notrepo/f/f2/file/tip/f2?style=raw'
1274 1320 200 Script output follows
1275 1321
1276 1322 f2
1277 1323
1278 1324 Test [paths] '*' in a repo root
1279 1325
1280 1326 $ hg id http://localhost:$HGPORT1/astar
1281 1327 8580ff50825a
1282 1328
1283 1329 $ killdaemons.py
1284 1330 $ cat > paths.conf <<EOF
1285 1331 > [paths]
1286 1332 > t/a = $root/a
1287 1333 > t/b = $root/b
1288 1334 > c = $root/c
1289 1335 > EOF
1290 1336 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1291 1337 > -A access-paths.log -E error-paths-5.log
1292 1338 $ cat hg.pid >> $DAEMON_PIDS
1293 1339 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1294 1340 200 Script output follows
1295 1341
1296 1342
1297 1343 /t/a/
1298 1344 /t/b/
1299 1345 /c/
1300 1346
1301 1347 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1302 1348 200 Script output follows
1303 1349
1304 1350
1305 1351 /t/a/
1306 1352 /t/b/
1307 1353
1308 1354
1309 1355 Test collapse = True
1310 1356
1311 1357 $ killdaemons.py
1312 1358 $ cat >> paths.conf <<EOF
1313 1359 > [web]
1314 1360 > collapse=true
1315 1361 > EOF
1316 1362 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1317 1363 > -A access-paths.log -E error-paths-6.log
1318 1364 $ cat hg.pid >> $DAEMON_PIDS
1319 1365 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1320 1366 200 Script output follows
1321 1367
1322 1368
1323 1369 /t/
1324 1370 /c/
1325 1371
1326 1372 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1327 1373 200 Script output follows
1328 1374
1329 1375
1330 1376 /t/a/
1331 1377 /t/b/
1332 1378
1333 1379
1334 1380 test descend = False
1335 1381
1336 1382 $ killdaemons.py
1337 1383 $ cat >> paths.conf <<EOF
1338 1384 > descend=false
1339 1385 > EOF
1340 1386 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1341 1387 > -A access-paths.log -E error-paths-7.log
1342 1388 $ cat hg.pid >> $DAEMON_PIDS
1343 1389 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1344 1390 200 Script output follows
1345 1391
1346 1392
1347 1393 /c/
1348 1394
1349 1395 $ get-with-headers.py localhost:$HGPORT1 't/?style=raw'
1350 1396 200 Script output follows
1351 1397
1352 1398
1353 1399 /t/a/
1354 1400 /t/b/
1355 1401
1356 1402 $ killdaemons.py
1357 1403 $ cat > paths.conf <<EOF
1358 1404 > [paths]
1359 1405 > nostore = $root/nostore
1360 1406 > inexistent = $root/inexistent
1361 1407 > EOF
1362 1408 $ hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
1363 1409 > -A access-paths.log -E error-paths-8.log
1364 1410 $ cat hg.pid >> $DAEMON_PIDS
1365 1411
1366 1412 test inexistent and inaccessible repo should be ignored silently
1367 1413
1368 1414 $ get-with-headers.py localhost:$HGPORT1 ''
1369 1415 200 Script output follows
1370 1416
1371 1417 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1372 1418 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1373 1419 <head>
1374 1420 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1375 1421 <meta name="robots" content="index, nofollow" />
1376 1422 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1377 1423 <script type="text/javascript" src="/static/mercurial.js"></script>
1378 1424
1379 1425 <title>Mercurial repositories index</title>
1380 1426 </head>
1381 1427 <body>
1382 1428
1383 1429 <div class="container">
1384 1430 <div class="menu">
1385 1431 <a href="https://mercurial-scm.org/">
1386 1432 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
1387 1433 </div>
1388 1434 <div class="main">
1389 1435 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1390 1436
1391 1437 <table class="bigtable">
1392 1438 <thead>
1393 1439 <tr>
1394 1440 <th><a href="?sort=name">Name</a></th>
1395 1441 <th><a href="?sort=description">Description</a></th>
1396 1442 <th><a href="?sort=contact">Contact</a></th>
1397 1443 <th><a href="?sort=lastchange">Last modified</a></th>
1398 1444 <th>&nbsp;</th>
1399 1445 <th>&nbsp;</th>
1400 1446 </tr>
1401 1447 </thead>
1402 1448 <tbody class="stripes2">
1403 1449
1404 1450 </tbody>
1405 1451 </table>
1406 1452 </div>
1407 1453 </div>
1408 1454
1409 1455
1410 1456 </body>
1411 1457 </html>
1412 1458
1413 1459
1414 1460 test listening address/port specified by web-conf (issue4699):
1415 1461
1416 1462 $ killdaemons.py
1417 1463 $ cat >> paths.conf <<EOF
1418 1464 > [web]
1419 1465 > address = localhost
1420 1466 > port = $HGPORT1
1421 1467 > EOF
1422 1468 $ hg serve -d --pid-file=hg.pid --web-conf paths.conf \
1423 1469 > -A access-paths.log -E error-paths-9.log
1424 1470 listening at http://*:$HGPORT1/ (bound to *$LOCALIP*:$HGPORT1) (glob) (?)
1425 1471 $ cat hg.pid >> $DAEMON_PIDS
1426 1472 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1427 1473 200 Script output follows
1428 1474
1429 1475
1430 1476
1431 1477 test --port option overrides web.port:
1432 1478
1433 1479 $ killdaemons.py
1434 1480 $ hg serve -p $HGPORT2 -d -v --pid-file=hg.pid --web-conf paths.conf \
1435 1481 > -A access-paths.log -E error-paths-10.log
1436 1482 listening at http://*:$HGPORT2/ (bound to *$LOCALIP*:$HGPORT2) (glob) (?)
1437 1483 $ cat hg.pid >> $DAEMON_PIDS
1438 1484 $ get-with-headers.py localhost:$HGPORT2 '?style=raw'
1439 1485 200 Script output follows
1440 1486
1441 1487
1442 1488
1443 1489
1444 1490 $ killdaemons.py
1445 1491 $ cat > collections.conf <<EOF
1446 1492 > [collections]
1447 1493 > $root=$root
1448 1494 > EOF
1449 1495 $ hg serve --config web.baseurl=http://hg.example.com:8080/ -p $HGPORT2 -d \
1450 1496 > --pid-file=hg.pid --webdir-conf collections.conf \
1451 1497 > -A access-collections.log -E error-collections.log
1452 1498 $ cat hg.pid >> $DAEMON_PIDS
1453 1499
1454 1500 collections: should succeed
1455 1501
1456 1502 $ get-with-headers.py localhost:$HGPORT2 '?style=raw'
1457 1503 200 Script output follows
1458 1504
1459 1505
1460 1506 /a/
1461 1507 /a/.hg/patches/
1462 1508 /b/
1463 1509 /c/
1464 1510 /notrepo/e/
1465 1511 /notrepo/f/
1466 1512
1467 1513 $ get-with-headers.py localhost:$HGPORT2 'a/file/tip/a?style=raw'
1468 1514 200 Script output follows
1469 1515
1470 1516 a
1471 1517 $ get-with-headers.py localhost:$HGPORT2 'b/file/tip/b?style=raw'
1472 1518 200 Script output follows
1473 1519
1474 1520 b
1475 1521 $ get-with-headers.py localhost:$HGPORT2 'c/file/tip/c?style=raw'
1476 1522 200 Script output follows
1477 1523
1478 1524 c
1479 1525
1480 1526 atom-log with basedir /
1481 1527
1482 1528 $ get-with-headers.py localhost:$HGPORT2 'a/atom-log' | grep '<link'
1483 1529 <link rel="self" href="http://hg.example.com:8080/a/atom-log"/>
1484 1530 <link rel="alternate" href="http://hg.example.com:8080/a/"/>
1485 1531 <link href="http://hg.example.com:8080/a/rev/8580ff50825a"/>
1486 1532
1487 1533 rss-log with basedir /
1488 1534
1489 1535 $ get-with-headers.py localhost:$HGPORT2 'a/rss-log' | grep '<guid'
1490 1536 <guid isPermaLink="true">http://hg.example.com:8080/a/rev/8580ff50825a</guid>
1491 1537 $ killdaemons.py
1492 1538 $ hg serve --config web.baseurl=http://hg.example.com:8080/foo/ -p $HGPORT2 -d \
1493 1539 > --pid-file=hg.pid --webdir-conf collections.conf \
1494 1540 > -A access-collections-2.log -E error-collections-2.log
1495 1541 $ cat hg.pid >> $DAEMON_PIDS
1496 1542
1497 1543 atom-log with basedir /foo/
1498 1544
1499 1545 $ get-with-headers.py localhost:$HGPORT2 'a/atom-log' | grep '<link'
1500 1546 <link rel="self" href="http://hg.example.com:8080/foo/a/atom-log"/>
1501 1547 <link rel="alternate" href="http://hg.example.com:8080/foo/a/"/>
1502 1548 <link href="http://hg.example.com:8080/foo/a/rev/8580ff50825a"/>
1503 1549
1504 1550 rss-log with basedir /foo/
1505 1551
1506 1552 $ get-with-headers.py localhost:$HGPORT2 'a/rss-log' | grep '<guid'
1507 1553 <guid isPermaLink="true">http://hg.example.com:8080/foo/a/rev/8580ff50825a</guid>
1508 1554
1509 1555 Path refreshing works as expected
1510 1556
1511 1557 $ killdaemons.py
1512 1558 $ mkdir $root/refreshtest
1513 1559 $ hg init $root/refreshtest/a
1514 1560 $ cat > paths.conf << EOF
1515 1561 > [paths]
1516 1562 > / = $root/refreshtest/*
1517 1563 > EOF
1518 1564 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1519 1565 $ cat hg.pid >> $DAEMON_PIDS
1520 1566
1521 1567 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1522 1568 200 Script output follows
1523 1569
1524 1570
1525 1571 /a/
1526 1572
1527 1573
1528 1574 By default refreshing occurs every 20s and a new repo won't be listed
1529 1575 immediately.
1530 1576
1531 1577 $ hg init $root/refreshtest/b
1532 1578 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1533 1579 200 Script output follows
1534 1580
1535 1581
1536 1582 /a/
1537 1583
1538 1584
1539 1585 Restart the server with no refresh interval. New repo should appear
1540 1586 immediately.
1541 1587
1542 1588 $ killdaemons.py
1543 1589 $ cat > paths.conf << EOF
1544 1590 > [web]
1545 1591 > refreshinterval = -1
1546 1592 > [paths]
1547 1593 > / = $root/refreshtest/*
1548 1594 > EOF
1549 1595 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1550 1596 $ cat hg.pid >> $DAEMON_PIDS
1551 1597
1552 1598 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1553 1599 200 Script output follows
1554 1600
1555 1601
1556 1602 /a/
1557 1603 /b/
1558 1604
1559 1605
1560 1606 $ hg init $root/refreshtest/c
1561 1607 $ get-with-headers.py localhost:$HGPORT1 '?style=raw'
1562 1608 200 Script output follows
1563 1609
1564 1610
1565 1611 /a/
1566 1612 /b/
1567 1613 /c/
1568 1614
1569 1615 $ killdaemons.py
1570 1616 $ cat > paths.conf << EOF
1571 1617 > [paths]
1572 1618 > /dir1/a_repo = $root/a
1573 1619 > /dir1/a_repo/b_repo = $root/b
1574 1620 > /dir1/dir2/index = $root/b
1575 1621 > EOF
1576 1622 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1577 1623 $ cat hg.pid >> $DAEMON_PIDS
1578 1624
1579 1625 $ echo 'index file' > $root/a/index
1580 1626 $ hg --cwd $root/a ci -Am 'add index file'
1581 1627 adding index
1582 1628
1583 1629 $ get-with-headers.py localhost:$HGPORT1 '' | grep 'a_repo'
1584 1630 <td><a href="/dir1/a_repo/">dir1/a_repo</a></td>
1585 1631 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1586 1632 <td><a href="/dir1/a_repo/b_repo/">dir1/a_repo/b_repo</a></td>
1587 1633 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1588 1634
1589 1635 $ get-with-headers.py localhost:$HGPORT1 'index' | grep 'a_repo'
1590 1636 <td><a href="/dir1/a_repo/">dir1/a_repo</a></td>
1591 1637 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1592 1638 <td><a href="/dir1/a_repo/b_repo/">dir1/a_repo/b_repo</a></td>
1593 1639 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1594 1640
1595 1641 $ get-with-headers.py localhost:$HGPORT1 'dir1' | grep 'a_repo'
1596 1642 <td><a href="/dir1/a_repo/">a_repo</a></td>
1597 1643 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1598 1644 <td><a href="/dir1/a_repo/b_repo/">a_repo/b_repo</a></td>
1599 1645 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1600 1646
1601 1647 $ get-with-headers.py localhost:$HGPORT1 'dir1/index' | grep 'a_repo'
1602 1648 <td><a href="/dir1/a_repo/">a_repo</a></td>
1603 1649 <a href="/dir1/a_repo/atom-log" title="subscribe to repository atom feed">
1604 1650 <td><a href="/dir1/a_repo/b_repo/">a_repo/b_repo</a></td>
1605 1651 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1606 1652
1607 1653 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo' | grep 'a_repo'
1608 1654 <link rel="icon" href="/dir1/a_repo/static/hgicon.png" type="image/png" />
1609 1655 <link rel="stylesheet" href="/dir1/a_repo/static/style-paper.css" type="text/css" />
1610 1656 <script type="text/javascript" src="/dir1/a_repo/static/mercurial.js"></script>
1611 1657 <title>dir1/a_repo: log</title>
1612 1658 href="/dir1/a_repo/atom-log" title="Atom feed for dir1/a_repo" />
1613 1659 href="/dir1/a_repo/rss-log" title="RSS feed for dir1/a_repo" />
1614 1660 <img src="/dir1/a_repo/static/hglogo.png" alt="mercurial" /></a>
1615 1661 <li><a href="/dir1/a_repo/graph/tip">graph</a></li>
1616 1662 <li><a href="/dir1/a_repo/tags">tags</a></li>
1617 1663 <li><a href="/dir1/a_repo/bookmarks">bookmarks</a></li>
1618 1664 <li><a href="/dir1/a_repo/branches">branches</a></li>
1619 1665 <li><a href="/dir1/a_repo/rev/tip">changeset</a></li>
1620 1666 <li><a href="/dir1/a_repo/file/tip">browse</a></li>
1621 1667 <li><a href="/dir1/a_repo/help">help</a></li>
1622 1668 <a href="/dir1/a_repo/atom-log" title="subscribe to atom feed">
1623 1669 <img class="atom-logo" src="/dir1/a_repo/static/feed-icon-14x14.png" alt="atom feed" />
1624 1670 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/a_repo">a_repo</a> </h2>
1625 1671 <form class="search" action="/dir1/a_repo/log">
1626 1672 number or hash, or <a href="/dir1/a_repo/help/revsets">revset expression</a>.</div>
1627 1673 <a href="/dir1/a_repo/shortlog/tip?revcount=30">less</a>
1628 1674 <a href="/dir1/a_repo/shortlog/tip?revcount=120">more</a>
1629 1675 | rev 1: <a href="/dir1/a_repo/shortlog/8580ff50825a">(0)</a> <a href="/dir1/a_repo/shortlog/tip">tip</a>
1630 1676 <a href="/dir1/a_repo/rev/71a89161f014">add index file</a>
1631 1677 <a href="/dir1/a_repo/rev/8580ff50825a">a</a>
1632 1678 <a href="/dir1/a_repo/shortlog/tip?revcount=30">less</a>
1633 1679 <a href="/dir1/a_repo/shortlog/tip?revcount=120">more</a>
1634 1680 | rev 1: <a href="/dir1/a_repo/shortlog/8580ff50825a">(0)</a> <a href="/dir1/a_repo/shortlog/tip">tip</a>
1635 1681 '/dir1/a_repo/shortlog/%next%',
1636 1682
1637 1683 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/index' | grep 'a_repo'
1638 1684 <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/dir1">dir1</a> &gt; <a href="/dir1/a_repo">a_repo</a> </h2>
1639 1685 <td><a href="/dir1/a_repo/b_repo/">b_repo</a></td>
1640 1686 <a href="/dir1/a_repo/b_repo/atom-log" title="subscribe to repository atom feed">
1641 1687
1642 1688 Files named 'index' are not blocked
1643 1689
1644 1690 $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/raw-file/tip/index'
1645 1691 200 Script output follows
1646 1692
1647 1693 index file
1648 1694
1649 1695 Repos named 'index' take precedence over the index file
1650 1696
1651 1697 $ get-with-headers.py localhost:$HGPORT1 'dir1/dir2/index' | grep 'index'
1652 1698 <link rel="icon" href="/dir1/dir2/index/static/hgicon.png" type="image/png" />
1653 1699 <meta name="robots" content="index, nofollow" />
1654 1700 <link rel="stylesheet" href="/dir1/dir2/index/static/style-paper.css" type="text/css" />
1655 1701 <script type="text/javascript" src="/dir1/dir2/index/static/mercurial.js"></script>
1656 1702 <title>dir1/dir2/index: log</title>
1657 1703 href="/dir1/dir2/index/atom-log" title="Atom feed for dir1/dir2/index" />
1658 1704 href="/dir1/dir2/index/rss-log" title="RSS feed for dir1/dir2/index" />
1659 1705 <img src="/dir1/dir2/index/static/hglogo.png" alt="mercurial" /></a>
1660 1706 <li><a href="/dir1/dir2/index/graph/tip">graph</a></li>
1661 1707 <li><a href="/dir1/dir2/index/tags">tags</a></li>
1662 1708 <li><a href="/dir1/dir2/index/bookmarks">bookmarks</a></li>
1663 1709 <li><a href="/dir1/dir2/index/branches">branches</a></li>
1664 1710 <li><a href="/dir1/dir2/index/rev/tip">changeset</a></li>
1665 1711 <li><a href="/dir1/dir2/index/file/tip">browse</a></li>
1666 1712 <li><a href="/dir1/dir2/index/help">help</a></li>
1667 1713 <a href="/dir1/dir2/index/atom-log" title="subscribe to atom feed">
1668 1714 <img class="atom-logo" src="/dir1/dir2/index/static/feed-icon-14x14.png" alt="atom feed" />
1669 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>
1670 1716 <form class="search" action="/dir1/dir2/index/log">
1671 1717 number or hash, or <a href="/dir1/dir2/index/help/revsets">revset expression</a>.</div>
1672 1718 <a href="/dir1/dir2/index/shortlog/tip?revcount=30">less</a>
1673 1719 <a href="/dir1/dir2/index/shortlog/tip?revcount=120">more</a>
1674 1720 | rev 0: <a href="/dir1/dir2/index/shortlog/39505516671b">(0)</a> <a href="/dir1/dir2/index/shortlog/tip">tip</a>
1675 1721 <a href="/dir1/dir2/index/rev/39505516671b">b</a>
1676 1722 <a href="/dir1/dir2/index/shortlog/tip?revcount=30">less</a>
1677 1723 <a href="/dir1/dir2/index/shortlog/tip?revcount=120">more</a>
1678 1724 | rev 0: <a href="/dir1/dir2/index/shortlog/39505516671b">(0)</a> <a href="/dir1/dir2/index/shortlog/tip">tip</a>
1679 1725 '/dir1/dir2/index/shortlog/%next%',
1680 1726
1681 1727 $ killdaemons.py
1682 1728
1683 1729 $ cat > paths.conf << EOF
1684 1730 > [paths]
1685 1731 > / = $root/a
1686 1732 > EOF
1687 1733 $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf
1688 1734 $ cat hg.pid >> $DAEMON_PIDS
1689 1735
1690 1736 $ hg id http://localhost:$HGPORT1
1691 1737 71a89161f014
1692 1738
1693 1739 $ get-with-headers.py localhost:$HGPORT1 '' | grep 'index'
1694 1740 <meta name="robots" content="index, nofollow" />
1695 1741 <a href="/rev/71a89161f014">add index file</a>
1696 1742
1697 1743 $ killdaemons.py
1698 1744
1699 1745 paths errors 1
1700 1746
1701 1747 $ cat error-paths-1.log
1702 1748
1703 1749 paths errors 2
1704 1750
1705 1751 $ cat error-paths-2.log
1706 1752
1707 1753 paths errors 3
1708 1754
1709 1755 $ cat error-paths-3.log
1710 1756
1711 1757 paths errors 4
1712 1758
1713 1759 $ cat error-paths-4.log
1714 1760
1715 1761 paths errors 5
1716 1762
1717 1763 $ cat error-paths-5.log
1718 1764
1719 1765 paths errors 6
1720 1766
1721 1767 $ cat error-paths-6.log
1722 1768
1723 1769 paths errors 7
1724 1770
1725 1771 $ cat error-paths-7.log
1726 1772
1727 1773 paths errors 8
1728 1774
1729 1775 $ cat error-paths-8.log
1730 1776
1731 1777 paths errors 9
1732 1778
1733 1779 $ cat error-paths-9.log
1734 1780
1735 1781 paths errors 10
1736 1782
1737 1783 $ cat error-paths-10.log
1738 1784
1739 1785 collections errors
1740 1786
1741 1787 $ cat error-collections.log
1742 1788
1743 1789 collections errors 2
1744 1790
1745 1791 $ cat error-collections-2.log
General Comments 0
You need to be logged in to leave comments. Login now