import logging import os from pathlib import Path import shutil import re import sys sys.path.append(os.path.dirname(__file__)) from common import exec_checked, exec_get_output, prompt, escape_filename, get_root, replace_in_file, run_script _invalid_file_char_regex = re.compile(r'[^a-zA-Z0-9_]') _variable_regex = re.compile(r'@([A-Z_]+)@') _logger = logging.getLogger(__name__) _root : Path def verify_tools() -> None: _logger.debug('Verifying all required tools are available...') success = True if shutil.which('git') is None: _logger.error('git not found in PATH') success = False if shutil.which('scons') is None: _logger.error('SCons not found in PATH') success = False if not success: raise RuntimeError('one or more required tools could not be found') def download_spp() -> None: _logger.debug('Checking if Scons++ is checked out...') output = exec_get_output(['git', 'submodule', 'status', 'external/scons-plus-plus']) if output[0] in ('+', ' '): return assert output[0] == '-' _logger.info('SCons++ not checkout out yet, doing it now.') exec_checked(['git', 'submodule', 'init']) exec_checked(['git', 'submodule', 'update', 'external/scons-plus-plus']) def update_spp() -> None: _logger.debug('Updating SCons++ submodule...') os.chdir(_root / 'external/scons-plus-plus') try: exec_checked(['git', 'fetch', 'origin', 'master']) exec_checked(['git', 'checkout', 'master']) output = exec_get_output(['git', 'status', '--porcelain']) if output.strip() == '': return finally: os.chdir(_root) _logger.info('Changes in SCons++ detected, creating commit.') exec_checked(['git', 'commit', '-m', 'Updated Scons++', 'external/scons-plus-plus']) def verify_unchanged() -> None: output = exec_get_output(['git', 'status', '--porcelain']) if output != '': raise RuntimeError('There are uncommitted changes. Commit, stash or revert them before running this script.') def setup_project() -> None: project_name = '' while project_name == '': print('Please enter a name for your project.') project_name = prompt().strip() module_name = project_name print(f'Please enter a name for the first module. Leave empty to use the project name ("{module_name}").') new_name = prompt().strip() if new_name != '': module_name = new_name module_folder_name = escape_filename(project_name.lower()) print(f'Please enter a folder name for the first module. Leave empty for "{module_folder_name}". Anything but [A-Za-z0-9_] will be replaced with underscores.') new_name = prompt().strip() if new_name != '': module_folder_name = escape_filename(new_name) # just enforce nice names module_exe_name = escape_filename(module_name.lower()) print(f'Please enter a file name for the module executable. Leave empty for "{module_exe_name}". Omit the file suffix. Anything but [A-Za-z0-9_] will be replaced with underscores.') new_name = prompt().strip() if new_name != '': module_exe_name = escape_filename(new_name) replace_in_file(_root / 'SConstruct', PROJECT_NAME=project_name, MODULE_FOLDER_NAME=module_folder_name) replace_in_file(_root / 'private/spp_template/SModule', MODULE_NAME=module_name, EXE_NAME=module_exe_name) template_folder = _root / 'private/spp_template' module_folder = _root / 'private' / module_folder_name _logger.debug(f'Moving {template_folder} to {module_folder}.') shutil.move(template_folder, module_folder) _logger.info('Creating a git commit for the setup.') exec_checked(['git', 'add', '.']) exec_checked(['git', 'commit', '-m', 'Project setup']) def setup_git_remote() -> None: current_url = exec_get_output(['git', 'remote', 'get-url', 'origin']) if 'spp_template' not in current_url: _logger.debug('Remote already set up.') return remote_url = '' while remote_url == '': print('Please enter a new URL for your git remote.') remote_url = prompt().strip() exec_checked(['git', 'remote', 'set-url', 'origin', remote_url]) def script_main(): global _root _root = get_root() verify_tools() download_spp() update_spp() verify_unchanged() setup_project() setup_git_remote() if __name__ == '__main__': run_script(script_main)