-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate_project_and_app_references.py
156 lines (131 loc) · 5.71 KB
/
update_project_and_app_references.py
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
"""
Purpose:
- Renames all project and app references from foo_project and foo_app to the desired project and app names.
Usage:
$ python ./update_project_and_app_references.py --target_dir "/path/to/foo_project/" --new_project_name "bar_project" --new_app_name "bar_app"
Note:
- This script will delete the git-cloned `.git` directory in the target directory, so you can start a new git repository.
"""
import argparse
import shutil
from pathlib import Path, PosixPath
## constants --------------------------------------------------------
REPO_PROJECT_NAME = 'django_template_42_project' # raw git-clone name
OLD_PROJECT_NAME = 'foo_project' # all the internal code project-references
OLD_APP_NAME = 'foo_app'
## helper functions -------------------------------------------------
def rename_top_level_directory(target_directory: Path, new_project_name: str) -> Path:
"""
Renames the top-level project directory if needed.
Called by run_updater().
"""
if REPO_PROJECT_NAME in target_directory.name:
new_directory: Path = target_directory.with_name(
target_directory.name.replace(REPO_PROJECT_NAME, new_project_name)
)
target_directory.rename(new_directory)
return_dir: Path = new_directory
else:
return_dir: Path = target_directory
return return_dir
def rename_files_and_directories(
target_directory: Path, new_project_name: str, new_app_name: str
) -> None:
"""
Renames any files and directories in the target directory.
Called by run_updater.
"""
for item in target_directory.rglob('*'):
assert type(item) is PosixPath
if item.is_dir():
if OLD_PROJECT_NAME in item.name:
new_dir_name: str = item.name.replace(OLD_PROJECT_NAME, new_project_name)
item.rename(item.with_name(new_dir_name))
elif OLD_APP_NAME in item.name:
new_dir_name: str = item.name.replace(OLD_APP_NAME, new_app_name)
item.rename(item.with_name(new_dir_name))
elif item.is_file():
if OLD_PROJECT_NAME in item.name:
new_file_name: str = item.name.replace(OLD_PROJECT_NAME, new_project_name)
item.rename(item.with_name(new_file_name))
elif OLD_APP_NAME in item.name:
new_file_name: str = item.name.replace(OLD_APP_NAME, new_app_name)
item.rename(item.with_name(new_file_name))
def update_file_contents(target_directory: Path, new_project_name: str, new_app_name: str) -> None:
for item in target_directory.rglob('*'):
assert type(item) is PosixPath
if item.is_file():
if item.name == 'update_project_and_app_references.py':
continue
replace_in_file(item, OLD_PROJECT_NAME, new_project_name)
replace_in_file(item, OLD_APP_NAME, new_app_name)
return
def replace_in_file(file_path: Path, old_text: str, new_text: str) -> None:
"""
Replaces old_text with new_text in the file at file_path.
Called by update_file_contents.
"""
try:
content = file_path.read_text(encoding='utf-8')
content = content.replace(old_text, new_text)
file_path.write_text(content, encoding='utf-8')
except UnicodeDecodeError:
pass # skip files that can't be read as UTF-8
return
def delete_git_directory(target_directory: Path) -> None:
"""
Deletes the .git directory in the target directory if it exists.
Called by run_updater.
"""
git_dir: Path = target_directory / '.git'
if git_dir.exists():
if git_dir.is_dir():
shutil.rmtree(git_dir)
print(f'Deleted .git directory in ``{target_directory}``.')
else:
print(f'No .git directory found at ``{git_dir}``.')
return
## manager functions ------------------------------------------------
def parse_args() -> None:
"""
Parses args and passes them to the main manager function.
Called by dundermain.
"""
## configure argument parser
parser = argparse.ArgumentParser(
description='Update project and app references in a directory.'
)
parser.add_argument('--target_dir', type=str, required=True, help='The directory to update.')
parser.add_argument('--new_project_name', type=str, required=True, help='The new project name.')
parser.add_argument('--new_app_name', type=str, required=True, help='The new app name.')
args = parser.parse_args()
## get the values
target_directory: Path = Path(args.target_dir)
new_project_name: str = args.new_project_name
new_app_name: str = args.new_app_name
## confirm target_directory exists
if not target_directory.exists():
raise FileNotFoundError(f'Target directory ``{target_directory}`` does not exist.')
## run updater
run_updater(target_directory, new_project_name, new_app_name)
return
def run_updater(target_directory: Path, new_project_name: str, new_app_name: str) -> None:
"""
Performs the update operations on the target directory.
Called by parse_args.
"""
## rename top-level directory if needed
target_directory = rename_top_level_directory(target_directory, new_project_name)
## first pass: rename files and directories
rename_files_and_directories(target_directory, new_project_name, new_app_name)
## second pass: update file contents
update_file_contents(target_directory, new_project_name, new_app_name)
## delete .git directory
delete_git_directory(target_directory)
print(
f'Updated project and app references in ``{target_directory}`` to ``{new_project_name}`` and ``{new_app_name}``.'
)
return
## dundermain -------------------------------------------------------
if __name__ == '__main__':
parse_args()