~loggerhead-team/loggerhead/trunk-rich

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# Copyright 2009, 2010, 2011 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


# This file allows loggerhead to be treated as a plugin for bzr.
#
# XXX: Because loggerhead already contains a loggerhead directory, much of the
# code is going to appear loaded at bzrlib.plugins.loggerhead.loggerhead.
# This seems like the easiest thing, because bzrlib wants the top-level plugin
# directory to be the module, but when it's used as a library people expect
# the source directory to contain a directory called loggerhead.  -- mbp
# 20090123

"""Loggerhead web viewer for Bazaar branches.

This provides a new option "--http" to the "bzr serve" command, that
starts a web server to browse the contents of a branch.
"""

from info import (
    bzr_plugin_version as version_info,
    bzr_compatible_versions,
    )

if __name__ == 'bzrlib.plugins.loggerhead':
    import bzrlib
    from bzrlib.api import require_any_api

    require_any_api(bzrlib, bzr_compatible_versions)

    # NB: Normally plugins should lazily load almost everything, but this
    # seems reasonable to have in-line here: bzrlib.commands and options are
    # normally loaded, and the rest of loggerhead won't be loaded until serve
    # --http is run.

    # transport_server_registry was added in bzr 1.16. When we drop support for
    # older releases, we can remove the code to override cmd_serve.

    try:
        from bzrlib.transport import transport_server_registry
    except ImportError:
        transport_server_registry = None

    DEFAULT_HOST = '0.0.0.0'
    DEFAULT_PORT = 8080
    HELP = ('Loggerhead, a web-based code viewer and server. (default port: %d)' %
            (DEFAULT_PORT,))

    def setup_logging(config):
        import logging
        import sys

        logger = logging.getLogger('loggerhead')
        handler = logging.StreamHandler(sys.stderr)
        handler.setLevel(logging.DEBUG)
        logger.addHandler(handler)
        logging.getLogger('simpleTAL').addHandler(handler)
        logging.getLogger('simpleTALES').addHandler(handler)


    def _ensure_loggerhead_path():
        """Ensure that you can 'import loggerhead' and get the root."""
        # loggerhead internal code will try to 'import loggerhead', so
        # let's put it on the path if we can't find it in the existing path
        try:
            import loggerhead.apps.transport
        except ImportError:
            import os.path, sys
            sys.path.append(os.path.dirname(__file__))

    def serve_http(transport, host=None, port=None, inet=None):
        # TODO: if we supported inet to pass requests in and respond to them,
        #       then it would be easier to test the full stack, but it probably
        #       means routing around paste.httpserver.serve which probably
        #       isn't testing the full stack
        from paste.httpexceptions import HTTPExceptionHandler
        from paste.httpserver import serve

        _ensure_loggerhead_path()

        from loggerhead.apps.http_head import HeadMiddleware
        from loggerhead.apps.transport import BranchesFromTransportRoot
        from loggerhead.config import LoggerheadConfig

        if host is None:
            host = DEFAULT_HOST
        if port is None:
            port = DEFAULT_PORT
        argv = ['--host', host, '--port', str(port), '--', transport.base]
        if not transport.is_readonly():
            argv.insert(0, '--allow-writes')
        config = LoggerheadConfig(argv)
        setup_logging(config)
        app = BranchesFromTransportRoot(transport.base, config)
        app = HeadMiddleware(app)
        app = HTTPExceptionHandler(app)
        serve(app, host=host, port=port)

    if transport_server_registry is not None:
        transport_server_registry.register('http', serve_http, help=HELP)
    else:
        import bzrlib.builtins
        from bzrlib.commands import get_cmd_object, register_command
        from bzrlib.option import Option

        _original_command = get_cmd_object('serve')

        class cmd_serve(bzrlib.builtins.cmd_serve):
            __doc__ = _original_command.__doc__

            takes_options = _original_command.takes_options + [
                Option('http', help=HELP)]

            def run(self, *args, **kw):
                if 'http' in kw:
                    from bzrlib.transport import get_transport
                    allow_writes = kw.get('allow_writes', False)
                    path = kw.get('directory', '.')
                    port = kw.get('port', DEFAULT_PORT)
                    # port might be an int already...
                    if isinstance(port, basestring) and ':' in port:
                        host, port = port.split(':')
                    else:
                        host = DEFAULT_HOST
                    if allow_writes:
                        transport = get_transport(path)
                    else:
                        transport = get_transport('readonly+' + path)
                    serve_http(transport, host, port)
                else:
                    super(cmd_serve, self).run(*args, **kw)

        register_command(cmd_serve)

    def load_tests(standard_tests, module, loader):
        _ensure_loggerhead_path()
        standard_tests.addTests(loader.loadTestsFromModuleNames(
            ['bzrlib.plugins.loggerhead.loggerhead.tests']))
        return standard_tests