forked from facebook/buck2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdocs.py
executable file
·130 lines (108 loc) · 3.7 KB
/
docs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python3
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under both the MIT license found in the
# LICENSE-MIT file in the root directory of this source tree and the Apache
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.
"""
Generate API documentation for the website.
"""
import argparse
import os
import subprocess
import tempfile
from pathlib import Path
def read_file(path):
with open(path, "r") as f:
return f.read()
def write_file(path, contents):
with open(path, "w") as f:
f.write(contents)
def buck_command(args):
if args.buck2:
return args.buck2
elif args.prod:
return "buck2"
elif args.cargo:
return "cargo run --bin=buck2 --"
else:
return "./buck2.sh"
# Given the path to the documentation, e.g. native/bxl/analysis_result
# produce a new name which is the destination, e.g. bxl/analysis_result
def doc_name(x):
if x.startswith("native/bxl/"):
return x[7:] # drop the native
elif x.endswith("/rules.bzl"):
return "rules"
elif x.endswith("/function"):
# Uninteresting docs we'd rather not have generated
return None
elif x.startswith("native/standard/") or x.startswith("native/extension/"):
return "starlark/" + x.split("/")[-1]
elif x.startswith("native/"):
return "build/" + x[7:]
else:
raise RuntimeError("Unknown name: " + x)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument(
"--prod",
action="store_true",
default=False,
help="Whether to use the production `buck2` binary",
)
parser.add_argument(
"--cargo",
action="store_true",
default=False,
help="Whether to use a `cargo` built binary.",
)
parser.add_argument(
"--buck2",
nargs="?",
help="Whether to use provided binary.",
)
args = parser.parse_args()
# Change to buck2 directory
buck2_dir = Path(__file__).parent.absolute()
os.chdir(str(buck2_dir))
# Clear the docs folder first so that if we change the names of any
# objects, we'll remove old docs
for x in Path("docs").rglob("*.generated.md"):
os.remove(x)
# Copy the starlark docs over. docusaurus does not handle upward path traversal very well.
for x in Path("starlark-rust/docs").glob("*.md"):
name = Path(x).stem
prefix = "---\nid: " + name + "\n---\n"
write_file(
"docs/developers/starlark/" + name + ".generated.md", prefix + read_file(x)
)
with tempfile.TemporaryDirectory() as tmp:
# Actually generate the docs
print("Running Buck...")
subprocess.run(
buck_command(args)
+ " docs starlark --format=markdown_files --markdown-files-destination-dir="
+ tmp
+ " --builtins prelude//docs:rules.bzl",
shell=True,
check=True,
)
for orig in Path(tmp).rglob("*.md"):
src = read_file(orig)
path = os.path.relpath(orig, tmp)
if path.endswith(".md"):
path = path[:-3]
name = doc_name(path)
if name is None:
continue
prefix = "---\nid: " + name.rsplit("/")[-1] + "\n---\n"
if name == "rules":
prefix += "# Rules\n\nThese rules are available as standard in Buck2.\n"
src = "\n".join(src.splitlines()[1:])
dest = "docs/api/" + name + ".generated.md"
os.makedirs(Path(dest).parent, exist_ok=True)
write_file(dest, prefix + src)
if __name__ == "__main__":
main()