-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbootstrap.py
executable file
·129 lines (102 loc) · 4.27 KB
/
bootstrap.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
#!/usr/bin/env python3
import os
import subprocess
import sys
from subprocess import CalledProcessError
def eprint(msg):
print(msg, file=sys.stderr)
if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 11):
eprint("This script requires python version 3.11 or greater")
exit(1)
import tomllib # requires Python >= 3.11
with open("slm.toml", "rb") as f:
data = tomllib.load(f)
DEPENDENCIES = data["dependencies"]
SLM_DIR = os.path.join(os.getcwd(), ".slm")
SLM_PKGS_DIR = os.path.join(SLM_DIR, "pkgs")
SLM_DEPS_DIR = os.path.join(SLM_DIR, "deps")
SLM_PKGCACHE_DIR = os.path.join(SLM_DIR, "pkg-cache")
def error(msg):
print(msg, file=sys.stderr)
sys.exit(1)
def check_run (*args, **kwargs):
kwargs["check"] = True
subprocess.run(*args, **kwargs)
def version_to_tag(version):
if version == "latest":
return "HEAD"
else:
return f"v{version}"
def package_to_url(package):
def git_url(package): return f"[email protected]:{package}"
def https_url(package): return f"https://github.com/{package}"
PROTOCOLS = { "git": git_url, "https": https_url, None: git_url }
return PROTOCOLS[os.environ.get("SLM_PROTOCOL")](package)
def fetch_package_into(path, package, version):
rev = version_to_tag(version)
url = package_to_url(package)
try:
eprint(f"slm bootstrap: fetching {package} {version} into {path}")
check_run(["git", "clone", "--depth", "1", "--quiet", url, path])
check_run(["git", "fetch", "--tags", "--quiet"], cwd=path)
check_run(["git", "checkout", "--quiet", "--force", rev], cwd=path)
except CalledProcessError:
error(f"failed fetching package {package}")
def download_conan_package_into(path, package, version, options):
import bootstrap_conan_utils as bcu
import tarfile
eprint(f"slm bootstrap: downloading \"{package}/{version}\" with options \"{options}\"")
cv = bcu.ConanVersion(package, version)
cv = bcu.conan_fully_qualify_latest_version(cv, options=options)
pfilename = bcu.conan_download_package(cv)
eprint(f"downloaded \"{pfilename}\", extracting to {path}")
tarfile.open(pfilename).extractall(path)
def generate_stanza_proj():
dep_proj_files = []
for dep in DEPENDENCIES.keys():
dep_path = os.path.join(SLM_DEPS_DIR, dep, "stanza.proj")
# For Windows - we replace the `\` with `/` so that the
# 'stanza build' invokation will actually run. Otherwise,
# stanza treats the `\` as an escape sequence and fails to build.
# On Mac/Linux - this should do nothing.
dep_unnorm = dep_path.replace(os.sep, '/')
dep_proj_files.append(dep_unnorm)
with open(os.path.join(SLM_DIR, "stanza.proj"), "w") as f:
f.writelines([f'include? "{proj_file}"\n' for proj_file in dep_proj_files])
def bootstrap(args):
# Create bootstrap dir structure
os.makedirs(SLM_DIR)
os.makedirs(SLM_PKGS_DIR)
os.makedirs(SLM_DEPS_DIR)
os.makedirs(SLM_PKGCACHE_DIR)
# Clone dependencies
for dependency, specifier in DEPENDENCIES.items():
eprint(f"dep \"{dependency}\" = \"{specifier}\"")
path = os.path.join(SLM_DEPS_DIR, dependency)
if "git" in specifier:
package = specifier["git"]
version = specifier["version"]
fetch_package_into(path, package, version)
elif "pkg" in specifier and "type" in specifier and specifier["type"]=="conan":
package = specifier["pkg"]
version = specifier["version"]
options = specifier["options"]
download_conan_package_into(path, package, version, options)
else:
error(f"unknown dependency type: \"{dependency}\" = \"{specifier}\"")
# Generate stanza.proj for build
generate_stanza_proj()
# Attempt to build the project and packages
try:
check_run(["stanza", "build"] + args)
except CalledProcessError:
error("Bootstrap failed trying to run `stanza build`")
slm_path = os.path.join(os.getcwd(), "slm")
print(f"slm bootstrapped: run `{slm_path} build` to finish building.")
def main(args):
if os.path.exists(SLM_DIR):
error(f"'{SLM_DIR}' exists, was `slm` already bootstrapped?")
bootstrap(args)
if __name__ == "__main__":
import sys
main(sys.argv[1:])