Skip to content

Commit 84af7a5

Browse files
authored
TEST
1 parent b653c99 commit 84af7a5

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

create-app.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/usr/bin/env python
2+
# coding:utf-8
3+
4+
import sys
5+
import os
6+
import io
7+
import zipfile
8+
import requests
9+
import re
10+
11+
12+
REPO_URL = 'https://github.com/Monzonprog/MiniTwitter'
13+
ORIGINAL_PACKAGE_NAME = 'com.jmonzon.minitwitter'
14+
ZIP_UNIX_SYSTEM = 3
15+
16+
17+
class ProjectCreator:
18+
def __init__(self, archive_data: bytes, project_name: str, package_name: str):
19+
self.zip_file = zipfile.ZipFile(io.BytesIO(archive_data), 'r')
20+
self.project_name = project_name
21+
self.package_name = package_name
22+
self.root_dir_path = None
23+
24+
def create(self):
25+
infolist: [zipfile.ZipInfo] = self.zip_file.infolist()
26+
self.root_dir_path = infolist[0].filename
27+
28+
for info in infolist:
29+
if info.filename.endswith('/'):
30+
# skip directory
31+
continue
32+
33+
last_segment = info.filename.split('/')[-1]
34+
if last_segment.endswith('.kt'):
35+
self.kt_file(info)
36+
37+
elif last_segment.endswith('.gradle.kts'):
38+
self.gradle_file(info)
39+
40+
elif last_segment.endswith('.xml'):
41+
self.xml_file(info)
42+
43+
elif last_segment.endswith('.py') or last_segment == 'README.md':
44+
continue
45+
46+
else:
47+
self.common_file(info)
48+
49+
def kt_file(self, info: zipfile.ZipInfo):
50+
file_name = self.replace_root_path(info.filename)
51+
file_name = file_name.replace(
52+
ORIGINAL_PACKAGE_NAME.replace('.', '/'),
53+
self.package_name.replace('.', '/'))
54+
content = TextProcessor(self.zip_file.read(info.filename).decode('utf-8'))\
55+
.replace_all_text(ORIGINAL_PACKAGE_NAME, self.package_name)\
56+
.remove_unwanted_comments().commit().encode()
57+
58+
self.write_to_file(file_name, content, info)
59+
60+
def gradle_file(self, info: zipfile.ZipInfo):
61+
self.replaceable_file(info)
62+
63+
def xml_file(self, info: zipfile.ZipInfo):
64+
self.replaceable_file(info)
65+
66+
def replaceable_file(self, info: zipfile.ZipInfo):
67+
file_name = self.replace_root_path(info.filename)
68+
content = TextProcessor(self.zip_file.read(info.filename).decode('utf-8')) \
69+
.replace_all_text(ORIGINAL_PACKAGE_NAME, self.package_name) \
70+
.commit().encode()
71+
72+
self.write_to_file(file_name, content, info)
73+
74+
def common_file(self, info: zipfile.ZipInfo):
75+
file_name = self.replace_root_path(info.filename)
76+
content = self.zip_file.read(info.filename)
77+
78+
self.write_to_file(file_name, content, info)
79+
80+
def replace_root_path(self, file_name: str) -> str:
81+
return file_name.replace(self.root_dir_path, self.project_name + '/')
82+
83+
@staticmethod
84+
def write_to_file(file_name: str, content: bytes, info: zipfile.ZipInfo):
85+
os.makedirs(os.path.dirname(file_name), exist_ok=True)
86+
open(file_name, 'wb').write(content)
87+
if info.create_system == ZIP_UNIX_SYSTEM:
88+
unix_attributes = info.external_attr >> 16
89+
if unix_attributes:
90+
os.chmod(file_name, unix_attributes)
91+
92+
93+
class TextProcessor:
94+
def __init__(self, txt: str):
95+
self.txt = txt
96+
self.commands = []
97+
98+
def replace_all_text(self, src: str, dst: str) -> 'TextProcessor':
99+
self.commands.append(('replace_all_text', src, dst))
100+
return self
101+
102+
def remove_unwanted_comments(self) -> 'TextProcessor':
103+
self.commands.append(('remove_unwanted_comments', None))
104+
return self
105+
106+
def commit(self) -> str:
107+
rlt = ''
108+
for line in self.txt.splitlines():
109+
skip_line = False
110+
111+
for cmd in self.commands:
112+
if cmd[0] == 'replace_all_text':
113+
line = line.replace(cmd[1], cmd[2])
114+
115+
elif cmd[0] == 'remove_unwanted_comments' and (
116+
line.startswith('/*') or
117+
line.startswith(' *') or
118+
line.startswith(' */')):
119+
skip_line = True
120+
121+
if not skip_line:
122+
if not (len(rlt) == 0 and len(line) == 0):
123+
rlt += line + '\n'
124+
125+
return rlt
126+
127+
128+
def fetch_latest_archive() -> bytes:
129+
r = requests.get(REPO_URL + '/releases/latest', allow_redirects=False)
130+
latest_tag = r.headers['location'].split('/')[-1]
131+
archive_url = REPO_URL + '/archive/%s.zip' % latest_tag
132+
return requests.get(archive_url).content
133+
134+
135+
def main():
136+
def green(txt: str) -> str:
137+
return '\33[32m' + txt + '\33[0m'
138+
139+
def red(txt: str) -> str:
140+
return '\33[31m' + txt + '\33[0m'
141+
142+
if not (len(sys.argv) == 3):
143+
print('Usage: python3 create-android-kotlin-app.py ' +
144+
green('<PROJECT_NAME> <APP_PACKAGE_NAME>'))
145+
return
146+
147+
project_name = sys.argv[1]
148+
if os.path.exists(project_name):
149+
print(red('Error: ') + 'Can not create project. ' +
150+
'There is already a directory named %s in the current path.' % green(project_name))
151+
return
152+
try:
153+
os.mkdir(project_name)
154+
except:
155+
print(red('Error: ') + 'Can not create directory %s' % green(project_name))
156+
return
157+
158+
package_name = sys.argv[2]
159+
if not re.match('^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+[0-9a-z_]$', package_name):
160+
print(red('Error: ') + 'Invalid java package name %s' % green(package_name))
161+
return
162+
163+
print('Creating a new android kotlin app in %s\n' % green("./" + project_name))
164+
print('Fetching the latest source code archive from %s\nThis might take a couple minutes.' % green(REPO_URL))
165+
archive_data = fetch_latest_archive()
166+
167+
print('Unzipping template files...\n')
168+
ProjectCreator(archive_data, project_name, package_name).create()
169+
print('Done. Happy hacking!')
170+
171+
172+
if __name__ == '__main__':
173+
main()
174+

0 commit comments

Comments
 (0)