mercurial/hgweb/hgweb_mod.py
author Gregory Szorc <gregory.szorc@gmail.com>
Sat, 22 Aug 2015 15:12:52 -0700
changeset 26136 6defc74f3066
parent 26135 edfb4d3b9672
child 26138 f77a3f27cea5
permissions -rw-r--r--
hgweb: move archive related attributes to requestcontext As part of this, "archive_specs" was renamed to "archivespecs" to align with naming conventions. "archive_specs" didn't technically need to be moved from hgweb. But it seemed to make sense to have all the archive code in the same class. As part of this, hgweb.configlist is no longer used, so it was deleted.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2391
d351a3be3371 Fixing up comment headers for split up code.
Eric Hopper <hopper@omnifarious.org>
parents: 2361
diff changeset
     1
# hgweb/hgweb_mod.py - Web interface for a repository.
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     2
#
238
3b92f8fe47ae hgweb.py: kill #! line, clean up copyright notice
mpm@selenic.com
parents: 222
diff changeset
     3
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4539
diff changeset
     4
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     5
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8191
diff changeset
     6
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9842
diff changeset
     7
# GNU General Public License version 2 or any later version.
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     8
20034
1e5b38a919dd cleanup: move stdlib imports to their own import statement
Augie Fackler <raf@durin42.com>
parents: 19906
diff changeset
     9
import os, re
18522
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
    10
from mercurial import ui, hg, hook, error, encoding, templater, util, repoview
18627
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
    11
from mercurial.templatefilters import websub
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
    12
from mercurial.i18n import _
13958
71f51cc71652 hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents: 13445
diff changeset
    13
from common import get_stat, ErrorResponse, permhooks, caching
12739
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 12696
diff changeset
    14
from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 12696
diff changeset
    15
from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
5566
d74fc8dec2b4 Less indirection in the WSGI web interface. This simplifies some code, and makes it more compliant with WSGI.
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5565
diff changeset
    16
from request import wsgirequest
20034
1e5b38a919dd cleanup: move stdlib imports to their own import statement
Augie Fackler <raf@durin42.com>
parents: 19906
diff changeset
    17
import webcommands, protocol, webutil
138
c77a679e9cfa Revamped templated hgweb
mpm@selenic.com
parents: 137
diff changeset
    18
6779
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6777
diff changeset
    19
perms = {
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6777
diff changeset
    20
    'changegroup': 'pull',
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6777
diff changeset
    21
    'changegroupsubset': 'pull',
13741
b51bf961b3cb wireproto: add getbundle() function
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13571
diff changeset
    22
    'getbundle': 'pull',
11370
db3f6f0e4e7d pushkey: add http support
Matt Mackall <mpm@selenic.com>
parents: 10995
diff changeset
    23
    'stream_out': 'pull',
db3f6f0e4e7d pushkey: add http support
Matt Mackall <mpm@selenic.com>
parents: 10995
diff changeset
    24
    'listkeys': 'pull',
6779
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6777
diff changeset
    25
    'unbundle': 'push',
11370
db3f6f0e4e7d pushkey: add http support
Matt Mackall <mpm@selenic.com>
parents: 10995
diff changeset
    26
    'pushkey': 'push',
6779
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6777
diff changeset
    27
}
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6777
diff changeset
    28
25718
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
    29
## Files of interest
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
    30
# Used to check if the repository has changed looking at mtime and size of
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
    31
# theses files. This should probably be relocated a bit higher in core.
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
    32
foi = [('spath', '00changelog.i'),
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
    33
       ('spath', 'phaseroots'), # ! phase can change content at the same size
25719
c51a18609a7f hgweb: also refresh the repo on changes to the obsstore
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25718
diff changeset
    34
       ('spath', 'obsstore'),
25720
bd2e171d023b hgweb: also monitor change to bookmarks
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25719
diff changeset
    35
       ('path', 'bookmarks'), # ! bookmark can change content at the same size
25718
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
    36
      ]
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
    37
18515
bf8bbbf4aa45 hgwebdir: use web.prefix when creating url breadcrumbs (issue3790)
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18429
diff changeset
    38
def makebreadcrumb(url, prefix=''):
18258
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    39
    '''Return a 'URL breadcrumb' list
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    40
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    41
    A 'URL breadcrumb' is a list of URL-name pairs,
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    42
    corresponding to each of the path items on a URL.
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    43
    This can be used to create path navigation entries.
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    44
    '''
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    45
    if url.endswith('/'):
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    46
        url = url[:-1]
18515
bf8bbbf4aa45 hgwebdir: use web.prefix when creating url breadcrumbs (issue3790)
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18429
diff changeset
    47
    if prefix:
bf8bbbf4aa45 hgwebdir: use web.prefix when creating url breadcrumbs (issue3790)
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18429
diff changeset
    48
        url = '/' + prefix + url
18258
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    49
    relpath = url
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    50
    if relpath.startswith('/'):
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    51
        relpath = relpath[1:]
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    52
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    53
    breadcrumb = []
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    54
    urlel = url
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    55
    pathitems = [''] + relpath.split('/')
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    56
    for pathel in reversed(pathitems):
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    57
        if not pathel or not urlel:
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    58
            break
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    59
        breadcrumb.append({'url': urlel, 'name': pathel})
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    60
        urlel = os.path.dirname(urlel)
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    61
    return reversed(breadcrumb)
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    62
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
    63
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    64
class requestcontext(object):
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    65
    """Holds state/context for an individual request.
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    66
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    67
    Servers can be multi-threaded. Holding state on the WSGI application
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    68
    is prone to race conditions. Instances of this class exist to hold
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    69
    mutable and race-free state for requests.
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    70
    """
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    71
    def __init__(self, app):
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    72
        object.__setattr__(self, 'app', app)
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    73
        object.__setattr__(self, 'repo', app.repo)
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    74
26136
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
    75
        object.__setattr__(self, 'archives', ('zip', 'gz', 'bz2'))
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
    76
26135
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    77
        object.__setattr__(self, 'maxchanges',
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    78
                           self.configint('web', 'maxchanges', 10))
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    79
        object.__setattr__(self, 'stripecount',
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    80
                           self.configint('web', 'stripes', 1))
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    81
        object.__setattr__(self, 'maxshortchanges',
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    82
                           self.configint('web', 'maxshortchanges', 60))
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    83
        object.__setattr__(self, 'maxfiles',
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    84
                           self.configint('web', 'maxfiles', 10))
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    85
        object.__setattr__(self, 'allowpull',
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    86
                           self.configbool('web', 'allowpull', True))
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    87
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    88
    # Proxy unknown reads and writes to the application instance
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    89
    # until everything is moved to us.
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    90
    def __getattr__(self, name):
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    91
        return getattr(self.app, name)
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    92
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    93
    def __setattr__(self, name, value):
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    94
        return setattr(self.app, name, value)
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
    95
26135
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    96
    # Servers are often run by a user different from the repo owner.
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    97
    # Trust the settings from the .hg/hgrc files by default.
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    98
    def config(self, section, name, default=None, untrusted=True):
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
    99
        return self.repo.ui.config(section, name, default,
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   100
                                   untrusted=untrusted)
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   101
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   102
    def configbool(self, section, name, default=False, untrusted=True):
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   103
        return self.repo.ui.configbool(section, name, default,
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   104
                                       untrusted=untrusted)
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   105
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   106
    def configint(self, section, name, default=None, untrusted=True):
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   107
        return self.repo.ui.configint(section, name, default,
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   108
                                      untrusted=untrusted)
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   109
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   110
    def configlist(self, section, name, default=None, untrusted=True):
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   111
        return self.repo.ui.configlist(section, name, default,
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   112
                                       untrusted=untrusted)
edfb4d3b9672 hgweb: move some config options to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26134
diff changeset
   113
26136
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   114
    archivespecs = {
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   115
        'bz2': ('application/x-bzip2', 'tbz2', '.tar.bz2', None),
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   116
        'gz': ('application/x-gzip', 'tgz', '.tar.gz', None),
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   117
        'zip': ('application/zip', 'zip', '.zip', None),
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   118
    }
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   119
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   120
    def archivelist(self, nodeid):
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   121
        allowed = self.configlist('web', 'allow_archive')
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   122
        for typ, spec in self.archivespecs.iteritems():
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   123
            if typ in allowed or self.configbool('web', 'allow%s' % typ):
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   124
                yield {'type': typ, 'extension': spec[2], 'node': nodeid}
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   125
1559
59b3639df0a9 Convert all classes to new-style classes by deriving them from object.
Eric Hopper <hopper@omnifarious.org>
parents: 1554
diff changeset
   126
class hgweb(object):
26132
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   127
    """HTTP server for individual repositories.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   128
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   129
    Instances of this class serve HTTP responses for a particular
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   130
    repository.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   131
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   132
    Instances are typically used as WSGI applications.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   133
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   134
    Some servers are multi-threaded. On these servers, there may
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   135
    be multiple active threads inside __call__.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   136
    """
10994
c12a57c1a67e hgweb: add baseui to hgweb entrypoint
Matt Mackall <mpm@selenic.com>
parents: 10905
diff changeset
   137
    def __init__(self, repo, name=None, baseui=None):
4874
d9e385a7a806 Use isinstance instead of type == type
Christian Ebert <blacktrash@gmx.net>
parents: 4872
diff changeset
   138
        if isinstance(repo, str):
10994
c12a57c1a67e hgweb: add baseui to hgweb entrypoint
Matt Mackall <mpm@selenic.com>
parents: 10905
diff changeset
   139
            if baseui:
c12a57c1a67e hgweb: add baseui to hgweb entrypoint
Matt Mackall <mpm@selenic.com>
parents: 10905
diff changeset
   140
                u = baseui.copy()
c12a57c1a67e hgweb: add baseui to hgweb entrypoint
Matt Mackall <mpm@selenic.com>
parents: 10905
diff changeset
   141
            else:
12696
ef969e58a394 hgweb: another fix for the help termwidth bug
Matt Mackall <mpm@selenic.com>
parents: 12691
diff changeset
   142
                u = ui.ui()
20168
d4be314b2071 hgweb: avoid initialization race (issue3953)
Matt Mackall <mpm@selenic.com>
parents: 19906
diff changeset
   143
            r = hg.repository(u, repo)
987
bfe12654764d hgweb: change startup argument processing
mpm@selenic.com
parents: 986
diff changeset
   144
        else:
22087
af62f0280a76 hgweb: avoid config object race with hgwebdir (issue4326)
Matt Mackall <mpm@selenic.com>
parents: 21759
diff changeset
   145
            # we trust caller to give us a private copy
20168
d4be314b2071 hgweb: avoid initialization race (issue3953)
Matt Mackall <mpm@selenic.com>
parents: 19906
diff changeset
   146
            r = repo
133
fb84d3e71042 added template support for some hgweb output, also, template files for
jake@edge2.net
parents: 132
diff changeset
   147
20168
d4be314b2071 hgweb: avoid initialization race (issue3953)
Matt Mackall <mpm@selenic.com>
parents: 19906
diff changeset
   148
        r = self._getview(r)
20790
49f2d5644f04 config: set a 'source' in most cases where config don't come from file but code
Mads Kiilerich <madski@unity3d.com>
parents: 20253
diff changeset
   149
        r.ui.setconfig('ui', 'report_untrusted', 'off', 'hgweb')
49f2d5644f04 config: set a 'source' in most cases where config don't come from file but code
Mads Kiilerich <madski@unity3d.com>
parents: 20253
diff changeset
   150
        r.baseui.setconfig('ui', 'report_untrusted', 'off', 'hgweb')
49f2d5644f04 config: set a 'source' in most cases where config don't come from file but code
Mads Kiilerich <madski@unity3d.com>
parents: 20253
diff changeset
   151
        r.ui.setconfig('ui', 'nontty', 'true', 'hgweb')
49f2d5644f04 config: set a 'source' in most cases where config don't come from file but code
Mads Kiilerich <madski@unity3d.com>
parents: 20253
diff changeset
   152
        r.baseui.setconfig('ui', 'nontty', 'true', 'hgweb')
25488
89ce95f907bd hgewb: disable progress when serving (issue4582)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22578
diff changeset
   153
        # displaying bundling progress bar while serving feel wrong and may
89ce95f907bd hgewb: disable progress when serving (issue4582)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22578
diff changeset
   154
        # break some wsgi implementation.
89ce95f907bd hgewb: disable progress when serving (issue4582)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22578
diff changeset
   155
        r.ui.setconfig('progress', 'disable', 'true', 'hgweb')
89ce95f907bd hgewb: disable progress when serving (issue4582)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22578
diff changeset
   156
        r.baseui.setconfig('progress', 'disable', 'true', 'hgweb')
20168
d4be314b2071 hgweb: avoid initialization race (issue3953)
Matt Mackall <mpm@selenic.com>
parents: 19906
diff changeset
   157
        self.repo = r
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 5779
diff changeset
   158
        hook.redirect(True)
22577
a111e460318a hgweb: refresh hgweb.repo on phase change (issue4061)
Anton Shestakov <engored@ya.ru>
parents: 22506
diff changeset
   159
        self.repostate = ((-1, -1), (-1, -1))
258
268bcb5a072a hgweb: watch changelog for changes
mpm@selenic.com
parents: 241
diff changeset
   160
        self.mtime = -1
1172
3f30a5e7e15b Use path relative to document root as reponame if published via a web server.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1170
diff changeset
   161
        self.reponame = name
3555
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   162
        # a repo owner may set web.templates in .hg/hgrc to get any file
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   163
        # readable by the user running the CGI script
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7948
diff changeset
   164
        self.templatepath = self.config('web', 'templates')
18627
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   165
        self.websubtable = self.loadwebsub()
3555
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   166
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   167
    # The CGI scripts are often run by a user different from the repo owner.
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   168
    # Trust the settings from the .hg/hgrc files by default.
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   169
    def config(self, section, name, default=None, untrusted=True):
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   170
        return self.repo.ui.config(section, name, default,
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   171
                                   untrusted=untrusted)
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   172
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   173
    def configbool(self, section, name, default=False, untrusted=True):
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   174
        return self.repo.ui.configbool(section, name, default,
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   175
                                       untrusted=untrusted)
881064004fd0 use untrusted settings in hgweb
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3499
diff changeset
   176
18522
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   177
    def _getview(self, repo):
25565
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   178
        """The 'web.view' config controls changeset filter to hgweb. Possible
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   179
        values are ``served``, ``visible`` and ``all``. Default is ``served``.
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   180
        The ``served`` filter only shows changesets that can be pulled from the
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   181
        hgweb instance.  The``visible`` filter includes secret changesets but
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   182
        still excludes "hidden" one.
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   183
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   184
        See the repoview module for details.
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   185
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   186
        The option has been around undocumented since Mercurial 2.5, but no
be4dc0007b8d hgweb: add some in-code documentation for 'web.view'
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 25488
diff changeset
   187
        user ever asked about it. So we better keep it undocumented for now."""
20168
d4be314b2071 hgweb: avoid initialization race (issue3953)
Matt Mackall <mpm@selenic.com>
parents: 19906
diff changeset
   188
        viewconfig = repo.ui.config('web', 'view', 'served',
d4be314b2071 hgweb: avoid initialization race (issue3953)
Matt Mackall <mpm@selenic.com>
parents: 19906
diff changeset
   189
                                    untrusted=True)
18522
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   190
        if viewconfig == 'all':
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   191
            return repo.unfiltered()
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   192
        elif viewconfig in repoview.filtertable:
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   193
            return repo.filtered(viewconfig)
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   194
        else:
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   195
            return repo.filtered('served')
36549fa712da hgweb: add a `web.view` to control filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18521
diff changeset
   196
26133
44ed220ef26f hgweb: don't make request optional
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26132
diff changeset
   197
    def refresh(self, request):
25718
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
   198
        repostate = []
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
   199
        # file of interrests mtime and size
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
   200
        for meth, fname in foi:
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
   201
            prefix = getattr(self.repo, meth)
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
   202
            st = get_stat(prefix, fname)
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
   203
            repostate.append((st.st_mtime, st.st_size))
2e32f0897bcf hgweb: use an extensible list of files to check for refresh
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25717
diff changeset
   204
        repostate = tuple(repostate)
22577
a111e460318a hgweb: refresh hgweb.repo on phase change (issue4061)
Anton Shestakov <engored@ya.ru>
parents: 22506
diff changeset
   205
        # we need to compare file size in addition to mtime to catch
a111e460318a hgweb: refresh hgweb.repo on phase change (issue4061)
Anton Shestakov <engored@ya.ru>
parents: 22506
diff changeset
   206
        # changes made less than a second ago
a111e460318a hgweb: refresh hgweb.repo on phase change (issue4061)
Anton Shestakov <engored@ya.ru>
parents: 22506
diff changeset
   207
        if repostate != self.repostate:
22223
c39d404f0eb0 hgweb: refresh repository using URL not path (issue4323)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22200
diff changeset
   208
            r = hg.repository(self.repo.baseui, self.repo.url())
18826
35fb2ef52a39 hgweb: do not pass on repo.ui when recreating a repo
Simon Heimberg <simohe@besonet.ch>
parents: 18629
diff changeset
   209
            self.repo = self._getview(r)
8859
580a79dde2a3 hgweb: web.encoding should override encoding.encoding (issue1183)
Matt Mackall <mpm@selenic.com>
parents: 8663
diff changeset
   210
            encoding.encoding = self.config("web", "encoding",
580a79dde2a3 hgweb: web.encoding should override encoding.encoding (issue1183)
Matt Mackall <mpm@selenic.com>
parents: 8663
diff changeset
   211
                                            encoding.encoding)
21759
bd3360c63bb3 hgweb: avoid initialization race (issue4280)
Matt Mackall <mpm@selenic.com>
parents: 20790
diff changeset
   212
            # update these last to avoid threads seeing empty settings
22577
a111e460318a hgweb: refresh hgweb.repo on phase change (issue4061)
Anton Shestakov <engored@ya.ru>
parents: 22506
diff changeset
   213
            self.repostate = repostate
a111e460318a hgweb: refresh hgweb.repo on phase change (issue4061)
Anton Shestakov <engored@ya.ru>
parents: 22506
diff changeset
   214
            # mtime is needed for ETag
21759
bd3360c63bb3 hgweb: avoid initialization race (issue4280)
Matt Mackall <mpm@selenic.com>
parents: 20790
diff changeset
   215
            self.mtime = st.st_mtime
26133
44ed220ef26f hgweb: don't make request optional
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26132
diff changeset
   216
44ed220ef26f hgweb: don't make request optional
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26132
diff changeset
   217
        self.repo.ui.environ = request.env
258
268bcb5a072a hgweb: watch changelog for changes
mpm@selenic.com
parents: 241
diff changeset
   218
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   219
    def run(self):
26132
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   220
        """Start a server from CGI environment.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   221
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   222
        Modern servers should be using WSGI and should avoid this
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   223
        method, if possible.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   224
        """
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   225
        if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
8663
45f626a39def wrap string literals in error messages
Martin Geisler <mg@lazybytes.net>
parents: 8390
diff changeset
   226
            raise RuntimeError("This function is only intended to be "
45f626a39def wrap string literals in error messages
Martin Geisler <mg@lazybytes.net>
parents: 8390
diff changeset
   227
                               "called while running as a CGI script.")
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   228
        import mercurial.hgweb.wsgicgi as wsgicgi
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   229
        wsgicgi.launch(self)
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   230
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   231
    def __call__(self, env, respond):
26132
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   232
        """Run the WSGI application.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   233
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   234
        This may be called by multiple threads.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   235
        """
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   236
        req = wsgirequest(env, respond)
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6781
diff changeset
   237
        return self.run_wsgi(req)
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   238
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   239
    def run_wsgi(self, req):
26132
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   240
        """Internal method to run the WSGI application.
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   241
26132
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   242
        This is typically only called by Mercurial. External consumers
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   243
        should be using instances of this class as the WSGI application.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25777
diff changeset
   244
        """
9887
38170eeed18c ui: add environ property to access os.environ or wsgirequest.environ
Sune Foldager <cryo@cyanite.org>
parents: 9842
diff changeset
   245
        self.refresh(req)
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
   246
        rctx = requestcontext(self)
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   247
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   248
        # work with CGI variables to create coherent structure
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   249
        # use SCRIPT_NAME, PATH_INFO and QUERY_STRING as well as our REPO_NAME
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   250
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   251
        req.url = req.env['SCRIPT_NAME']
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   252
        if not req.url.endswith('/'):
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   253
            req.url += '/'
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5890
diff changeset
   254
        if 'REPO_NAME' in req.env:
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   255
            req.url += req.env['REPO_NAME'] + '/'
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   256
6459
8189e03adb44 hgweb: make hgwebdir work in the absence of PATH_INFO
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6379
diff changeset
   257
        if 'PATH_INFO' in req.env:
8189e03adb44 hgweb: make hgwebdir work in the absence of PATH_INFO
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6379
diff changeset
   258
            parts = req.env['PATH_INFO'].strip('/').split('/')
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   259
            repo_parts = req.env.get('REPO_NAME', '').split('/')
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   260
            if parts[:len(repo_parts)] == repo_parts:
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   261
                parts = parts[len(repo_parts):]
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   262
            query = '/'.join(parts)
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   263
        else:
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   264
            query = req.env['QUERY_STRING'].split('&', 1)[0]
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   265
            query = query.split(';', 1)[0]
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   266
8860
36654238c050 hgweb: deny cloning a subpath of a repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8859
diff changeset
   267
        # process this if it's a protocol request
36654238c050 hgweb: deny cloning a subpath of a repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8859
diff changeset
   268
        # protocol bits don't need to create any URLs
36654238c050 hgweb: deny cloning a subpath of a repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8859
diff changeset
   269
        # and the clients always use the old URL structure
36654238c050 hgweb: deny cloning a subpath of a repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8859
diff changeset
   270
36654238c050 hgweb: deny cloning a subpath of a repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8859
diff changeset
   271
        cmd = req.form.get('cmd', [''])[0]
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11593
diff changeset
   272
        if protocol.iscmd(cmd):
13445
61a898576888 hgweb: handle invalid requests with both form data and querystring
Mads Kiilerich <mads@kiilerich.com>
parents: 12739
diff changeset
   273
            try:
61a898576888 hgweb: handle invalid requests with both form data and querystring
Mads Kiilerich <mads@kiilerich.com>
parents: 12739
diff changeset
   274
                if query:
61a898576888 hgweb: handle invalid requests with both form data and querystring
Mads Kiilerich <mads@kiilerich.com>
parents: 12739
diff changeset
   275
                    raise ErrorResponse(HTTP_NOT_FOUND)
61a898576888 hgweb: handle invalid requests with both form data and querystring
Mads Kiilerich <mads@kiilerich.com>
parents: 12739
diff changeset
   276
                if cmd in perms:
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
   277
                    self.check_perm(rctx, req, perms[cmd])
13445
61a898576888 hgweb: handle invalid requests with both form data and querystring
Mads Kiilerich <mads@kiilerich.com>
parents: 12739
diff changeset
   278
                return protocol.call(self.repo, req, cmd)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25565
diff changeset
   279
            except ErrorResponse as inst:
13571
84bd3fd63afc hgweb_mod: respond right away if the client specified 100-continue support
Augie Fackler <durin42@gmail.com>
parents: 13445
diff changeset
   280
                # A client that sends unbundle without 100-continue will
84bd3fd63afc hgweb_mod: respond right away if the client specified 100-continue support
Augie Fackler <durin42@gmail.com>
parents: 13445
diff changeset
   281
                # break if we respond early.
84bd3fd63afc hgweb_mod: respond right away if the client specified 100-continue support
Augie Fackler <durin42@gmail.com>
parents: 13445
diff changeset
   282
                if (cmd == 'unbundle' and
14991
4f39610996fa http2: send an extra header to signal a non-broken client
Augie Fackler <durin42@gmail.com>
parents: 13966
diff changeset
   283
                    (req.env.get('HTTP_EXPECT',
4f39610996fa http2: send an extra header to signal a non-broken client
Augie Fackler <durin42@gmail.com>
parents: 13966
diff changeset
   284
                                 '').lower() != '100-continue') or
4f39610996fa http2: send an extra header to signal a non-broken client
Augie Fackler <durin42@gmail.com>
parents: 13966
diff changeset
   285
                    req.env.get('X-HgHttp2', '')):
13445
61a898576888 hgweb: handle invalid requests with both form data and querystring
Mads Kiilerich <mads@kiilerich.com>
parents: 12739
diff changeset
   286
                    req.drain()
19488
60e060f4faa9 hgweb: force connection close on early response
Augie Fackler <raf@durin42.com>
parents: 18858
diff changeset
   287
                else:
60e060f4faa9 hgweb: force connection close on early response
Augie Fackler <raf@durin42.com>
parents: 18858
diff changeset
   288
                    req.headers.append(('Connection', 'Close'))
18352
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18258
diff changeset
   289
                req.respond(inst, protocol.HGTYPE,
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18258
diff changeset
   290
                            body='0\n%s\n' % inst.message)
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18258
diff changeset
   291
                return ''
8860
36654238c050 hgweb: deny cloning a subpath of a repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8859
diff changeset
   292
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   293
        # translate user-visible url structure to internal structure
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   294
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   295
        args = query.split('/', 2)
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   296
        if 'cmd' not in req.form and args and args[0]:
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   297
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   298
            cmd = args.pop(0)
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   299
            style = cmd.rfind('-')
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   300
            if style != -1:
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   301
                req.form['style'] = [cmd[:style]]
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   302
                cmd = cmd[style + 1:]
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   303
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   304
            # avoid accepting e.g. style parameter as command
14953
6ee6ecf1ee89 hgweb_mod: use safehasattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14913
diff changeset
   305
            if util.safehasattr(webcommands, cmd):
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   306
                req.form['cmd'] = [cmd]
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   307
7287
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   308
            if cmd == 'static':
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   309
                req.form['file'] = ['/'.join(args)]
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   310
            else:
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   311
                if args and args[0]:
25777
1c2a8db33b8f hgweb: allow symbolic revisions with forward slashes in urls
Anton Shestakov <av6@dwimlabs.net>
parents: 25720
diff changeset
   312
                    node = args.pop(0).replace('%2F', '/')
7287
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   313
                    req.form['node'] = [node]
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   314
                if args:
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   315
                    req.form['file'] = args
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   316
9731
0e080d519d1b hgweb: treat rev as raw-rev if user agent is hg
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8860
diff changeset
   317
            ua = req.env.get('HTTP_USER_AGENT', '')
0e080d519d1b hgweb: treat rev as raw-rev if user agent is hg
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8860
diff changeset
   318
            if cmd == 'rev' and 'mercurial' in ua:
0e080d519d1b hgweb: treat rev as raw-rev if user agent is hg
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8860
diff changeset
   319
                req.form['style'] = ['raw']
0e080d519d1b hgweb: treat rev as raw-rev if user agent is hg
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8860
diff changeset
   320
7287
6e9fe4ff9c54 hgweb: handle subdirectories within static directory
Brendan Cully <brendan@kublai.com>
parents: 7180
diff changeset
   321
            if cmd == 'archive':
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   322
                fn = req.form['node'][0]
26136
6defc74f3066 hgweb: move archive related attributes to requestcontext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26135
diff changeset
   323
                for type_, spec in rctx.archivespecs.iteritems():
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   324
                    ext = spec[2]
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   325
                    if fn.endswith(ext):
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   326
                        req.form['node'] = [fn[:-len(ext)]]
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   327
                        req.form['type'] = [type_]
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   328
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   329
        # process the web interface request
5599
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   330
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   331
        try:
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   332
            tmpl = self.templater(req)
8859
580a79dde2a3 hgweb: web.encoding should override encoding.encoding (issue1183)
Matt Mackall <mpm@selenic.com>
parents: 8663
diff changeset
   333
            ctype = tmpl('mimetype', encoding=encoding.encoding)
6391
a1007f7b9b7b Backed out changeset d2bb66a8a435 (temporary template compatibility)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6379
diff changeset
   334
            ctype = templater.stringify(ctype)
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   335
7562
b663b5563de7 hgweb: allow static content when deny_read denies access
Mark Edgington <edgimar@gmail.com>
parents: 7396
diff changeset
   336
            # check read permissions non-static content
b663b5563de7 hgweb: allow static content when deny_read denies access
Mark Edgington <edgimar@gmail.com>
parents: 7396
diff changeset
   337
            if cmd != 'static':
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
   338
                self.check_perm(rctx, req, None)
7336
2dc868712dcc hgweb: support for deny_read/allow_read options
Mark Edgington <edgimar@gmail.com>
parents: 7311
diff changeset
   339
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   340
            if cmd == '':
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   341
                req.form['cmd'] = [tmpl.cache['default']]
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   342
                cmd = req.form['cmd'][0]
5890
a0e20a5eba3c hgweb: fast path for sending raw files
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5889
diff changeset
   343
13966
a1c31c64bcd3 hgweb: support disabling page cache
Steven Stallion <sstallion@gmail.com>
parents: 13964
diff changeset
   344
            if self.configbool('web', 'cache', True):
a1c31c64bcd3 hgweb: support disabling page cache
Steven Stallion <sstallion@gmail.com>
parents: 13964
diff changeset
   345
                caching(self, req) # sets ETag header or raises NOT_MODIFIED
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   346
            if cmd not in webcommands.__all__:
6368
2c370f08c486 hgweb: better error messages
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6249
diff changeset
   347
                msg = 'no such method: %s' % cmd
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   348
                raise ErrorResponse(HTTP_BAD_REQUEST, msg)
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   349
            elif cmd == 'file' and 'raw' in req.form.get('style', []):
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   350
                self.ctype = ctype
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
   351
                content = webcommands.rawfile(rctx, req, tmpl)
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   352
            else:
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
   353
                content = getattr(webcommands, cmd)(rctx, req, tmpl)
6149
b023915aa1bc hgweb: separate protocol calls from interface calls (issue996)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6142
diff changeset
   354
                req.respond(HTTP_OK, ctype)
5890
a0e20a5eba3c hgweb: fast path for sending raw files
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5889
diff changeset
   355
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7348
diff changeset
   356
            return content
5600
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   357
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25565
diff changeset
   358
        except (error.LookupError, error.RepoLookupError) as err:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5976
diff changeset
   359
            req.respond(HTTP_NOT_FOUND, ctype)
6374
31a01e3d99cc hgweb: fix breakage in python < 2.5 introduced in 2c370f08c486
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6368
diff changeset
   360
            msg = str(err)
18855
50c922c1b514 hgweb: show correct error message for i18n environment
Takumi IINO <trot.thunder@gmail.com>
parents: 18522
diff changeset
   361
            if (util.safehasattr(err, 'name') and
50c922c1b514 hgweb: show correct error message for i18n environment
Takumi IINO <trot.thunder@gmail.com>
parents: 18522
diff changeset
   362
                not isinstance(err,  error.ManifestLookupError)):
6368
2c370f08c486 hgweb: better error messages
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6249
diff changeset
   363
                msg = 'revision not found: %s' % err.name
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7348
diff changeset
   364
            return tmpl('error', error=msg)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25565
diff changeset
   365
        except (error.RepoError, error.RevlogError) as inst:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5976
diff changeset
   366
            req.respond(HTTP_SERVER_ERROR, ctype)
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7348
diff changeset
   367
            return tmpl('error', error=str(inst))
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25565
diff changeset
   368
        except ErrorResponse as inst:
7740
176d3d681702 hgweb: pass ErrorResponses directly into req.respond()
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7637
diff changeset
   369
            req.respond(inst, ctype)
12739
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 12696
diff changeset
   370
            if inst.code == HTTP_NOT_MODIFIED:
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 12696
diff changeset
   371
                # Not allowed to return a body on a 304
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 12696
diff changeset
   372
                return ['']
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7348
diff changeset
   373
            return tmpl('error', error=inst.message)
5599
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   374
18627
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   375
    def loadwebsub(self):
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   376
        websubtable = []
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   377
        websubdefs = self.repo.ui.configitems('websub')
18629
013fcd112f13 extensions: obsolete and remove interhg extension
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18627
diff changeset
   378
        # we must maintain interhg backwards compatibility
013fcd112f13 extensions: obsolete and remove interhg extension
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18627
diff changeset
   379
        websubdefs += self.repo.ui.configitems('interhg')
18627
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   380
        for key, pattern in websubdefs:
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   381
            # grab the delimiter from the character after the "s"
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   382
            unesc = pattern[1]
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   383
            delim = re.escape(unesc)
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   384
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   385
            # identify portions of the pattern, taking care to avoid escaped
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   386
            # delimiters. the replace format and flags are optional, but
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   387
            # delimiters are required.
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   388
            match = re.match(
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   389
                r'^s%s(.+)(?:(?<=\\\\)|(?<!\\))%s(.*)%s([ilmsux])*$'
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   390
                % (delim, delim, delim), pattern)
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   391
            if not match:
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   392
                self.repo.ui.warn(_("websub: invalid pattern for %s: %s\n")
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   393
                                  % (key, pattern))
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   394
                continue
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   395
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   396
            # we need to unescape the delimiter for regexp and format
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   397
            delim_re = re.compile(r'(?<!\\)\\%s' % delim)
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   398
            regexp = delim_re.sub(unesc, match.group(1))
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   399
            format = delim_re.sub(unesc, match.group(2))
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   400
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   401
            # the pattern allows for 6 regexp flags, so set them if necessary
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   402
            flagin = match.group(3)
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   403
            flags = 0
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   404
            if flagin:
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   405
                for flag in flagin.upper():
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   406
                    flags |= re.__dict__[flag]
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   407
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   408
            try:
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   409
                regexp = re.compile(regexp, flags)
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   410
                websubtable.append((regexp, format))
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   411
            except re.error:
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   412
                self.repo.ui.warn(_("websub: invalid regexp for %s: %s\n")
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   413
                                  % (key, regexp))
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   414
        return websubtable
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   415
5599
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   416
    def templater(self, req):
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   417
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   418
        # determine scheme, port and server name
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   419
        # this is needed to create absolute urls
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   420
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   421
        proto = req.env.get('wsgi.url_scheme')
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   422
        if proto == 'https':
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   423
            proto = 'https'
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   424
            default_port = "443"
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   425
        else:
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   426
            proto = 'http'
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   427
            default_port = "80"
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   428
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   429
        port = req.env["SERVER_PORT"]
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   430
        port = port != default_port and (":" + port) or ""
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   431
        urlbase = '%s://%s%s' % (proto, req.env['SERVER_NAME'], port)
13964
616ad3f6fd33 hgweb: support alternate logo url
Steven Stallion <sstallion@gmail.com>
parents: 13959
diff changeset
   432
        logourl = self.config("web", "logourl", "http://mercurial.selenic.com/")
14913
44382887d012 hgweb: add a "web/logoimg" setting to customize the web logo image
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 13966
diff changeset
   433
        logoimg = self.config("web", "logoimg", "hglogo.png")
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   434
        staticurl = self.config("web", "staticurl") or req.url + 'static/'
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   435
        if not staticurl.endswith('/'):
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   436
            staticurl += '/'
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   437
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   438
        # some functions for the templater
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   439
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   440
        def motd(**map):
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   441
            yield self.config("web", "motd", "")
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   442
5599
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   443
        # figure out which style to use
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   444
7345
55651328dfcc hgweb: fix up the less/more links on the graph page
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7336
diff changeset
   445
        vars = {}
9842
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9731
diff changeset
   446
        styles = (
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9731
diff changeset
   447
            req.form.get('style', [None])[0],
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9731
diff changeset
   448
            self.config('web', 'style'),
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9731
diff changeset
   449
            'paper',
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9731
diff changeset
   450
        )
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9731
diff changeset
   451
        style, mapfile = templater.stylemap(styles, self.templatepath)
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9731
diff changeset
   452
        if style == styles[0]:
7345
55651328dfcc hgweb: fix up the less/more links on the graph page
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7336
diff changeset
   453
            vars['style'] = style
55651328dfcc hgweb: fix up the less/more links on the graph page
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7336
diff changeset
   454
55651328dfcc hgweb: fix up the less/more links on the graph page
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7336
diff changeset
   455
        start = req.url[-1] == '?' and '&' or '?'
55651328dfcc hgweb: fix up the less/more links on the graph page
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7336
diff changeset
   456
        sessionvars = webutil.sessionvars(vars, start)
5596
20b07b68a865 hgweb: get rid of some nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5595
diff changeset
   457
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   458
        if not self.reponame:
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   459
            self.reponame = (self.config("web", "name")
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   460
                             or req.env.get('REPO_NAME')
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   461
                             or req.url.strip('/') or self.repo.root)
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   462
18627
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   463
        def websubfilter(text):
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   464
            return websub(text, self.websubtable)
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   465
5599
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   466
        # create the templater
3de66c2a9734 hgweb: split out templater definition
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5598
diff changeset
   467
8360
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8225
diff changeset
   468
        tmpl = templater.templater(mapfile,
18627
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18522
diff changeset
   469
                                   filters={"websub": websubfilter},
5600
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   470
                                   defaults={"url": req.url,
13964
616ad3f6fd33 hgweb: support alternate logo url
Steven Stallion <sstallion@gmail.com>
parents: 13959
diff changeset
   471
                                             "logourl": logourl,
14913
44382887d012 hgweb: add a "web/logoimg" setting to customize the web logo image
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 13966
diff changeset
   472
                                             "logoimg": logoimg,
5600
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   473
                                             "staticurl": staticurl,
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   474
                                             "urlbase": urlbase,
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   475
                                             "repo": self.reponame,
19906
1dba26575dba hgweb: remove now unnecessary explicit header() and footer()
Alexander Plavin <alexander@plav.in>
parents: 19488
diff changeset
   476
                                             "encoding": encoding.encoding,
5600
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   477
                                             "motd": motd,
18258
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
   478
                                             "sessionvars": sessionvars,
bebb05a7e249 hgweb: add a "URL breadcrumb" to the index and repository pages
Angel Ezquerra <angel.ezquerra at gmail.com>
parents: 16754
diff changeset
   479
                                             "pathdef": makebreadcrumb(req.url),
20253
43cfad930d38 hgweb: avoid invalid infinity scroll request when overwritten web.style
Takumi IINO <trot.thunder@gmail.com>
parents: 20169
diff changeset
   480
                                             "style": style,
5600
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   481
                                            })
9d900f7282e6 hgweb: explicitly pass around the templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5599
diff changeset
   482
        return tmpl
5591
08887121a652 split out hgweb commands into a separate file, move some code around
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5579
diff changeset
   483
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
   484
    def check_perm(self, rctx, req, op):
22200
b27c3beaaf30 cleanup: avoid local vars shadowing imports
Mads Kiilerich <madski@unity3d.com>
parents: 22087
diff changeset
   485
        for permhook in permhooks:
26134
e0a6908f066f hgweb: establish class for holding per request context
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26133
diff changeset
   486
            permhook(rctx, req, op)