Eclectic Media Git klaus / master bin / klaus
master

Tree @master (Download .tar.gz)

klaus @masterraw · history · blame

#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function

import sys
import os
import argparse
import webbrowser

from dulwich.errors import NotGitRepository
from dulwich.repo import Repo

from klaus import make_app, KLAUS_VERSION
from klaus.utils import force_unicode


def git_repository(path):
    path = os.path.abspath(path)
    if not os.path.exists(path):
        raise argparse.ArgumentTypeError('%r: No such directory' % path)
    try:
        Repo(path)
    except NotGitRepository:
        raise argparse.ArgumentTypeError('%r: Not a Git repository' % path)
    return path


def make_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('--host',     help="default: 127.0.0.1", default='127.0.0.1')
    parser.add_argument('--port',     help="default: 8080", default=8080, type=int)
    parser.add_argument('--site-name', help="site name showed in header. default: your hostname")
    parser.add_argument('--version', help='print version number', action='store_true')
    parser.add_argument('-b', '--browser', help="open klaus in a browser on server start",
                        default=False, action='store_true')
    parser.add_argument('-B', '--with-browser', help="specify which browser to use with --browser",
                        metavar='BROWSER', default=None)
    parser.add_argument('--ctags', help="enable ctags for which revisions? default: none. "
                                        "WARNING: Don't use 'ALL' for public servers!",
                        choices=['none', 'tags-and-branches', 'ALL'], default='none')

    parser.add_argument('repos', help='repositories to serve',
                        metavar='DIR', nargs='*', type=git_repository)

    grp = parser.add_argument_group("Git Smart HTTP")
    grp.add_argument('--smarthttp', help="enable Git Smart HTTP serving",
                     action='store_true')
    grp.add_argument('--htdigest', help="use credentials from FILE",
                     metavar="FILE", type=argparse.FileType('r'))

    grp = parser.add_argument_group("Development flags", "DO NOT USE IN PRODUCTION!")
    grp.add_argument('--debug', help="Enable Werkzeug debugger and reloader", action='store_true')

    return parser


def main():
    args = make_parser().parse_args()

    if args.version:
        print(KLAUS_VERSION)
        return 0

    if args.htdigest and not args.smarthttp:
        print("ERROR: --htdigest option has no effect without --smarthttp enabled", file=sys.stderr)
        return 1

    if not args.repos:
        print("WARNING: No repositories supplied -- syntax is 'klaus dir1 dir2...'.", file=sys.stderr)

    if not args.site_name:
        args.site_name = '%s:%d' % (args.host, args.port)

    if args.ctags != 'none':
        from klaus.ctagsutils import check_have_exuberant_ctags
        if not check_have_exuberant_ctags():
            print("ERROR: Exuberant ctags not installed (or 'ctags' binary isn't *Exuberant* ctags)", file=sys.stderr)
            return 1
        try:
            import ctags
        except ImportError:
            raise ImportError("Please install 'python-ctags3' to enable ctags support.")

    app = make_app(
        args.repos,
        force_unicode(args.site_name or args.host),
        args.smarthttp,
        args.htdigest,
        ctags_policy=args.ctags,
    )

    if args.browser:
        _open_browser(args)

    app.run(args.host, args.port, args.debug)

def _open_browser(args):
    # Open a web browser onto the server URL. Technically we're jumping the
    # gun a little here since the server is not yet running, but there's no
    # clean way to run a function after the server has started without
    # losing the simplicity of the code. In the Real World (TM) it'll take
    # longer for the browser to start than it will for us to start
    # serving, so we'll be OK.
    if args.with_browser is None:
        opener = webbrowser.open
    else:
        opener = webbrowser.get(args.with_browser).open
    opener('http://%s:%s' % (args.host, args.port))


if __name__ == '__main__':
    exit(main())