webis.py 4.66 KB
Newer Older
1
#!/usr/bin/env python3
Martin Potthast's avatar
Martin Potthast committed
2
"""The main webis command.
Steve Goering's avatar
Steve Goering committed
3

Martin Potthast's avatar
Martin Potthast committed
4 5
Copyright webis.de 2015-today
Authors: Steve Göring, Martin Potthast
Steve Goering's avatar
Steve Goering committed
6
"""
Martin Potthast's avatar
Martin Potthast committed
7

8
import argparse
Martin Potthast's avatar
Martin Potthast committed
9
import collections
10 11
import json
import loader
Martin Potthast's avatar
Martin Potthast committed
12 13
import os
import sys
14 15

from lib import *
Martin Potthast's avatar
Martin Potthast committed
16
from log import *
17 18 19
from system import *


Martin Potthast's avatar
Martin Potthast committed
20 21 22 23 24 25 26 27
def load_config():
    """Returns the configuration, based on the JSON configuration file."""
    try:
        return json.loads(read_file(os.path.dirname(
            os.path.realpath(__file__)) + "/config.json"))
    except Exception as e:
        lError("The file config.json is invalid.")
        sys.exit(1)
28

Steve Goering's avatar
Steve Goering committed
29

Martin Potthast's avatar
Martin Potthast committed
30 31 32
def get_commands(config):
    """Returns commands mapped to directories containing their subcommands."""
    commands = collections.OrderedDict()
Martin Potthast's avatar
Martin Potthast committed
33 34
    # FIXME: Variable names should be English only; also "moduls" has been
    # renamed to "command".
Martin Potthast's avatar
Martin Potthast committed
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
    for directory in os.listdir(config["moduls_directory"]):
        if (os.path.isdir(config["moduls_directory"] + directory) and
            directory not in config["ignored_dirs"]):
            commands[directory] = config["moduls_directory"] + directory
    return commands


def get_subcommands(config, commandpath):
    """Returns subcommands of a given command mapped to their script files."""
    subcommands = collections.OrderedDict()
    for script in os.listdir(commandpath):
        subcommandpath = commandpath + "/" + script
        if os.path.isfile(subcommandpath):
            allowed_scripts = config["allowed_scripts"]
            if check_subcommand_shebang(subcommandpath, allowed_scripts):
                subcommand = script.rsplit(".", 1)[0]
                subcommands[subcommand] = subcommandpath
    return subcommands


def get_subcommand_help(subcommandpath):
    """Returns the help message expected at the beginning of a command."""
    if not os.path.isfile(subcommandpath):
        return os.path.basename(subcommandpath)

    f = open(subcommandpath)
61 62 63 64 65 66 67
    lines = f.readlines()
    f.close()
    if len(lines) < 1 or lines[1][0] != "#":
        return ""
    return lines[1][1:].replace("\n", "").strip()


Martin Potthast's avatar
Martin Potthast committed
68 69 70 71 72 73 74
def check_subcommand_shebang(subcommandpath, allowed_scripts):
    """Checks if the shebang of a given script is among the allowed shebangs."""
    shebang = get_shebang(subcommandpath)
    for interpreter in allowed_scripts:
        if interpreter in shebang:
            return True
    return False
Steve Goering's avatar
Steve Goering committed
75

76

Martin Potthast's avatar
Martin Potthast committed
77 78 79 80 81 82
def run_subcommand(subcommand, subcommandpath, params=[]):
    """Runs subcommand passing params and returns its exit code."""
    lDbg("Running " + subcommand + " at " + subcommandpath)
    # FIXME: When the script is installed at /usr/lib, this won't work, anymore:
    os.system("chmod +x {}".format(subcommandpath))
    cmd = " ".join([subcommandpath] + params)
83 84
    return_value = os.system(cmd)
    if return_value == 0:
Martin Potthast's avatar
Martin Potthast committed
85
        lInfo("Done.")
86
    else:
Martin Potthast's avatar
Martin Potthast committed
87
        lError("An error occurred while executing " + cmd)
88
    return return_value
89 90 91


def main(args):
Martin Potthast's avatar
Martin Potthast committed
92 93 94 95 96 97 98 99 100
    config = load_config()
    commands = get_commands(config)
    parser = argparse.ArgumentParser()
    subparsers = {}
    allcommands = {}
    commandparsers = parser.add_subparsers(
        metavar='<command>', dest='<command>', help='Available commands:')
    for command in commands:
        # TODO: It is unclear where to obtain the help messages for commands.
Martin Potthast's avatar
Martin Potthast committed
101
        # TODO: It is conceivable to introduce aliases for each command, but it
Martin Potthast's avatar
Martin Potthast committed
102 103
        # is unclear where to obtain them. Simply using a prefix does not
        # work for betamng and betaweb, since they share a long prefix.
Martin Potthast's avatar
Martin Potthast committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
        commandparser = commandparsers.add_parser(command, 
            help='TODO: Help message for commands.')
        subparsers[command] = commandparser
        subcommandparsers = commandparser.add_subparsers(
            metavar='<subcommand>', dest='<subcommand>',
            help='Available subcommands:')
        subcommands = get_subcommands(config, commands[command])
        allcommands[command] = subcommands
        for subcommand in subcommands:
            subcommandparser = subcommandparsers.add_parser(
                subcommand, help=str(
                    get_subcommand_help(subcommands[subcommand])), 
                add_help=False)
            subparsers[subcommand] = subcommandparser

    if len(args) == 0:
        parser.print_help()
121 122
        return 0

Martin Potthast's avatar
Martin Potthast committed
123 124 125 126 127 128 129
    parseresults = parser.parse_known_args(args)
    argsdict = vars(parseresults[0])
    parameter = parseresults[1]
    
    if len(argsdict) == 2 and argsdict['<subcommand>'] == None:
        subparsers[argsdict['<command>']].print_help()
        return 0
130

Martin Potthast's avatar
Martin Potthast committed
131 132
    return run_subcommand(argsdict['<subcommand>'], 
        allcommands[argsdict['<command>']][argsdict['<subcommand>']], parameter)
133 134 135 136


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
Martin Potthast's avatar
Martin Potthast committed
137