#!/usr/bin/env python3 import argparse import os import re import subprocess SCHEMA_PATH = "SignalServiceKit/Resources/schema.sql" TABLES_TO_IGNORE = [ "grdb_migrations", "sqlite_sequence", "indexable_text_fts_data", "indexable_text_fts_idx", "indexable_text_fts_docsize", "indexable_text_fts_config", "SearchableNameFTS_data", "SearchableNameFTS_idx", "SearchableNameFTS_docsize", "SearchableNameFTS_config", ] def main(ns): repo_root = os.path.abspath(os.path.join(__file__, "../..")) args = ["Scripts/sqlclient", "--quiet"] if ns.staging: args.extend(["--staging"]) if ns.path is not None: args.extend(["--path", ns.path]) if ns.passphrase is not None: args.extend(["--passphrase", ns.passphrase]) args.extend(["--", ".schema"]) schema = subprocess.run( args, check=True, encoding="utf8", capture_output=True, cwd=repo_root, ).stdout # Drop the "ok" from setting the passphrase. assert schema.startswith("ok\n") schema = schema[3:] # Normalize the formatting. schema = subprocess.run( ["bundle", "exec", "anbt-sql-formatter"], check=True, input=schema, encoding="utf8", capture_output=True, ).stdout # Remove tables that don't need to be included. (Generally, some other # mechanism creates these so that we don't need to.) for table in TABLES_TO_IGNORE: schema = re.sub( r"CREATE\s+TABLE\s+(IF NOT EXISTS\s+)?'?" + table + r".*?;\n\n", "", schema, flags=re.MULTILINE | re.DOTALL, ) file_path = os.path.join(repo_root, SCHEMA_PATH) with open(file_path, "r") as file: old_schema = file.read() if schema == old_schema: return with open(file_path, "w") as file: file.write(schema) def parse_args(): parser = argparse.ArgumentParser() target = parser.add_mutually_exclusive_group() target.add_argument( "--staging", action="store_true", help="Target the staging database of the currently-booted simulator.", ) target.add_argument( "--path", metavar="/a/b/c", help="Target the database at the provided path.", ) parser.add_argument( "--passphrase", metavar="abcdef0123456789", help="Use the provided passphrase to decrypt the database. " "(Or you can use “Settings” -> “Internal” -> “Misc” -> “Save plaintext database key”.)", ) return parser.parse_args() if __name__ == "__main__": ns = parse_args() main(ns)