mirror of
https://github.com/godotengine/godot-docs.git
synced 2025-12-31 17:49:03 +03:00
The program moves a list of rst files along with their image dependencies to a target directory. It then outputs redirects in the format the ReadTheDocs backend expects.
109 lines
3.7 KiB
Python
109 lines
3.7 KiB
Python
import re
|
|
from argparse import ArgumentParser
|
|
from os.path import isfile, isdir, join, realpath, split, dirname, relpath
|
|
import os
|
|
import shutil
|
|
|
|
|
|
def parse_and_get_arguments():
|
|
"""Creates and returns an object with parsed arguments, using argparse."""
|
|
parser: ArgumentParser = ArgumentParser(
|
|
prog="move_rst_files",
|
|
description="Moves reST documents and their dependencies from one folder to another. Outputs required redirections in the ReadTheDocs backend.",
|
|
)
|
|
parser.add_argument(
|
|
"documents", nargs="+", help="Paths of documents to move.",
|
|
)
|
|
parser.add_argument(
|
|
"output_path", help="Path to the target output directory.",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def find_project_root_path(document_path):
|
|
"""Returns the path to the repository's root directory by looking for the file conf.py, starting
|
|
from the path of any file in the project."""
|
|
full_path = realpath(document_path)
|
|
dirpath = split(full_path)[0]
|
|
|
|
root_path = ""
|
|
current = dirpath
|
|
iterations = 0
|
|
while root_path == "":
|
|
if isfile(join(current, "conf.py")):
|
|
root_path = current
|
|
else:
|
|
current = split(current)[0]
|
|
if current == "":
|
|
break
|
|
iterations += 1
|
|
if iterations > 20:
|
|
break
|
|
return root_path
|
|
|
|
|
|
def find_images(document):
|
|
"""Returns the list of image filepaths used by the `document`."""
|
|
images = []
|
|
for line in document:
|
|
match = re.match(r"\.\. image::\s+(img\/.+)", line)
|
|
if match:
|
|
images.append(match[1])
|
|
return list(set(images))
|
|
|
|
|
|
def find_document_dependencies(documents):
|
|
"""For each document path in `documents`, finds all pictures it depends on and returns a dict with the form { document: [images] }."""
|
|
data = {}
|
|
for path in documents:
|
|
with open(path, "r") as rst_file:
|
|
images = find_images(rst_file)
|
|
data[path] = images
|
|
return data
|
|
|
|
|
|
def move_documents(paths, output_path):
|
|
"""Moves .rst files and all their image dependencies to `output_path`"""
|
|
data = find_document_dependencies(paths)
|
|
for path in data:
|
|
directory = dirname(path)
|
|
shutil.move(path, output_path)
|
|
for image in data[path]:
|
|
image_in_path = join(directory, image)
|
|
image_out_path = join(output_path, image)
|
|
image_out_dirpath = dirname(image_out_path)
|
|
if not isdir(image_out_dirpath):
|
|
os.makedirs(image_out_dirpath)
|
|
shutil.move(image_in_path, image_out_path)
|
|
|
|
|
|
def print_redirects(paths):
|
|
"""Prints redirects we need to make on the ReadTheDocs backend with the form "input -> output".
|
|
Moving the file /learning/features/viewports/viewports.rst to /tutorials/viewports/viewports.rst
|
|
Requires the following redirect:
|
|
/learning/features/viewports/viewports.html -> /tutorials/viewports/viewports.html
|
|
"""
|
|
redirects = ""
|
|
project_root_path = find_project_root_path(paths[0])
|
|
out_path_relative = relpath(args.output_path, project_root_path)
|
|
for document in paths:
|
|
in_path_relative = relpath(document, project_root_path)
|
|
in_directory, filename_rst = split(in_path_relative)
|
|
filename_html = filename_rst.rsplit(".rst", 1)[0] + ".html"
|
|
|
|
in_path = join(in_directory, filename_html)
|
|
out_path = join(out_path_relative, filename_html)
|
|
redirects += in_path + " -> " + out_path + "\n"
|
|
print(redirects)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = parse_and_get_arguments()
|
|
assert isdir(args.output_path)
|
|
|
|
documents = [
|
|
path for path in args.documents if isfile(path) and path.endswith(".rst")
|
|
]
|
|
move_documents(documents, args.output_path)
|
|
print_redirects(documents)
|