Example #1
0
    def __init__(self, user=None, password=None, server=None, port=None,
                 anon=False):
        """Initialise an SR trac object."""
        config = Config()

        if server is None:
            server = config["server"]

        if port is None:
            port = config["https_port"]

        self.server = server
        self.port = port

        rpc_settings = {"server": server, "port": port}

        if anon:
            rpc_url = "https://{server}:{port}/trac/rpc"
        else:
            rpc_url = "https://{user}:{password}@{server}:{port}/trac/login" \
                      "/rpc"

            user = config.get_user(user)
            rpc_settings["user"] = user
            rpc_settings["password"] = config.get_password(password, user=user)

        rpc_url = rpc_url.format(**rpc_settings)

        ServerProxy.__init__(self, rpc_url)

        if 'ticket.create' not in self.system.listMethods():
            raise WrongServer()
Example #2
0
def command(args):
    import sys
    import subprocess

    from sr.tools.config import Config

    config = Config()

    username = config.get_user()

    url = GIT_URL.format(username=username, team=args.team.upper(), project=args.project)

    cmdline = ["git", "clone", url]

    if args.dir is not None:
        cmdline.append(args.dir)

    sys.exit(subprocess.call(cmdline))
Example #3
0
def command(args):
    import sys
    import subprocess

    from sr.tools.config import Config

    config = Config()

    username = config.get_user()

    url = GIT_URL.format(username=username,
                         team=args.team.upper(),
                         project=args.project)

    cmdline = ["git", "clone", url]

    if args.dir is not None:
        cmdline.append(args.dir)

    sys.exit(subprocess.call(cmdline))
Example #4
0
def cmd(args):
    """
    Run the given Gerrit command and return the response.

    This will get the Gerrit SSH host from the configuration file.

    :param list args: The arguments to run on Gerrit.
    :returns: The contents from the result.
    """
    conf = Config()
    c = ["ssh", conf["gerrit_ssh"], "gerrit"] + args
    return subprocess.check_output(c, universal_newlines=True).strip()
Example #5
0
    def __init__(self,
                 user=None,
                 password=None,
                 server=None,
                 port=None,
                 anon=False):
        """Initialise an SR trac object."""
        config = Config()

        if server is None:
            server = config["server"]

        if port is None:
            port = config["https_port"]

        self.server = server
        self.port = port

        rpc_settings = {"server": server, "port": port}

        if anon:
            rpc_url = "https://{server}:{port}/trac/rpc"
        else:
            rpc_url = "https://{user}:{password}@{server}:{port}/trac/login" \
                      "/rpc"

            user = config.get_user(user)
            rpc_settings["user"] = user
            rpc_settings["password"] = config.get_password(password, user=user)

        rpc_url = rpc_url.format(**rpc_settings)

        ServerProxy.__init__(self, rpc_url)

        if 'ticket.create' not in self.system.listMethods():
            raise WrongServer()
Example #6
0
def command(args):
    from sr.tools.config import Config

    with UsermanServer.from_config(Config()) as userman:
        user_info = userman.get('user', args.username)
        description = describe_user(user_info, userman)

        if user_info['has_media_consent']:
            exit("{0} already granted media-consent!".format(description))

        question = "Confirm media-consent for {0}? [Y/n]: ".format(description)
        confirm = query(question, ('', 'y'), ('n',))

        if not confirm:
            exit()

        # Yes, really, we need to pass 'true' as a string
        userman.post('user', args.username, media_consent='true')
Example #7
0
def command(args):
    import os
    import sys

    from sr.tools import spending
    from sr.tools.config import Config
    from sr.tools.environment import get_config_filename

    # Invoke ledger on the SR spending repo
    # Check that we are indeed invoking it on spending.git
    config = Config()

    # Default to using the spending.git specified in the config
    root = config["spending"]
    if root is not None:
        root = os.path.expanduser(root)
    else:
        # Not specified in the config
        root = os.getcwd()

    try:
        # Check that it's actually spending.git
        root = spending.find_root(path=root)
    except spending.NotSpendingRepo:
        print("This isn't SR spending.git", file=sys.stderr)
        print("Solve this by either:", file=sys.stderr)
        print(" - Changing working directory to spending.git", file=sys.stderr)
        print(" - Set the 'spending' config option in {}".format(
            get_config_filename()),
              file=sys.stderr)
        sys.exit(1)

    ledger_args = ['ledger'] + args.command
    if "--file" not in args:
        # Tell ledger where to look
        ledger_args = ['ledger', "--file", os.path.join(root, "spending.dat")] \
            + args.command

    os.execvp("ledger", ledger_args)
Example #8
0
def command(args):
    import os
    import subprocess

    from sr.tools.config import Config

    config = Config()

    if args.anonymous:
        prefix = "git://{0}/".format(config["server"])
    else:
        prefix = "{0}:".format(config["gerrit_ssh"])

    repo = args.repo
    if repo[:len(prefix)] != prefix:
        repo = "{0}{1}".format(prefix, repo)

    cmd = ["git", "clone", "--recursive", repo]
    if args.dir is not None:
        cmd += [args.dir]

    subprocess.check_call(cmd)

    clonedir = args.dir
    if clonedir is None:
        clonedir = os.path.basename(args.repo)

        if clonedir[-4:] == ".git":
            clonedir = clonedir[:-4]

    if not args.anonymous:
        # Set up the gerrit Change-Id commit hook
        cmd = [
            "scp", "{}:hooks/commit-msg".format(config["gerrit_ssh"]),
            os.path.join(clonedir, ".git", "hooks")
        ]
        subprocess.check_call(cmd)
Example #9
0
def command(args):
    from decimal import Decimal as D
    import os
    from subprocess import check_output
    import sys

    import yaml

    from sr.tools import budget, spending
    from sr.tools.config import Config

    config = Config()

    try:
        root = budget.find_root()
    except budget.NotBudgetRepo:
        print("Error: Please run in budget.git", file=sys.stderr)
        exit(1)

    os.chdir(root)
    b = budget.load_budget("./")

    try:
        f = open("funds-in.yaml", "r")
    except IOError:
        if os.path.exists("check"):
            os.execv("./check", ["./check"] + sys.argv[1:])
        exit(1)

    funds_in = yaml.load(f)
    total_in = D(0)

    for i in funds_in["incoming"]:
        # Convert to str to avoid some rounding issues!
        total_in += D(str(i["amount"]))

    # All the lines in funds-in.yaml are divided by 1.1 at the moment
    MAX = total_in * budget.FUDGE_FACTOR

    # Calculate how much has been budgeted in total
    budgeted = D(0)
    for line in b.walk():
        budgeted += (D(1) + line.uncertainty) * line.cost

    if budgeted > MAX:
        print("Fail: Budget is £%s too high" % (budgeted - MAX),
              file=sys.stderr)
        exit(1)

    print("OK: ", end='')
    if budgeted == MAX:
        print("Budget is at maximum.")
    else:
        print("Budget is £%s below maximum." % (MAX - budgeted))

    def list_referenced_lines(root):
        """Return a list of budget lines referenced in ``spending.git``."""

        cmd = [
            "ledger", "--file",
            os.path.join(root, "spending.dat"), "reg", "^Expenses:",
            "--format", "%A\n"
        ]
        output = check_output(cmd, universal_newlines=True).strip()
        lines = output.splitlines()
        return [spending.account_to_budget_line(line) for line in lines]

    spending_root = args.spending
    if spending_root is None:
        spending_root_config = config.get("spending")
        if spending_root_config is not None:
            spending_root = os.path.expanduser(spending_root_config)

    if spending_root is not None:
        # Check stuff with spending.git
        inv_budget_lines = set()

        # Check that all transactions reference valid budget lines
        for line in list_referenced_lines(spending_root):
            try:
                b.path(line)

            except budget.InvalidPath:
                inv_budget_lines.add(line)

        if len(inv_budget_lines):
            print("{} non-existent budget lines referenced from spending.git:".
                  format(len(inv_budget_lines)))

            for line in inv_budget_lines:
                print(" -", line)
        else:
            print("OK: All spending.git budget line references are valid.")

        # Lines that have been closed but don't match their spends
        close_fail = {}

        # Lines that are over budget
        over_budget = {}

        # Load the budget again with spending information
        b = spending.load_budget_with_spending(spending_root)

        # Check that the spends line up with the budget moneywise
        for bline in b.walk():
            if bline.closed:
                # Closed lines must match their spent amount
                if bline.cost != bline.spent:
                    close_fail[bline] = bline.spent

                continue

            line_max = bline.cost * (D(1) + bline.uncertainty)
            if bline.spent > line_max:
                over_budget[bline] = bline.spent

        if len(close_fail):
            print("{0} closed lines do not match the amount spent against "
                  "them:".format(len(close_fail)))
            for line, spent in close_fail.items():
                print(" - {0}: £{1} spent, £{2} allocated".format(
                    line.name, spent, line.cost))
        else:
            print("OK: All closed lines have the correct value.")

        if len(over_budget):
            print("{0} lines are over budget:".format(len(over_budget)))
            for line, spent in over_budget.items():

                print(" - {0}: £{1} spent, £{2} allocated (including fudge)".
                      format(line.name, spent,
                             line.cost * budget.FUDGE_FACTOR))
        else:
            print("OK: No open budget lines are overspent.")
Example #10
0
def command(args):
    from decimal import Decimal as D
    import os
    from subprocess import check_output
    import sys

    import yaml

    from sr.tools import budget, spending
    from sr.tools.config import Config

    config = Config()

    try:
        root = budget.find_root()
    except budget.NotBudgetRepo:
        print("Error: Please run in budget.git", file=sys.stderr)
        exit(1)

    os.chdir(root)
    b = budget.load_budget("./")

    try:
        f = open("funds-in.yaml", "r")
    except IOError:
        if os.path.exists("check"):
            os.execv("./check", ["./check"] + sys.argv[1:])
        exit(1)

    funds_in = yaml.load(f)
    total_in = D(0)

    for i in funds_in["incoming"]:
        # Convert to str to avoid some rounding issues!
        total_in += D(str(i["amount"]))

    # All the lines in funds-in.yaml are divided by 1.1 at the moment
    MAX = total_in * budget.FUDGE_FACTOR

    # Calculate how much has been budgeted in total
    budgeted = D(0)
    for line in b.walk():
        budgeted += (D(1) + line.uncertainty) * line.cost

    if budgeted > MAX:
        print("Fail: Budget is £%s too high" %
              (budgeted - MAX), file=sys.stderr)
        exit(1)

    print("OK: ", end='')
    if budgeted == MAX:
        print("Budget is at maximum.")
    else:
        print("Budget is £%s below maximum." % (MAX - budgeted))

    def list_referenced_lines(root):
        """Return a list of budget lines referenced in ``spending.git``."""

        cmd = ["ledger",
               "--file", os.path.join(root, "spending.dat"),
               "reg", "^Expenses:",
               "--format", "%A\n"]
        output = check_output(cmd, universal_newlines=True).strip()
        lines = output.splitlines()
        return [spending.account_to_budget_line(line) for line in lines]

    spending_root = args.spending
    if spending_root is None:
        spending_root_config = config.get("spending")
        if spending_root_config is not None:
            spending_root = os.path.expanduser(spending_root_config)

    if spending_root is not None:
        # Check stuff with spending.git
        inv_budget_lines = set()

        # Check that all transactions reference valid budget lines
        for line in list_referenced_lines(spending_root):
            try:
                b.path(line)

            except budget.InvalidPath:
                inv_budget_lines.add(line)

        if len(inv_budget_lines):
            print("{} non-existent budget lines referenced from spending.git:"
                  .format(len(inv_budget_lines)))

            for line in inv_budget_lines:
                print(" -", line)
        else:
            print("OK: All spending.git budget line references are valid.")

        # Lines that have been closed but don't match their spends
        close_fail = {}

        # Lines that are over budget
        over_budget = {}

        # Load the budget again with spending information
        b = spending.load_budget_with_spending(spending_root)

        # Check that the spends line up with the budget moneywise
        for bline in b.walk():
            if bline.closed:
                # Closed lines must match their spent amount
                if bline.cost != bline.spent:
                    close_fail[bline] = bline.spent

                continue

            line_max = bline.cost * (D(1) + bline.uncertainty)
            if bline.spent > line_max:
                over_budget[bline] = bline.spent

        if len(close_fail):
            print("{0} closed lines do not match the amount spent against "
                  "them:".format(len(close_fail)))
            for line, spent in close_fail.items():
                print(" - {0}: £{1} spent, £{2} allocated".format(
                    line.name,
                    spent,
                    line.cost))
        else:
            print("OK: All closed lines have the correct value.")

        if len(over_budget):
            print("{0} lines are over budget:".format(len(over_budget)))
            for line, spent in over_budget.items():

                print(" - {0}: £{1} spent, £{2} allocated (including fudge)"
                      .format(line.name, spent,
                              line.cost * budget.FUDGE_FACTOR))
        else:
            print("OK: No open budget lines are overspent.")