def write_package_graph(data):
    log_block("writing package dependency graph")

    already_written = {}

    with open('packages.gv', 'w') as output:
        output.write("digraph G {\n")

        for container in myConfig.libraries:
            output.write(" subgraph \"" + build_package_cluster_name(container) + "\" {\n")
            for package in myConfig.libraries[container]:
                output.write("  " + package + ";\n")
            output.write(" }\n")

        for cfile in data.files:
            src = find_package_for_file(cfile, data)
            if src is None:
                continue
            for include in data.all_includes[cfile]:
                dst = None
                if include in data.include_path_mapping:
                    dst = find_package_for_file(data.include_path_mapping[include], data)
                else:
                    dst = find_package_for_file(include, data)
                if dst is None or src is dst:
                    continue
                line = src + " -> " + dst + ";\n"
                if line not in already_written:
                    output.write(line)
                    already_written[line] = True
        output.write("}\n")
def process_files(data):
    log_block("start removing includes from files")

    while len(data.files) > 0:
        logging.info("-" * 60)
        oldsize = len(data.files)
        for file in data.files[:]:
            if file in data.includes:
                continue
            logging.info("Processing: " + file)
            remove_file_from_includes(file, " needed from:", data)
            data.files.remove(file)
            if len(data.limit_files) > 0 and not any(x in file for x in data.limit_files):
                logging.info("  Skipping.")
                continue
            validate_includes(file, data)
        if oldsize == len(data.files):
            break
def write_lib_graph(data):
    log_block("writing library dependency graph")
    dependencies, ignore = build_lib_dependencies(data)
    with open('libraries.gv', 'w') as output:
        output.write("digraph G {\n")
        for src in dependencies.keys():
            for dst in dependencies[src]:
                line = ""
                if src in myConfig.dependencies and dst in myConfig.dependencies[src]:
                    line = src + " -> " + dst + ";\n"
                else:
                    line = src + " -> " + dst + " [color = red];\n"
                output.write(line)
        for src in myConfig.dependencies:
            for dst in myConfig.dependencies[src]:
                if src in dependencies and dst in dependencies[src]:
                    continue
                else:
                    line = src + " -> " + dst + " [color = blue];\n"
                    output.write(line)
        output.write("}\n")
def process_leftover_files(data):
    log_block("Files with possible errors in includes (e.g. a cycle), extra round:")

    for file in data.files:
        logging.warn("File: " + file)
        validate_includes(file, data)
                continue
            logging.info("Processing: " + file)
            remove_file_from_includes(file, " needed from:", data)
            data.files.remove(file)
            if len(data.limit_files) > 0 and not any(x in file for x in data.limit_files):
                logging.info("  Skipping.")
                continue
            validate_includes(file, data)
        if oldsize == len(data.files):
            break


def process_leftover_files(data):
    log_block("Files with possible errors in includes (e.g. a cycle), extra round:")

    for file in data.files:
        logging.warn("File: " + file)
        validate_includes(file, data)

data = prepare_include_data()

remove_files_without_includes(data)

check_compiler()

process_files(data)

process_leftover_files(data)

log_block("Removed includes:" + str(data.removed_includes) + "/Preserved includes:" + str(data.preserved_includes))