mercurial/hgweb/common.py
author Matt Mackall <mpm@selenic.com>
Tue, 19 Jan 2010 22:45:09 -0600
changeset 10264 d6512b3e9ac0
parent 10078 97c75ad3b1a0
parent 10263 25e572394f5c
child 12183 f64b416b0ac8
permissions -rw-r--r--
Merge with stable
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: 2356
diff changeset
     1
# hgweb/common.py - Utility functions needed by hgweb_mod and hgwebdir_mod
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>
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2514
diff changeset
     4
# Copyright 2005, 2006 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: 7966
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: 9694
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
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
     9
import errno, mimetypes, os
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
    10
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    11
HTTP_OK = 200
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    12
HTTP_BAD_REQUEST = 400
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6924
diff changeset
    13
HTTP_UNAUTHORIZED = 401
7029
b84d27386285 hgweb: Respond with HTTP 403 for disabled archive types instead of 404
Rocco Rutte <pdmef@gmx.net>
parents: 6926
diff changeset
    14
HTTP_FORBIDDEN = 403
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    15
HTTP_NOT_FOUND = 404
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6924
diff changeset
    16
HTTP_METHOD_NOT_ALLOWED = 405
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    17
HTTP_SERVER_ERROR = 500
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    18
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    19
# Hooks for hgweb permission checks; extensions can add hooks here. Each hook
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    20
# is invoked like this: hook(hgweb, request, operation), where operation is
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    21
# either read, pull or push. Hooks should either raise an ErrorResponse
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    22
# exception, or just return.
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    23
# It is possible to do both authentication and authorization through this.
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    24
permhooks = []
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    25
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    26
def checkauthz(hgweb, req, op):
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    27
    '''Check permission for operation based on request data (including
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    28
    authentication info). Return if op allowed, else raise an ErrorResponse
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    29
    exception.'''
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    30
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    31
    user = req.env.get('REMOTE_USER')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    32
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    33
    deny_read = hgweb.configlist('web', 'deny_read')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    34
    if deny_read and (not user or deny_read == ['*'] or user in deny_read):
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    35
        raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    36
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    37
    allow_read = hgweb.configlist('web', 'allow_read')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    38
    result = (not allow_read) or (allow_read == ['*'])
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    39
    if not (result or user in allow_read):
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    40
        raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    41
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    42
    if op == 'pull' and not hgweb.allowpull:
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    43
        raise ErrorResponse(HTTP_UNAUTHORIZED, 'pull not authorized')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    44
    elif op == 'pull' or op is None: # op is None for interface requests
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    45
        return
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    46
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    47
    # enforce that you can only push using POST requests
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    48
    if req.env['REQUEST_METHOD'] != 'POST':
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    49
        msg = 'push requires POST request'
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    50
        raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    51
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    52
    # require ssl by default for pushing, auth info cannot be sniffed
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    53
    # and replayed
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    54
    scheme = req.env.get('wsgi.url_scheme')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    55
    if hgweb.configbool('web', 'push_ssl', True) and scheme != 'https':
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    56
        raise ErrorResponse(HTTP_OK, 'ssl required')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    57
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    58
    deny = hgweb.configlist('web', 'deny_push')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    59
    if deny and (not user or deny == ['*'] or user in deny):
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    60
        raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    61
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    62
    allow = hgweb.configlist('web', 'allow_push')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    63
    result = allow and (allow == ['*'] or user in allow)
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    64
    if not result:
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    65
        raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    66
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    67
# Add the default permhook, which provides simple authorization.
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    68
permhooks.append(checkauthz)
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    69
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    70
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
    71
class ErrorResponse(Exception):
7741
a3d7f99c23c0 hgweb: support custom http headers in ErrorResponse
Sune Foldager <cryo@cyanite.org>
parents: 7310
diff changeset
    72
    def __init__(self, code, message=None, headers=[]):
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
    73
        Exception.__init__(self)
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
    74
        self.code = code
7741
a3d7f99c23c0 hgweb: support custom http headers in ErrorResponse
Sune Foldager <cryo@cyanite.org>
parents: 7310
diff changeset
    75
        self.headers = headers
6924
e8332c8108ff hgweb: generate error message only if nothing is passed
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6123
diff changeset
    76
        if message is not None:
5563
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
    77
            self.message = message
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
    78
        else:
5563
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
    79
            self.message = _statusmessage(code)
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
    80
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
    81
def _statusmessage(code):
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
    82
    from BaseHTTPServer import BaseHTTPRequestHandler
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
    83
    responses = BaseHTTPRequestHandler.responses
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
    84
    return responses.get(code, ('Error', 'Unknown error'))[0]
5760
0145f9afb0e7 Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5563
diff changeset
    85
9694
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9031
diff changeset
    86
def statusmessage(code, message=None):
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9031
diff changeset
    87
    return '%d %s' % (code, message or _statusmessage(code))
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
    88
10078
97c75ad3b1a0 hgweb: Make get_mtime use repository to find store path.
Brendan Cully <brendan@kublai.com>
parents: 9910
diff changeset
    89
def get_mtime(spath):
97c75ad3b1a0 hgweb: Make get_mtime use repository to find store path.
Brendan Cully <brendan@kublai.com>
parents: 9910
diff changeset
    90
    cl_path = os.path.join(spath, "00changelog.i")
3853
c0b449154a90 switch to the .hg/store layout, fix the tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3276
diff changeset
    91
    if os.path.exists(cl_path):
1418
68f81ba07b2a Make hgweb work when the repository is empty (no 00changelog.i)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1416
diff changeset
    92
        return os.stat(cl_path).st_mtime
68f81ba07b2a Make hgweb work when the repository is empty (no 00changelog.i)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1416
diff changeset
    93
    else:
10078
97c75ad3b1a0 hgweb: Make get_mtime use repository to find store path.
Brendan Cully <brendan@kublai.com>
parents: 9910
diff changeset
    94
        return os.stat(spath).st_mtime
1418
68f81ba07b2a Make hgweb work when the repository is empty (no 00changelog.i)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1416
diff changeset
    95
2514
419c42223bee Really fix http headers for web UI and issue 254.
Eric Hopper <hopper@omnifarious.org>
parents: 2391
diff changeset
    96
def staticfile(directory, fname, req):
5930
c301f15c965a send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5779
diff changeset
    97
    """return a file inside directory with guessed Content-Type header
1825
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
    98
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
    99
    fname always uses '/' as directory separator and isn't allowed to
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   100
    contain unusual path components.
5930
c301f15c965a send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5779
diff changeset
   101
    Content-Type is guessed using the mimetypes module.
1825
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   102
    Return an empty string if fname is illegal or file not found.
1793
83c6d8355909 Allow serving static files from hgwebdir to fix CSS and favicon.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1792
diff changeset
   103
1825
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   104
    """
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   105
    parts = fname.split('/')
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   106
    for part in parts:
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   107
        if (part in ('', os.curdir, os.pardir) or
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   108
            os.sep in part or os.altsep is not None and os.altsep in part):
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   109
            return ""
7288
9c399c53469d Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   110
    fpath = os.path.join(*parts)
9c399c53469d Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   111
    if isinstance(directory, str):
9c399c53469d Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   112
        directory = [directory]
9c399c53469d Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   113
    for d in directory:
9c399c53469d Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   114
        path = os.path.join(d, fpath)
9c399c53469d Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   115
        if os.path.exists(path):
9c399c53469d Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
   116
            break
1793
83c6d8355909 Allow serving static files from hgwebdir to fix CSS and favicon.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1792
diff changeset
   117
    try:
1825
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   118
        os.stat(path)
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   119
        ct = mimetypes.guess_type(path)[0] or "text/plain"
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   120
        req.respond(HTTP_OK, ct, length = os.path.getsize(path))
9031
3b76321aa0de compat: use open() instead of file() everywhere
Alejandro Santos <alejolp@alejolp.com>
parents: 8761
diff changeset
   121
        return open(path, 'rb').read()
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
   122
    except TypeError:
8761
0289f384e1e5 Generally replace "file name" with "filename" in help and comments.
timeless <timeless@gmail.com>
parents: 8225
diff changeset
   123
        raise ErrorResponse(HTTP_SERVER_ERROR, 'illegal filename')
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
   124
    except OSError, err:
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
   125
        if err.errno == errno.ENOENT:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   126
            raise ErrorResponse(HTTP_NOT_FOUND)
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
   127
        else:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   128
            raise ErrorResponse(HTTP_SERVER_ERROR, err.strerror)
3276
db9d2a624521 hgweb: Search templates in templatepath/style/map, too, using a common function.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3244
diff changeset
   129
4462
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   130
def paritygen(stripecount, offset=0):
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   131
    """count parity of horizontal stripes for easier reading"""
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   132
    if stripecount and offset:
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   133
        # account for offset, e.g. due to building the list in reverse
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   134
        count = (stripecount + offset) % stripecount
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   135
        parity = (stripecount + offset) / stripecount & 1
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   136
    else:
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   137
        count = 0
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   138
        parity = 0
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   139
    while True:
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   140
        yield parity
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   141
        count += 1
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   142
        if stripecount and count >= stripecount:
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   143
            parity = 1 - parity
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   144
            count = 0
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   145
5779
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   146
def get_contact(config):
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   147
    """Return repo contact information or empty string.
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   148
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   149
    web.contact is the primary source, but if that is not set, try
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   150
    ui.username or $EMAIL as a fallback to display something useful.
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   151
    """
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   152
    return (config("web", "contact") or
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   153
            config("ui", "username") or
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   154
            os.environ.get("EMAIL") or "")