mercurial/hgweb/webcommands.py
changeset 6393 894875eae49b
parent 6392 2540521dc7c1
child 6410 644a56c7ae79
equal deleted inserted replaced
6392:2540521dc7c1 6393:894875eae49b
     3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
     3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
     4 #
     4 #
     5 # This software may be used and distributed according to the terms
     5 # This software may be used and distributed according to the terms
     6 # of the GNU General Public License, incorporated herein by reference.
     6 # of the GNU General Public License, incorporated herein by reference.
     7 
     7 
     8 import os, mimetypes
     8 import os, mimetypes, re
     9 import webutil
     9 import webutil
    10 from mercurial import revlog
    10 from mercurial import revlog, archival
       
    11 from mercurial.node import hex, nullid
    11 from mercurial.util import binary
    12 from mercurial.util import binary
    12 from mercurial.repo import RepoError
    13 from mercurial.repo import RepoError
    13 from common import staticfile, ErrorResponse, HTTP_OK, HTTP_NOT_FOUND
    14 from common import paritygen, staticfile, get_contact, ErrorResponse
       
    15 from common import HTTP_OK, HTTP_NOT_FOUND
    14 
    16 
    15 # __all__ is populated with the allowed commands. Be sure to add to it if
    17 # __all__ is populated with the allowed commands. Be sure to add to it if
    16 # you're adding a new command, or the new command won't work.
    18 # you're adding a new command, or the new command won't work.
    17 
    19 
    18 __all__ = [
    20 __all__ = [
    28         return changelog(web, req, tmpl)
    30         return changelog(web, req, tmpl)
    29 
    31 
    30 def rawfile(web, req, tmpl):
    32 def rawfile(web, req, tmpl):
    31     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
    33     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
    32     if not path:
    34     if not path:
    33         content = web.manifest(tmpl, webutil.changectx(web.repo, req), path)
    35         content = manifest(web, req, tmpl)
    34         req.respond(HTTP_OK, web.ctype)
    36         req.respond(HTTP_OK, web.ctype)
    35         return content
    37         return content
    36 
    38 
    37     try:
    39     try:
    38         fctx = webutil.filectx(web.repo, req)
    40         fctx = webutil.filectx(web.repo, req)
    39     except revlog.LookupError, inst:
    41     except revlog.LookupError, inst:
    40         try:
    42         try:
    41             content = web.manifest(tmpl, webutil.changectx(web.repo, req), path)
    43             content = manifest(web, req, tmpl)
    42             req.respond(HTTP_OK, web.ctype)
    44             req.respond(HTTP_OK, web.ctype)
    43             return content
    45             return content
    44         except ErrorResponse:
    46         except ErrorResponse:
    45             raise inst
    47             raise inst
    46 
    48 
    51         mt = mt or 'application/octet-stream'
    53         mt = mt or 'application/octet-stream'
    52 
    54 
    53     req.respond(HTTP_OK, mt, path, len(text))
    55     req.respond(HTTP_OK, mt, path, len(text))
    54     return [text]
    56     return [text]
    55 
    57 
       
    58 def _filerevision(web, tmpl, fctx):
       
    59     f = fctx.path()
       
    60     text = fctx.data()
       
    61     fl = fctx.filelog()
       
    62     n = fctx.filenode()
       
    63     parity = paritygen(web.stripecount)
       
    64 
       
    65     if binary(text):
       
    66         mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
       
    67         text = '(binary:%s)' % mt
       
    68 
       
    69     def lines():
       
    70         for lineno, t in enumerate(text.splitlines(1)):
       
    71             yield {"line": t,
       
    72                    "lineid": "l%d" % (lineno + 1),
       
    73                    "linenumber": "% 6d" % (lineno + 1),
       
    74                    "parity": parity.next()}
       
    75 
       
    76     return tmpl("filerevision",
       
    77                 file=f,
       
    78                 path=webutil.up(f),
       
    79                 text=lines(),
       
    80                 rev=fctx.rev(),
       
    81                 node=hex(fctx.node()),
       
    82                 author=fctx.user(),
       
    83                 date=fctx.date(),
       
    84                 desc=fctx.description(),
       
    85                 branch=webutil.nodebranchnodefault(fctx),
       
    86                 parent=webutil.siblings(fctx.parents()),
       
    87                 child=webutil.siblings(fctx.children()),
       
    88                 rename=webutil.renamelink(fl, n),
       
    89                 permissions=fctx.manifest().flags(f))
       
    90 
    56 def file(web, req, tmpl):
    91 def file(web, req, tmpl):
    57     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
    92     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
    58     if path:
    93     if path:
    59         try:
    94         try:
    60             return web.filerevision(tmpl, webutil.filectx(web.repo, req))
    95             return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
    61         except revlog.LookupError, inst:
    96         except revlog.LookupError, inst:
    62             pass
    97             pass
    63 
    98 
    64     try:
    99     try:
    65         return web.manifest(tmpl, webutil.changectx(web.repo, req), path)
   100         return manifest(web, req, tmpl)
    66     except ErrorResponse:
   101     except ErrorResponse:
    67         raise inst
   102         raise inst
       
   103 
       
   104 def _search(web, tmpl, query):
       
   105 
       
   106     def changelist(**map):
       
   107         cl = web.repo.changelog
       
   108         count = 0
       
   109         qw = query.lower().split()
       
   110 
       
   111         def revgen():
       
   112             for i in xrange(cl.count() - 1, 0, -100):
       
   113                 l = []
       
   114                 for j in xrange(max(0, i - 100), i + 1):
       
   115                     ctx = web.repo.changectx(j)
       
   116                     l.append(ctx)
       
   117                 l.reverse()
       
   118                 for e in l:
       
   119                     yield e
       
   120 
       
   121         for ctx in revgen():
       
   122             miss = 0
       
   123             for q in qw:
       
   124                 if not (q in ctx.user().lower() or
       
   125                         q in ctx.description().lower() or
       
   126                         q in " ".join(ctx.files()).lower()):
       
   127                     miss = 1
       
   128                     break
       
   129             if miss:
       
   130                 continue
       
   131 
       
   132             count = 1
       
   133             n = ctx.node()
       
   134             showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
       
   135 
       
   136             yield tmpl('searchentry',
       
   137                        parity=parity.next(),
       
   138                        author=ctx.user(),
       
   139                        parent=webutil.siblings(ctx.parents()),
       
   140                        child=webutil.siblings(ctx.children()),
       
   141                        changelogtag=showtags,
       
   142                        desc=ctx.description(),
       
   143                        date=ctx.date(),
       
   144                        files=web.listfilediffs(tmpl, ctx.files(), n),
       
   145                        rev=ctx.rev(),
       
   146                        node=hex(n),
       
   147                        tags=webutil.nodetagsdict(web.repo, n),
       
   148                        inbranch=webutil.nodeinbranch(web.repo, ctx),
       
   149                        branches=webutil.nodebranchdict(web.repo, ctx))
       
   150 
       
   151             if count >= web.maxchanges:
       
   152                 break
       
   153 
       
   154     cl = web.repo.changelog
       
   155     parity = paritygen(web.stripecount)
       
   156 
       
   157     return tmpl('search',
       
   158                 query=query,
       
   159                 node=hex(cl.tip()),
       
   160                 entries=changelist,
       
   161                 archives=web.archivelist("tip"))
    68 
   162 
    69 def changelog(web, req, tmpl, shortlog = False):
   163 def changelog(web, req, tmpl, shortlog = False):
    70     if 'node' in req.form:
   164     if 'node' in req.form:
    71         ctx = webutil.changectx(web.repo, req)
   165         ctx = webutil.changectx(web.repo, req)
    72     else:
   166     else:
    75         else:
   169         else:
    76             hi = web.repo.changelog.count() - 1
   170             hi = web.repo.changelog.count() - 1
    77         try:
   171         try:
    78             ctx = web.repo.changectx(hi)
   172             ctx = web.repo.changectx(hi)
    79         except RepoError:
   173         except RepoError:
    80             return web.search(tmpl, hi) # XXX redirect to 404 page?
   174             return _search(web, tmpl, hi) # XXX redirect to 404 page?
    81 
   175 
    82     return web.changelog(tmpl, ctx, shortlog = shortlog)
   176     def changelist(limit=0, **map):
       
   177         cl = web.repo.changelog
       
   178         l = [] # build a list in forward order for efficiency
       
   179         for i in xrange(start, end):
       
   180             ctx = web.repo.changectx(i)
       
   181             n = ctx.node()
       
   182             showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
       
   183 
       
   184             l.insert(0, {"parity": parity.next(),
       
   185                          "author": ctx.user(),
       
   186                          "parent": webutil.siblings(ctx.parents(), i - 1),
       
   187                          "child": webutil.siblings(ctx.children(), i + 1),
       
   188                          "changelogtag": showtags,
       
   189                          "desc": ctx.description(),
       
   190                          "date": ctx.date(),
       
   191                          "files": web.listfilediffs(tmpl, ctx.files(), n),
       
   192                          "rev": i,
       
   193                          "node": hex(n),
       
   194                          "tags": webutil.nodetagsdict(web.repo, n),
       
   195                          "inbranch": webutil.nodeinbranch(web.repo, ctx),
       
   196                          "branches": webutil.nodebranchdict(web.repo, ctx)
       
   197                         })
       
   198 
       
   199         if limit > 0:
       
   200             l = l[:limit]
       
   201 
       
   202         for e in l:
       
   203             yield e
       
   204 
       
   205     maxchanges = shortlog and web.maxshortchanges or web.maxchanges
       
   206     cl = web.repo.changelog
       
   207     count = cl.count()
       
   208     pos = ctx.rev()
       
   209     start = max(0, pos - maxchanges + 1)
       
   210     end = min(count, start + maxchanges)
       
   211     pos = end - 1
       
   212     parity = paritygen(web.stripecount, offset=start-end)
       
   213 
       
   214     changenav = webutil.revnavgen(pos, maxchanges, count, web.repo.changectx)
       
   215 
       
   216     return tmpl(shortlog and 'shortlog' or 'changelog',
       
   217                 changenav=changenav,
       
   218                 node=hex(cl.tip()),
       
   219                 rev=pos, changesets=count,
       
   220                 entries=lambda **x: changelist(limit=0,**x),
       
   221                 latestentry=lambda **x: changelist(limit=1,**x),
       
   222                 archives=web.archivelist("tip"))
    83 
   223 
    84 def shortlog(web, req, tmpl):
   224 def shortlog(web, req, tmpl):
    85     return changelog(web, req, tmpl, shortlog = True)
   225     return changelog(web, req, tmpl, shortlog = True)
    86 
   226 
    87 def changeset(web, req, tmpl):
   227 def changeset(web, req, tmpl):
    88     return web.changeset(tmpl, webutil.changectx(web.repo, req))
   228     ctx = webutil.changectx(web.repo, req)
       
   229     n = ctx.node()
       
   230     showtags = webutil.showtag(web.repo, tmpl, 'changesettag', n)
       
   231     parents = ctx.parents()
       
   232     p1 = parents[0].node()
       
   233 
       
   234     files = []
       
   235     parity = paritygen(web.stripecount)
       
   236     for f in ctx.files():
       
   237         files.append(tmpl("filenodelink",
       
   238                           node=hex(n), file=f,
       
   239                           parity=parity.next()))
       
   240 
       
   241     diffs = web.diff(tmpl, p1, n, None)
       
   242     return tmpl('changeset',
       
   243                 diff=diffs,
       
   244                 rev=ctx.rev(),
       
   245                 node=hex(n),
       
   246                 parent=webutil.siblings(parents),
       
   247                 child=webutil.siblings(ctx.children()),
       
   248                 changesettag=showtags,
       
   249                 author=ctx.user(),
       
   250                 desc=ctx.description(),
       
   251                 date=ctx.date(),
       
   252                 files=files,
       
   253                 archives=web.archivelist(hex(n)),
       
   254                 tags=webutil.nodetagsdict(web.repo, n),
       
   255                 branch=webutil.nodebranchnodefault(ctx),
       
   256                 inbranch=webutil.nodeinbranch(web.repo, ctx),
       
   257                 branches=webutil.nodebranchdict(web.repo, ctx))
    89 
   258 
    90 rev = changeset
   259 rev = changeset
    91 
   260 
    92 def manifest(web, req, tmpl):
   261 def manifest(web, req, tmpl):
    93     return web.manifest(tmpl, webutil.changectx(web.repo, req),
   262     ctx = webutil.changectx(web.repo, req)
    94                         webutil.cleanpath(web.repo, req.form['path'][0]))
   263     path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
       
   264     mf = ctx.manifest()
       
   265     node = ctx.node()
       
   266 
       
   267     files = {}
       
   268     parity = paritygen(web.stripecount)
       
   269 
       
   270     if path and path[-1] != "/":
       
   271         path += "/"
       
   272     l = len(path)
       
   273     abspath = "/" + path
       
   274 
       
   275     for f, n in mf.items():
       
   276         if f[:l] != path:
       
   277             continue
       
   278         remain = f[l:]
       
   279         if "/" in remain:
       
   280             short = remain[:remain.index("/") + 1] # bleah
       
   281             files[short] = (f, None)
       
   282         else:
       
   283             short = os.path.basename(remain)
       
   284             files[short] = (f, n)
       
   285 
       
   286     if not files:
       
   287         raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
       
   288 
       
   289     def filelist(**map):
       
   290         fl = files.keys()
       
   291         fl.sort()
       
   292         for f in fl:
       
   293             full, fnode = files[f]
       
   294             if not fnode:
       
   295                 continue
       
   296 
       
   297             fctx = ctx.filectx(full)
       
   298             yield {"file": full,
       
   299                    "parity": parity.next(),
       
   300                    "basename": f,
       
   301                    "date": fctx.changectx().date(),
       
   302                    "size": fctx.size(),
       
   303                    "permissions": mf.flags(full)}
       
   304 
       
   305     def dirlist(**map):
       
   306         fl = files.keys()
       
   307         fl.sort()
       
   308         for f in fl:
       
   309             full, fnode = files[f]
       
   310             if fnode:
       
   311                 continue
       
   312 
       
   313             yield {"parity": parity.next(),
       
   314                    "path": "%s%s" % (abspath, f),
       
   315                    "basename": f[:-1]}
       
   316 
       
   317     return tmpl("manifest",
       
   318                 rev=ctx.rev(),
       
   319                 node=hex(node),
       
   320                 path=abspath,
       
   321                 up=webutil.up(abspath),
       
   322                 upparity=parity.next(),
       
   323                 fentries=filelist,
       
   324                 dentries=dirlist,
       
   325                 archives=web.archivelist(hex(node)),
       
   326                 tags=webutil.nodetagsdict(web.repo, node),
       
   327                 inbranch=webutil.nodeinbranch(web.repo, ctx),
       
   328                 branches=webutil.nodebranchdict(web.repo, ctx))
    95 
   329 
    96 def tags(web, req, tmpl):
   330 def tags(web, req, tmpl):
    97     return web.tags(tmpl)
   331     i = web.repo.tagslist()
       
   332     i.reverse()
       
   333     parity = paritygen(web.stripecount)
       
   334 
       
   335     def entries(notip=False,limit=0, **map):
       
   336         count = 0
       
   337         for k, n in i:
       
   338             if notip and k == "tip":
       
   339                 continue
       
   340             if limit > 0 and count >= limit:
       
   341                 continue
       
   342             count = count + 1
       
   343             yield {"parity": parity.next(),
       
   344                    "tag": k,
       
   345                    "date": web.repo.changectx(n).date(),
       
   346                    "node": hex(n)}
       
   347 
       
   348     return tmpl("tags",
       
   349                 node=hex(web.repo.changelog.tip()),
       
   350                 entries=lambda **x: entries(False,0, **x),
       
   351                 entriesnotip=lambda **x: entries(True,0, **x),
       
   352                 latestentry=lambda **x: entries(True,1, **x))
    98 
   353 
    99 def summary(web, req, tmpl):
   354 def summary(web, req, tmpl):
   100     return web.summary(tmpl)
   355     i = web.repo.tagslist()
       
   356     i.reverse()
       
   357 
       
   358     def tagentries(**map):
       
   359         parity = paritygen(web.stripecount)
       
   360         count = 0
       
   361         for k, n in i:
       
   362             if k == "tip": # skip tip
       
   363                 continue
       
   364 
       
   365             count = 1
       
   366             if count > 10: # limit to 10 tags
       
   367                 break
       
   368 
       
   369             yield tmpl("tagentry",
       
   370                        parity=parity.next(),
       
   371                        tag=k,
       
   372                        node=hex(n),
       
   373                        date=web.repo.changectx(n).date())
       
   374 
       
   375     def branches(**map):
       
   376         parity = paritygen(web.stripecount)
       
   377 
       
   378         b = web.repo.branchtags()
       
   379         l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.items()]
       
   380         l.sort()
       
   381 
       
   382         for r,n,t in l:
       
   383             ctx = web.repo.changectx(n)
       
   384             yield {'parity': parity.next(),
       
   385                    'branch': t,
       
   386                    'node': hex(n),
       
   387                    'date': ctx.date()}
       
   388 
       
   389     def changelist(**map):
       
   390         parity = paritygen(web.stripecount, offset=start-end)
       
   391         l = [] # build a list in forward order for efficiency
       
   392         for i in xrange(start, end):
       
   393             ctx = web.repo.changectx(i)
       
   394             n = ctx.node()
       
   395             hn = hex(n)
       
   396 
       
   397             l.insert(0, tmpl(
       
   398                'shortlogentry',
       
   399                 parity=parity.next(),
       
   400                 author=ctx.user(),
       
   401                 desc=ctx.description(),
       
   402                 date=ctx.date(),
       
   403                 rev=i,
       
   404                 node=hn,
       
   405                 tags=webutil.nodetagsdict(web.repo, n),
       
   406                 inbranch=webutil.nodeinbranch(web.repo, ctx),
       
   407                 branches=webutil.nodebranchdict(web.repo, ctx)))
       
   408 
       
   409         yield l
       
   410 
       
   411     cl = web.repo.changelog
       
   412     count = cl.count()
       
   413     start = max(0, count - web.maxchanges)
       
   414     end = min(count, start + web.maxchanges)
       
   415 
       
   416     return tmpl("summary",
       
   417                 desc=web.config("web", "description", "unknown"),
       
   418                 owner=get_contact(web.config) or "unknown",
       
   419                 lastchange=cl.read(cl.tip())[2],
       
   420                 tags=tagentries,
       
   421                 branches=branches,
       
   422                 shortlog=changelist,
       
   423                 node=hex(cl.tip()),
       
   424                 archives=web.archivelist("tip"))
   101 
   425 
   102 def filediff(web, req, tmpl):
   426 def filediff(web, req, tmpl):
   103     return web.filediff(tmpl, webutil.filectx(web.repo, req))
   427     fctx = webutil.filectx(web.repo, req)
       
   428     n = fctx.node()
       
   429     path = fctx.path()
       
   430     parents = fctx.parents()
       
   431     p1 = parents and parents[0].node() or nullid
       
   432 
       
   433     diffs = web.diff(tmpl, p1, n, [path])
       
   434     return tmpl("filediff",
       
   435                 file=path,
       
   436                 node=hex(n),
       
   437                 rev=fctx.rev(),
       
   438                 branch=webutil.nodebranchnodefault(fctx),
       
   439                 parent=webutil.siblings(parents),
       
   440                 child=webutil.siblings(fctx.children()),
       
   441                 diff=diffs)
   104 
   442 
   105 diff = filediff
   443 diff = filediff
   106 
   444 
   107 def annotate(web, req, tmpl):
   445 def annotate(web, req, tmpl):
   108     return web.fileannotate(tmpl, webutil.filectx(web.repo, req))
   446     fctx = webutil.filectx(web.repo, req)
       
   447     f = fctx.path()
       
   448     n = fctx.filenode()
       
   449     fl = fctx.filelog()
       
   450     parity = paritygen(web.stripecount)
       
   451 
       
   452     def annotate(**map):
       
   453         last = None
       
   454         if binary(fctx.data()):
       
   455             mt = (mimetypes.guess_type(fctx.path())[0]
       
   456                   or 'application/octet-stream')
       
   457             lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
       
   458                                 '(binary:%s)' % mt)])
       
   459         else:
       
   460             lines = enumerate(fctx.annotate(follow=True, linenumber=True))
       
   461         for lineno, ((f, targetline), l) in lines:
       
   462             fnode = f.filenode()
       
   463             name = web.repo.ui.shortuser(f.user())
       
   464 
       
   465             if last != fnode:
       
   466                 last = fnode
       
   467 
       
   468             yield {"parity": parity.next(),
       
   469                    "node": hex(f.node()),
       
   470                    "rev": f.rev(),
       
   471                    "author": name,
       
   472                    "file": f.path(),
       
   473                    "targetline": targetline,
       
   474                    "line": l,
       
   475                    "lineid": "l%d" % (lineno + 1),
       
   476                    "linenumber": "% 6d" % (lineno + 1)}
       
   477 
       
   478     return tmpl("fileannotate",
       
   479                 file=f,
       
   480                 annotate=annotate,
       
   481                 path=webutil.up(f),
       
   482                 rev=fctx.rev(),
       
   483                 node=hex(fctx.node()),
       
   484                 author=fctx.user(),
       
   485                 date=fctx.date(),
       
   486                 desc=fctx.description(),
       
   487                 rename=webutil.renamelink(fl, n),
       
   488                 branch=webutil.nodebranchnodefault(fctx),
       
   489                 parent=webutil.siblings(fctx.parents()),
       
   490                 child=webutil.siblings(fctx.children()),
       
   491                 permissions=fctx.manifest().flags(f))
   109 
   492 
   110 def filelog(web, req, tmpl):
   493 def filelog(web, req, tmpl):
   111     return web.filelog(tmpl, webutil.filectx(web.repo, req))
   494     fctx = webutil.filectx(web.repo, req)
       
   495     f = fctx.path()
       
   496     fl = fctx.filelog()
       
   497     count = fl.count()
       
   498     pagelen = web.maxshortchanges
       
   499     pos = fctx.filerev()
       
   500     start = max(0, pos - pagelen + 1)
       
   501     end = min(count, start + pagelen)
       
   502     pos = end - 1
       
   503     parity = paritygen(web.stripecount, offset=start-end)
       
   504 
       
   505     def entries(limit=0, **map):
       
   506         l = []
       
   507 
       
   508         for i in xrange(start, end):
       
   509             ctx = fctx.filectx(i)
       
   510             n = fl.node(i)
       
   511 
       
   512             l.insert(0, {"parity": parity.next(),
       
   513                          "filerev": i,
       
   514                          "file": f,
       
   515                          "node": hex(ctx.node()),
       
   516                          "author": ctx.user(),
       
   517                          "date": ctx.date(),
       
   518                          "rename": webutil.renamelink(fl, n),
       
   519                          "parent": webutil.siblings(fctx.parents()),
       
   520                          "child": webutil.siblings(fctx.children()),
       
   521                          "desc": ctx.description()})
       
   522 
       
   523         if limit > 0:
       
   524             l = l[:limit]
       
   525 
       
   526         for e in l:
       
   527             yield e
       
   528 
       
   529     nodefunc = lambda x: fctx.filectx(fileid=x)
       
   530     nav = webutil.revnavgen(pos, pagelen, count, nodefunc)
       
   531     return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
       
   532                 entries=lambda **x: entries(limit=0, **x),
       
   533                 latestentry=lambda **x: entries(limit=1, **x))
       
   534 
   112 
   535 
   113 def archive(web, req, tmpl):
   536 def archive(web, req, tmpl):
   114     type_ = req.form['type'][0]
   537     type_ = req.form['type'][0]
   115     allowed = web.configlist("web", "allow_archive")
   538     allowed = web.configlist("web", "allow_archive")
   116     if (type_ in web.archives and (type_ in allowed or
   539     key = req.form['node'][0]
       
   540 
       
   541     if not (type_ in web.archives and (type_ in allowed or
   117         web.configbool("web", "allow" + type_, False))):
   542         web.configbool("web", "allow" + type_, False))):
   118         web.archive(tmpl, req, req.form['node'][0], type_)
   543         msg = 'Unsupported archive type: %s' % type_
   119         return []
   544         raise ErrorResponse(HTTP_NOT_FOUND, msg)
   120     raise ErrorResponse(HTTP_NOT_FOUND, 'unsupported archive type: %s' % type_)
   545 
       
   546     reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
       
   547     cnode = web.repo.lookup(key)
       
   548     arch_version = key
       
   549     if cnode == key or key == 'tip':
       
   550         arch_version = short(cnode)
       
   551     name = "%s-%s" % (reponame, arch_version)
       
   552     mimetype, artype, extension, encoding = web.archive_specs[type_]
       
   553     headers = [
       
   554         ('Content-Type', mimetype),
       
   555         ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
       
   556     ]
       
   557     if encoding:
       
   558         headers.append(('Content-Encoding', encoding))
       
   559     req.header(headers)
       
   560     req.respond(HTTP_OK)
       
   561     archival.archive(web.repo, req, cnode, artype, prefix=name)
       
   562     return []
       
   563 
   121 
   564 
   122 def static(web, req, tmpl):
   565 def static(web, req, tmpl):
   123     fname = req.form['file'][0]
   566     fname = req.form['file'][0]
   124     # a repo owner may set web.static in .hg/hgrc to get any file
   567     # a repo owner may set web.static in .hg/hgrc to get any file
   125     # readable by the user running the CGI script
   568     # readable by the user running the CGI script