forked from tgstation/TerraGov-Marine-Corps
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: TiviPlus <[email protected]>
- Loading branch information
Showing
20 changed files
with
455 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Quickly setting up a development database with ezdb | ||
While you do not need a database to code for tgmc, it is a prerequisite to many important features, especially on the admin side. Thus, if you are working in any code that benefits from it, it can be helpful to have one handy. | ||
|
||
**ezdb** is a tool for quickly setting up an isolated development database. It will manage downloading MariaDB, creating the database, setting it up, and updating it when the code evolves. It is not recommended for use in production servers, but is perfect for quick development. | ||
|
||
To run ezdb, go to `tools/ezdb`, and double-click on ezdb.bat. This will set up the database on port 1338, but you can configure this with `--port`. When it is done, you should be able to launch tgstation as normal and have database access. This runs on the same Python bootstrapper as things like the map merge tool, which can sometimes be flaky. | ||
|
||
If you wish to delete the ezdb database, delete the `db` folder as well as `config/ezdb.txt`. | ||
|
||
To update ezdb, run the script again. This will both look for any updates in the database changelog, as well as update your schema revision. | ||
|
||
Contact Mothblocks if you face any issues in this process. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import argparse | ||
from .steps import STEPS | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument("--port", type = int, default = 1338) | ||
|
||
args = parser.parse_args() | ||
|
||
for step in STEPS: | ||
if not step.should_run(): | ||
continue | ||
|
||
step.run(args) | ||
|
||
print("Done!") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
@call "%~dp0\..\bootstrap\python" -m ezdb %* | ||
@pause |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import re | ||
from dataclasses import dataclass | ||
from .paths import get_changelog_path | ||
|
||
REGEX_CHANGE = r"-+\s*Version (?P<major>[0-9]+)\.(?P<minor>[0-9]+), .+?\`\`\`sql\s*(?P<sql>.+?)\s*\`\`\`.*?-{5}" | ||
|
||
@dataclass | ||
class Change: | ||
major_version: int | ||
minor_version: int | ||
sql: str | ||
|
||
def get_changes() -> list[Change]: | ||
with open(get_changelog_path(), "r") as file: | ||
changelog = file.read() | ||
changes = [] | ||
|
||
for change_match in re.finditer(REGEX_CHANGE, changelog, re.MULTILINE | re.DOTALL): | ||
changes.append(Change( | ||
int(change_match.group("major")), | ||
int(change_match.group("minor")), | ||
change_match.group("sql") | ||
)) | ||
|
||
changes.sort(key = lambda change: (change.major_version, change.minor_version), reverse = True) | ||
|
||
return changes | ||
|
||
def get_current_version(): | ||
changes = get_changes() | ||
return (changes[0].major_version, changes[0].minor_version) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from .paths import get_config_path | ||
from typing import Optional | ||
|
||
def read_config() -> Optional[dict[str, str]]: | ||
config_path = get_config_path() | ||
if not config_path.exists(): | ||
return None | ||
|
||
with config_path.open('r') as file: | ||
lines = file.readlines() | ||
entries = {} | ||
|
||
for line in lines: | ||
if line.startswith("#"): | ||
continue | ||
if " " not in line: | ||
continue | ||
|
||
key, value = line.split(" ", 1) | ||
entries[key.strip()] = value.strip() | ||
|
||
return entries |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import atexit | ||
import mysql.connector | ||
import subprocess | ||
from contextlib import closing | ||
from .config import read_config | ||
from .paths import get_mariadb_client_path, get_mariadb_daemon_path | ||
|
||
def open_connection(): | ||
config = read_config() | ||
assert config["FEEDBACK_PASSWORD"] is not None, "No password found in config file" | ||
|
||
connection = mysql.connector.connect( | ||
user = config["FEEDBACK_LOGIN"], | ||
password = config["FEEDBACK_PASSWORD"], | ||
port = int(config["PORT"]), | ||
raise_on_warnings = True, | ||
) | ||
|
||
connection.autocommit = True | ||
|
||
return closing(connection) | ||
|
||
# We use custom things like delimiters, so we can't use the built-in cursor.execute | ||
def execute_sql(sql: str): | ||
config = read_config() | ||
assert config is not None, "No config file found" | ||
assert config["FEEDBACK_PASSWORD"] is not None, "No password found in config file" | ||
|
||
subprocess.run( | ||
[ | ||
str(get_mariadb_client_path()), | ||
"-u", | ||
"root", | ||
"-p" + config["FEEDBACK_PASSWORD"], | ||
"--port", | ||
config["PORT"], | ||
"--database", | ||
config["FEEDBACK_DATABASE"], | ||
], | ||
input = sql, | ||
encoding = "utf-8", | ||
check = True, | ||
stderr = subprocess.STDOUT, | ||
) | ||
|
||
def insert_new_schema_query(major_version: int, minor_version: int): | ||
return f"INSERT INTO `schema_revision` (`major`, `minor`) VALUES ({major_version}, {minor_version})" | ||
|
||
process = None | ||
def start_daemon(): | ||
global process | ||
if process is not None: | ||
return | ||
|
||
print("Starting MariaDB daemon...") | ||
config = read_config() | ||
assert config is not None, "No config file found" | ||
|
||
process = subprocess.Popen( | ||
[ | ||
str(get_mariadb_daemon_path()), | ||
"--port", | ||
config["PORT"], | ||
], | ||
stderr = subprocess.PIPE, | ||
) | ||
|
||
atexit.register(process.kill) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import pathlib | ||
|
||
def get_root_path(): | ||
current_path = pathlib.Path(__file__) | ||
while current_path.name != 'tools': | ||
current_path = current_path.parent | ||
return current_path.parent | ||
|
||
def get_config_path(): | ||
return get_root_path() / 'config' / 'ezdb.txt' | ||
|
||
def get_db_path(): | ||
return get_root_path() / 'db' | ||
|
||
def get_data_path(): | ||
return get_db_path() / 'data' | ||
|
||
def get_mariadb_bin_path(): | ||
return get_db_path() / 'bin' | ||
|
||
def get_mariadb_client_path(): | ||
return get_mariadb_bin_path() / 'mariadb.exe' | ||
|
||
def get_mariadb_daemon_path(): | ||
return get_mariadb_bin_path() / 'mariadbd.exe' | ||
|
||
def get_mariadb_install_db_path(): | ||
return get_mariadb_bin_path() / 'mariadb-install-db.exe' | ||
|
||
def get_initial_schema_path(): | ||
return get_root_path() / 'SQL' / 'tgmc-schema.sql' | ||
|
||
def get_changelog_path(): | ||
return get_root_path() / 'SQL' / 'database_changelog.md' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from .download_mariadb import DownloadMariaDB | ||
from .install_database import InstallDatabase | ||
from .install_initial_schema import InstallInitialSchema | ||
from .update_schema import UpdateSchema | ||
|
||
STEPS = [ | ||
DownloadMariaDB, | ||
InstallDatabase, | ||
InstallInitialSchema, | ||
UpdateSchema, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import os | ||
import pathlib | ||
import tempfile | ||
import urllib.request | ||
import zipfile | ||
from ..ezdb.paths import get_config_path, get_data_path, get_db_path, get_mariadb_bin_path, get_mariadb_daemon_path, get_mariadb_install_db_path | ||
from .step import Step | ||
|
||
# Theoretically, this could use the REST API that MariaDB has to find the URL given a version: | ||
# https://downloads.mariadb.org/rest-api/mariadb/10.11 | ||
DOWNLOAD_URL = "http://downloads.mariadb.org/rest-api/mariadb/10.11.2/mariadb-10.11.2-winx64.zip" | ||
FOLDER_NAME = "mariadb-10.11.2-winx64" | ||
|
||
temp_extract_path = get_db_path() / "_temp/" | ||
|
||
class DownloadMariaDB(Step): | ||
@staticmethod | ||
def should_run() -> bool: | ||
return not get_mariadb_bin_path().exists() | ||
|
||
@staticmethod | ||
def run(args): | ||
if temp_extract_path.exists(): | ||
print("Deleting old temporary extract folder") | ||
temp_extract_path.rmdir() | ||
|
||
print("Downloading portable MariaDB...") | ||
|
||
# delete = False so we can write to it | ||
temporary_file = tempfile.NamedTemporaryFile(delete = False) | ||
|
||
try: | ||
urllib.request.urlretrieve(DOWNLOAD_URL, temporary_file.name) | ||
|
||
print("Extracting...") | ||
os.makedirs(temp_extract_path, exist_ok = True) | ||
with zipfile.ZipFile(temporary_file) as zip_file: | ||
for file in zip_file.namelist(): | ||
if file.startswith(f"{FOLDER_NAME}/bin/"): | ||
with zip_file.open(file) as source, open(temp_extract_path / pathlib.Path(file).name, "wb") as target: | ||
target.write(source.read()) | ||
|
||
print("Moving...") | ||
|
||
temp_extract_path.rename(get_mariadb_bin_path()) | ||
finally: | ||
temporary_file.close() | ||
|
||
if temp_extract_path.exists(): | ||
temp_extract_path.rmdir() |
Oops, something went wrong.