llvm_cov_refryer 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/usr/bin/env python3
  2. import os
  3. import shutil
  4. import argparse
  5. from bs4 import BeautifulSoup
  6. # Function to recursively search for the "Source" directory
  7. def find_source_dir(starting_path, source_dir):
  8. for root, dirs, files in os.walk(starting_path):
  9. if source_dir in dirs:
  10. source_path = os.path.join(root, source_dir)
  11. before_source = os.path.relpath(source_path, starting_path)
  12. after_source = os.path.relpath(starting_path, source_path)
  13. return before_source
  14. return None, None
  15. def check_for_siblings(docs_root, source_dir):
  16. all_dirs = [os.path.join(docs_root, d) for d in os.listdir(docs_root) if os.path.isdir(os.path.join(docs_root, d))]
  17. if not os.path.exists(docs_root):
  18. return 1, None
  19. source_path = os.path.abspath(os.path.join(docs_root, source_dir))
  20. if not os.path.exists(source_path):
  21. return 2, all_dirs
  22. sibling_dirs = [d for d in all_dirs if not os.path.samefile(d, source_path)]
  23. if sibling_dirs:
  24. return 3, sibling_dirs
  25. return 0, None
  26. def has_files(path):
  27. for root, _, files in os.walk(path):
  28. if files:
  29. return True
  30. return False
  31. def delete_empty_directory(relative_path):
  32. absolute_path = os.path.abspath(relative_path)
  33. if not os.path.exists(absolute_path):
  34. print(f"Directory does not exist: {relative_path}")
  35. return
  36. if has_files(absolute_path):
  37. print(f"Directory is not empty: {relative_path}")
  38. return
  39. try:
  40. shutil.rmtree(absolute_path)
  41. print(f"Deleted: {relative_path}")
  42. except OSError as e:
  43. print(f"Error deleting directory: {e}")
  44. def remove_directory_if_exists(relative_path):
  45. absolute_path = os.path.abspath(relative_path)
  46. if os.path.exists(absolute_path) and os.path.isdir(absolute_path):
  47. try:
  48. shutil.rmtree(absolute_path)
  49. print(f"Removed directory and its contents: {relative_path}")
  50. except OSError as e:
  51. print(f"Error removing directory: {e}")
  52. else:
  53. print(f"Directory does not exist: {relative_path}")
  54. def process_docs(source_dir, docs_root):
  55. # Define the path to the index.html file
  56. index_html_path = os.path.join(docs_root, "index.html")
  57. # Read the index.html file
  58. with open(index_html_path, "r") as html_file:
  59. index_html_content = html_file.read()
  60. html = BeautifulSoup(index_html_content, "html.parser")
  61. # Modify links and associated html files within each tr.light-row
  62. for tr in html.find_all("tr", class_="light-row"):
  63. link = tr.find("a", href=True)
  64. if link:
  65. href = link["href"]
  66. # Fix linked file title and css href
  67. filepath = os.path.join(docs_root, href)
  68. fix_code_html(filepath, source_dir)
  69. source_root_index = href.find(source_dir)
  70. if source_root_index != -1:
  71. trimmed_href = href[source_root_index:]
  72. link["href"] = f"coverage/{trimmed_href}"
  73. # Save the modified HTML content back to the index.html file
  74. with open(index_html_path, "w") as modified_html_file:
  75. modified_html_file.write(str(html))
  76. def fix_code_html(path_filename, source_dir):
  77. with open(path_filename, "r") as html_file:
  78. html_content = html_file.read()
  79. html = BeautifulSoup(html_content, "html.parser")
  80. # fix css href
  81. link = html.find("link")
  82. css = link["href"].split('/')[-1]
  83. depth = path_filename.split("Source")[-1].count('/')
  84. parent_nav = "../" * (depth + 1)
  85. link["href"] = f"{parent_nav}{css}"
  86. # fix title
  87. title = html.select_one('.source-name-title pre')
  88. fixed_title = f".../{source_dir}{title.text.split(source_dir)[-1]}"
  89. title.string = fixed_title
  90. # resave
  91. with open(path_filename, "w") as html_file:
  92. html_file.write(str(html))
  93. # Parse command line arguments
  94. parser = argparse.ArgumentParser(description="Transmogrify a llvm-cov report to use relative paths to source.")
  95. parser.add_argument("--source-dir", required=True, help="Name of Source directory within the report coverage/ path")
  96. parser.add_argument("--docs-root", required=True, help="Path to the docs folder containing index.html and coverage/ path.")
  97. args = parser.parse_args()
  98. coverage_path = os.path.join(args.docs_root, "coverage")
  99. status, dirs = check_for_siblings(coverage_path, args.source_dir)
  100. if status == 1:
  101. print(f"{args.docs_root} does not exist.")
  102. exit(1)
  103. if status == 3:
  104. remove_directory_if_exists(os.path.join(coverage_path, args.source_dir))
  105. process_docs(args.source_dir, args.docs_root)
  106. source_path = os.path.join(args.docs_root, "coverage", find_source_dir(coverage_path, args.source_dir))
  107. shutil.move(source_path, coverage_path)
  108. # We can assume the original folder tree starts
  109. # with Users so we will delete that carefully
  110. disgraced_former_cov_docs_path = os.path.join(coverage_path, "Users")
  111. # Delete the original path, if it's tree is empty.
  112. delete_empty_directory(disgraced_former_cov_docs_path)