| 
 | 1 | +import glob  | 
 | 2 | +from typing import NamedTuple  | 
 | 3 | +import pathlib  | 
 | 4 | +import shutil  | 
 | 5 | + | 
 | 6 | +SCRIPT_BASE_PATH = pathlib.Path(__file__).parent  | 
 | 7 | +SCRIPT_TEMPLATE_PATH = SCRIPT_BASE_PATH / 'template' / 'whitelabel'  | 
 | 8 | +ETH_BASE_PATH = SCRIPT_BASE_PATH.parent.parent / 'eth'  | 
 | 9 | +FORKS_BASE_PATH = ETH_BASE_PATH / 'vm' / 'forks'  | 
 | 10 | + | 
 | 11 | +INPUT_PROMPT = '-->'  | 
 | 12 | +YES = 'y'  | 
 | 13 | + | 
 | 14 | +# Given a fork name of Muir Glacier we need to derive:  | 
 | 15 | +# pascal case: MuirGlacier  | 
 | 16 | +# lower_dash_case: muir-glacier  | 
 | 17 | +# lower_snake_case: muir_glacier  | 
 | 18 | +# upper_snake_case: MUIR_GLACIER  | 
 | 19 | + | 
 | 20 | + | 
 | 21 | +class Writing(NamedTuple):  | 
 | 22 | +    pascal_case: str  | 
 | 23 | +    lower_dash_case: str  | 
 | 24 | +    lower_snake_case: str  | 
 | 25 | +    upper_snake_case: str  | 
 | 26 | + | 
 | 27 | + | 
 | 28 | +WHITELABEL_FORK = Writing(  | 
 | 29 | +    pascal_case="Istanbul",  | 
 | 30 | +    lower_dash_case="istanbul",  | 
 | 31 | +    lower_snake_case="istanbul",  | 
 | 32 | +    upper_snake_case="ISTANBUL",  | 
 | 33 | +)  | 
 | 34 | + | 
 | 35 | +WHITELABEL_PARENT = Writing(  | 
 | 36 | +    pascal_case="Petersburg",  | 
 | 37 | +    lower_dash_case="petersburg",  | 
 | 38 | +    lower_snake_case="petersburg",  | 
 | 39 | +    upper_snake_case="PETERSBURG",  | 
 | 40 | +)  | 
 | 41 | + | 
 | 42 | + | 
 | 43 | +def bootstrap() -> None:  | 
 | 44 | +    print("Specify the name of the fork (e.g Muir Glacier):")  | 
 | 45 | +    fork_name = input(INPUT_PROMPT)  | 
 | 46 | + | 
 | 47 | +    if not all(x.isalpha() or x.isspace() for x in fork_name):  | 
 | 48 | +        print(f"Can't use {fork_name} as fork name, must be alphabetical")  | 
 | 49 | +        return  | 
 | 50 | + | 
 | 51 | +    print("Specify the fork base (e.g Istanbul):")  | 
 | 52 | +    fork_base = input(INPUT_PROMPT)  | 
 | 53 | + | 
 | 54 | +    fork_base_path = FORKS_BASE_PATH / fork_base  | 
 | 55 | +    if not fork_base_path.exists():  | 
 | 56 | +        print(f"No fork exists at {fork_base_path}")  | 
 | 57 | +        return  | 
 | 58 | + | 
 | 59 | +    writing_new_fork = create_writing(fork_name)  | 
 | 60 | +    writing_parent_fork = create_writing(fork_base)  | 
 | 61 | + | 
 | 62 | +    print("Check your inputs:")  | 
 | 63 | +    print("New fork:")  | 
 | 64 | +    print(writing_new_fork)  | 
 | 65 | + | 
 | 66 | +    print("Base fork:")  | 
 | 67 | +    print(writing_parent_fork)  | 
 | 68 | + | 
 | 69 | +    print("Proceed (y/n)?")  | 
 | 70 | +    proceed = input(INPUT_PROMPT)  | 
 | 71 | + | 
 | 72 | +    if proceed.lower() == YES:  | 
 | 73 | +        create_fork(writing_new_fork, writing_parent_fork)  | 
 | 74 | +        print("Your fork is ready!")  | 
 | 75 | + | 
 | 76 | + | 
 | 77 | +def create_writing(fork_name: str):  | 
 | 78 | +    # Remove extra spaces  | 
 | 79 | +    normalized = " ".join(fork_name.split())  | 
 | 80 | + | 
 | 81 | +    snake_case = normalized.replace(' ', '_')  | 
 | 82 | +    dash_case = normalized.replace(' ', '-')  | 
 | 83 | +    pascal_case = normalized.title().replace(' ', '')  | 
 | 84 | + | 
 | 85 | +    return Writing(  | 
 | 86 | +        pascal_case=pascal_case,  | 
 | 87 | +        lower_dash_case=dash_case.lower(),  | 
 | 88 | +        lower_snake_case=snake_case.lower(),  | 
 | 89 | +        upper_snake_case=snake_case.upper(),  | 
 | 90 | +    )  | 
 | 91 | + | 
 | 92 | + | 
 | 93 | +def create_fork(writing_new_fork: Writing, writing_parent_fork: Writing) -> None:  | 
 | 94 | +    fork_path = FORKS_BASE_PATH / writing_new_fork.lower_snake_case  | 
 | 95 | +    shutil.copytree(SCRIPT_TEMPLATE_PATH, fork_path)  | 
 | 96 | +    replace_in(fork_path, WHITELABEL_FORK.pascal_case, writing_new_fork.pascal_case)  | 
 | 97 | +    replace_in(fork_path, WHITELABEL_FORK.lower_snake_case, writing_new_fork.lower_snake_case)  | 
 | 98 | +    replace_in(fork_path, WHITELABEL_FORK.lower_dash_case, writing_new_fork.lower_dash_case)  | 
 | 99 | +    replace_in(fork_path, WHITELABEL_FORK.upper_snake_case, writing_new_fork.upper_snake_case)  | 
 | 100 | + | 
 | 101 | +    replace_in(fork_path, WHITELABEL_PARENT.pascal_case, writing_parent_fork.pascal_case)  | 
 | 102 | +    replace_in(fork_path, WHITELABEL_PARENT.lower_snake_case, writing_parent_fork.lower_snake_case)  | 
 | 103 | +    replace_in(fork_path, WHITELABEL_PARENT.lower_dash_case, writing_parent_fork.lower_dash_case)  | 
 | 104 | +    replace_in(fork_path, WHITELABEL_PARENT.upper_snake_case, writing_parent_fork.upper_snake_case)  | 
 | 105 | + | 
 | 106 | + | 
 | 107 | +def replace_in(base_path: pathlib.Path, find_text: str, replace_txt: str) -> None:  | 
 | 108 | +    for filepath in glob.iglob(f'{base_path}/**/*.py', recursive=True):  | 
 | 109 | +        with open(filepath) as file:  | 
 | 110 | +            s = file.read()  | 
 | 111 | +        s = s.replace(find_text, replace_txt)  | 
 | 112 | +        with open(filepath, "w") as file:  | 
 | 113 | +            file.write(s)  | 
 | 114 | + | 
 | 115 | + | 
 | 116 | +if __name__ == '__main__':  | 
 | 117 | +    bootstrap()  | 
0 commit comments