File indexing completed on 2024-04-14 03:50:24

0001 #! /usr/bin/env python3
0002 # -*- coding: utf-8 -*-
0003 #
0004 # SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org>
0005 #
0006 # SPDX-License-Identifier: BSD-2-Clause
0007 
0008 import argparse
0009 import os
0010 import logging
0011 import shutil
0012 import subprocess
0013 import sys
0014 import tempfile
0015 import time
0016 
0017 from kapidox import utils
0018 
0019 DESCRIPTION = """
0020 Generate Graphviz dot files for one or all frameworks.
0021 """
0022 
0023 
0024 def generate_dot(fw_dir, fw_name, output_dir):
0025     """Calls cmake to generate the dot file for a framework.
0026 
0027     Returns true on success, false on failure"""
0028     dot_path = os.path.join(output_dir, fw_name + ".dot")
0029     build_dir = tempfile.mkdtemp(prefix="depdiagram-prepare-build-")
0030     try:
0031         ret = subprocess.call(["cmake", fw_dir, "--graphviz={}".format(dot_path)],
0032                               stdout=open("/dev/null", "w"),
0033                               cwd=build_dir)
0034         if ret != 0:
0035             if os.path.exists(dot_path):
0036                 os.remove(dot_path)
0037             logging.error("Generating dot file for {} failed.".format(fw_name))
0038             return False
0039         # Add a timestamp and version info to help with diagnostics
0040         with open(dot_path, "a") as f:
0041             f.write("\n# Generated on {}\n".format(time.ctime()))
0042             version = utils.get_kapidox_version()
0043             if version:
0044                 f.write("# By {} {}\n".format(sys.argv[0], version))
0045     finally:
0046         shutil.rmtree(build_dir)
0047     return True
0048 
0049 
0050 def prepare_one(fw_dir, output_dir):
0051     fw_name = utils.parse_fancyname(fw_dir)
0052     if fw_name is None:
0053         return False
0054 
0055     yaml_path = os.path.join(fw_dir, "metainfo.yaml")
0056     if not os.path.exists(yaml_path):
0057         logging.error(f"'{fw_dir}' is not a framework: '{yaml_path}' does not exist.")
0058         return False
0059 
0060     if not os.path.exists(output_dir):
0061         os.makedirs(output_dir)
0062 
0063     if not generate_dot(fw_dir, fw_name, output_dir):
0064         return False
0065     shutil.copyfile(yaml_path, os.path.join(output_dir, fw_name + ".yaml"))
0066     return True
0067 
0068 
0069 def prepare_all(fw_base_dir, dot_dir):
0070     """Generate dot files for all frameworks.
0071 
0072     Looks for frameworks in `fw_base_dir`. Output the dot files in sub dirs of
0073     `dot_dir`.
0074     """
0075     lst = os.listdir(fw_base_dir)
0076     fails = []
0077     for idx, fw_name in enumerate(lst):
0078         fw_dir = os.path.join(fw_base_dir, fw_name)
0079         if not os.path.isdir(fw_dir):
0080             continue
0081 
0082         progress = int(100 * (idx + 1) / len(lst))
0083         print(f'{progress}% {fw_name}')
0084         if not prepare_one(fw_dir, dot_dir):
0085             fails.append(fw_name)
0086     return fails
0087 
0088 
0089 def main():
0090     parser = argparse.ArgumentParser(description=DESCRIPTION)
0091 
0092     group = parser.add_mutually_exclusive_group(required=True)
0093     group.add_argument("-s", "--single",
0094                        help="Generate dot files for the framework stored in DIR",
0095                        metavar="DIR")
0096     group.add_argument("-a", "--all",
0097                        help="Generate dot files for all frameworks whose dir is in BASE_DIR",
0098                        metavar="BASE_DIR")
0099     parser.add_argument("dot_dir",
0100                         help="Destination dir where dot files will be generated")
0101 
0102     args = parser.parse_args()
0103 
0104     dot_dir = os.path.abspath(args.dot_dir)
0105 
0106     if args.single:
0107         fw_dir = os.path.abspath(args.single)
0108         if prepare_one(fw_dir, dot_dir):
0109             return 0
0110         else:
0111             return 1
0112     else:
0113         fw_base_dir = os.path.abspath(args.all)
0114         fails = prepare_all(fw_base_dir, dot_dir)
0115         if fails:
0116             logging.error("{} framework(s) failed: {}".format(len(fails), ", ".join(fails)))
0117             return 1
0118         else:
0119             return 0
0120 
0121 
0122 if __name__ == "__main__":
0123     sys.exit(main())