-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathisaacscript_lua.py
More file actions
202 lines (150 loc) · 6.11 KB
/
isaacscript_lua.py
File metadata and controls
202 lines (150 loc) · 6.11 KB
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# pylint: disable=missing-function-docstring
# pylint: disable=missing-module-docstring
# pylint: disable=line-too-long
#!/usr/bin/env python
import argparse
import json
import os
import pathlib
import re
import shutil
import sys
import tempfile
import urllib.request
import pkg_resources
if sys.version_info < (3, 0):
printf("Error: This script requires Python 3.")
sys.exit(1)
# Constants
VERSION = pkg_resources.get_distribution("isaacscript_lua").version
DIR = os.getcwd()
PROJECT_NAME = os.path.basename(DIR)
FILE_NAMES_TO_CHECK = ["main.lua", "metadata.xml"]
LIBRARY_NAME = "isaacscript-common"
def main():
args = parse_command_line_arguments()
check_lua_project()
match args.command:
case "install":
command_install()
case "update":
command_update()
case _:
error(
f'The command of "{args.command}" is invalid. Valid commands are: install, update'
)
def parse_command_line_arguments():
parser = argparse.ArgumentParser(
description="Manage the IsaacScript libraries in a Lua project."
)
parser.add_argument(
"command",
type=str,
help="the command to run (e.g. install, update)",
)
parser.add_argument(
"-v",
"--version",
action="version",
help="display the version",
version=VERSION,
)
return parser.parse_args()
def check_lua_project():
for file_name in FILE_NAMES_TO_CHECK:
file_path = os.path.join(DIR, file_name)
if not os.path.exists(file_path):
error(
f'You must run this script in the working directory corresponding to an Isaac mod written in Lua with a "{file_name}" file in it.'
)
def command_install():
check_namespace_directory()
def check_namespace_directory():
namespace_directory_path = os.path.join(DIR, PROJECT_NAME)
if not os.path.isdir(namespace_directory_path):
printf(
f"Failed to locate your namespaced directory for your Lua source files at: {namespace_directory_path}"
)
printf(
"This directory is mandatory to avoid namespacing conflicts with other mods in the Lua ecosystem. See the docs for more information: https://wofsauge.github.io/IsaacDocs/rep/tutorials/Using-Additional-Lua-Files.html"
)
error(
"If you don't have your Lua code in a namespaced directory already, this is probably a bug in your mod. Create the aforementioned directory and then re-run the installer."
)
library_file_name = LIBRARY_NAME + ".lua"
lib_directory_path = os.path.join(namespace_directory_path, "lib")
if not os.path.isdir(lib_directory_path):
os.mkdir(lib_directory_path)
destination_path = os.path.join(lib_directory_path, library_file_name)
version = get_latest_version_of_library()
url = get_url_for_library(version)
printf(f'Getting "{LIBRARY_NAME}" version "{version}" from: {url}')
urllib.request.urlretrieve(url, destination_path)
printf(f"Installed: {destination_path}")
def command_update():
library_file_name = LIBRARY_NAME + ".lua"
found_at_least_one = False
for file_path in pathlib.Path(DIR).rglob(library_file_name):
found_at_least_one = True
check_if_library_needs_update(file_path)
if not found_at_least_one:
printf(f'Did not find any files called "{library_file_name}". Skipping.')
def check_if_library_needs_update(old_file_path: pathlib.Path):
library_name = old_file_path.stem
with open(old_file_path, encoding="utf-8") as file_handle:
old_file_contents = file_handle.read()
current_version = get_version_from_lua_contents(
library_name, old_file_contents, old_file_path
)
url = get_url_for_library(library_name)
printf(f'Checking for the latest version of "{library_name}" from: {url}')
with urllib.request.urlopen(url) as response:
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
shutil.copyfileobj(response, tmp_file)
with open(tmp_file.name, encoding="utf8") as file_handle:
new_file_contents = file_handle.read()
latest_version = get_version_from_lua_contents(library_name, new_file_contents, url)
if current_version == latest_version:
printf(f"Version {current_version} is the latest version for: {library_name}")
os.remove(tmp_file.name)
return
printf(f"Old version detected for: {library_name}")
printf(f"Upgrading from {current_version} --> {latest_version}")
shutil.move(tmp_file.name, old_file_path)
printf("Complete.")
def get_version_from_lua_contents(
library_name: str, file_contents: str, file_path: str
):
match = re.search(
r"^" + library_name + r" (\d+\.\d+\.\d+)$", file_contents, re.MULTILINE
)
if not match:
error(f'Failed to parse the version from the "{file_path}" file.')
return match.group(1)
def get_latest_version_of_library():
# The API endpoint requires a user agent to be set.
version_url = f"https://api.npms.io/v2/package/{LIBRARY_NAME}"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1)"}
request = urllib.request.Request(url=version_url, headers=headers)
printf(f"Getting the latest version from: {version_url}")
with urllib.request.urlopen(request) as response:
package_info_string = response.read().decode("utf-8")
package_info = json.loads(package_info_string)
if "collected" not in package_info:
error('Failed to find the "collected" field in the package info.')
collected = package_info["collected"]
if "metadata" not in collected:
error('Failed to find the "metadata" field in the package info.')
metadata = collected["metadata"]
if "version" not in metadata:
error('Failed to find the "version" field in the package info.')
return metadata["version"]
def get_url_for_library(version: str):
return f"https://unpkg.com/{LIBRARY_NAME}@{version}/dist/{LIBRARY_NAME}.lua"
def error(msg: str):
printf("Error:", msg)
sys.exit(1)
def printf(*args):
print(*args, flush=True)
if __name__ == "__main__":
main()