Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
expandDBD 3.20 KiB
#!/usr/bin/env python
from __future__ import print_function

import argparse
import os
import re
import sys

SCANNED_FILES = set()
RECORD_REGEX = re.compile(r"include[ \t]*\"?((.*)Record.dbd)\"?")
INCLUDE_REGEX = re.compile(r"include[ \t]+\"?([^\"]*)\"?")
BLANK_LINE_REGEX = re.compile(r"^[ \t]*(#|%|$)")


def find_dbd_file(filename, include_paths):
    """Search for a given .dbd file among the include paths."""
    for include_path in include_paths:
        potential_path = os.path.join(include_path, filename)
        if os.path.exists(potential_path):
            return potential_path
    return None


def open_dbd_file(current_file, filename, includes=None):
    """Open a .dbd file and return the lines."""
    if not includes:
        includes = ["."]

    basename = os.path.basename(filename)
    if basename in SCANNED_FILES:
        print(
            "Info: skipping duplicate file {basename} included from {current_file}".format(
                basename=basename, current_file=current_file
            ),
            file=sys.stderr,
        )
        return []
    dbd_file = find_dbd_file(basename, includes)
    if dbd_file is None:
        print("File '{basename}' not found".format(basename=basename), file=sys.stderr)
        sys.exit(1)
    if basename != "dbCommon.dbd":
        SCANNED_FILES.add(basename)
    with open(dbd_file, "r") as f:
        return [line.rstrip() for line in f.readlines()]


def expand_dbd_file(current_file, dbdlines, includes):
    """Print to stdout a fully-expanded .dbd file."""
    for line in dbdlines:
        if BLANK_LINE_REGEX.match(line):
            continue
        m = INCLUDE_REGEX.search(line)
        if m:
            lines = open_dbd_file(current_file, m.group(1), includes)
            expand_dbd_file(m.group(1), lines, includes)
        else:
            print(line)


def parse_record_dbd_file(current_file, dbdlines, includes):
    """Recursively search through .dbd files for xRecord.dbd, and print the record names."""
    for line in dbdlines:
        if BLANK_LINE_REGEX.match(line):
            continue
        m = RECORD_REGEX.search(line)
        if m:
            if find_dbd_file(m.group(1), includes):
                print(m.group(2))
            else:
                print(
                    "File '{group}' not found".format(group=m.group(1)), file=sys.stderr
                )
                sys.exit(1)
            continue
        m = INCLUDE_REGEX.search(line)
        if m:
            lines = open_dbd_file(current_file, m.group(1), includes)
            parse_record_dbd_file(m.group(1), lines, includes)


def handle_dbd_file(dbdfiles, include, record_types):
    """Process the .dbd files."""
    for dbdfile in dbdfiles:
        lines = open_dbd_file("command line", dbdfile, include)
        if record_types:
            parse_record_dbd_file(dbdfile, lines, include)
        else:
            expand_dbd_file(dbdfile, lines, include)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-I", "--include", action="append")
    parser.add_argument("-r", "--record-types", action="store_true")
    parser.add_argument("dbdfiles", nargs="+")

    args = parser.parse_args()

    handle_dbd_file(**vars(args))


if __name__ == "__main__":
    main()