hotupdate_script.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # -*-coding:utf-8-*-
  2. #===============================================================================
  3. #@desc:热更资源打包工具
  4. #===============================================================================
  5. import os
  6. import difflib
  7. import hashlib
  8. import shutil
  9. import zipfile
  10. # 主渠道号
  11. G_UNION_ID = 166
  12. # 与底包c++层保持一致,原则上每个大类别的包(主包)此处都不一样
  13. G_ENCRYPT_KEY = "fyLua"
  14. G_ENCRYPT_SIGN = "sdy5cf0"
  15. # 热更版本号配置
  16. G_HALL_VERSION = {"818": 17}
  17. G_GAME_VERSION = {"001": 1, "824": 7, "901": 6, "902": 6, "903": 5, "904": 5, "905": 4,"906": 3,"907": 4,"908": 4,"909": 4,"910": 4,"911": 2,"912": 5,"913": 1}
  18. # 版本定义
  19. G_MIN_VERSION = 1
  20. G_DIFF_VERSION = 10
  21. # 目录定义
  22. G_ROOT_PATH = os.getcwd() + "\\..\\..\\"
  23. G_RUN_PATH = G_ROOT_PATH + "\\hotupdate_version"
  24. G_NEW_PATH = G_RUN_PATH + "\\new\\"
  25. G_RES_PATH = G_NEW_PATH + "\\res"
  26. G_SRC_PATH = G_NEW_PATH + "\\src"
  27. G_OUT_PATH = G_RUN_PATH + "\\out\\" + str(G_UNION_ID)
  28. # 新版本标记
  29. G_NEW_VERSION = {}
  30. # --------------------公共方法--------------------
  31. # 创建文件夹
  32. def create_dir(dir_name, delete = True):
  33. if os.path.exists(os.path.dirname(dir_name)):
  34. if delete:
  35. shutil.rmtree(dir_name)
  36. os.makedirs(dir_name)
  37. else:
  38. os.makedirs(dir_name)
  39. # 拷贝文件夹
  40. def copy_files(src_path, dst_path):
  41. if not os.path.exists(src_path):
  42. return
  43. if not os.path.exists(dst_path):
  44. os.makedirs(dst_path)
  45. if os.path.exists(src_path):
  46. shutil.rmtree(dst_path)
  47. #print('copy ' + src_path + " to " + dst_path)
  48. shutil.copytree(src_path, dst_path)
  49. # 生成zip包
  50. def zip_file(dir_path, zip_name):
  51. zip = zipfile.ZipFile(dir_path + zip_name, "w", zipfile.ZIP_DEFLATED)
  52. for path, dir_names, file_names in os.walk(dir_path):
  53. # 去掉目标跟路径,只对目标文件夹下边的文件及文件夹进行压缩
  54. fpath = path.replace(dir_path, '')
  55. #print("path >>> " + path)
  56. for file_name in file_names:
  57. if file_name == zip_name:
  58. continue
  59. zip.write(os.path.join(path, file_name), os.path.join(fpath, file_name))
  60. zip.close()
  61. # 文件md5
  62. def hash_md5(file_name):
  63. if not os.path.isfile(file_name):
  64. print('**file not exist: ' + file_name)
  65. return
  66. hash_obj = hashlib.md5()
  67. f = open(file_name, 'rb')
  68. while True:
  69. b = f.read(8096)
  70. if not b :
  71. break
  72. hash_obj.update(b)
  73. f.close()
  74. return hash_obj.hexdigest()
  75. # 获取文件列表
  76. def get_file_list(path):
  77. file_list = []
  78. for root, dirs, fs in os.walk(path):
  79. for f in fs:
  80. f_fullpath = os.path.join(root, f)
  81. f_relativepath = f_fullpath[len(path):]
  82. file_list.append(f_relativepath)
  83. return file_list
  84. #
  85. def get_diff_list(src_path, dst_path):
  86. src_file_list = get_file_list(src_path)
  87. dst_file_list = get_file_list(dst_path)
  88. set_src = set(src_file_list)
  89. set_dst = set(dst_file_list)
  90. set_comm = set_src & set_dst
  91. set_new = set_dst - set_src
  92. diff_file_list = []
  93. for tmp_file in sorted(set_comm):
  94. src_md5 = hash_md5(src_path + "\\" + tmp_file)
  95. dst_md5 = hash_md5(dst_path + "\\" + tmp_file)
  96. if src_md5 != dst_md5:
  97. print('>>diff file: ' + tmp_file)
  98. diff_file_list.append(tmp_file)
  99. for tmp_file in sorted(set_new):
  100. print('>>new file: ' + tmp_file)
  101. diff_file_list.append(tmp_file)
  102. return diff_file_list
  103. # --------------------公共方法--------------------
  104. # 拷贝资源文件
  105. def copy_resources():
  106. create_dir(G_NEW_PATH)
  107. copy_files(G_ROOT_PATH + "\\res", G_RES_PATH)
  108. copy_files(G_ROOT_PATH + "\\src", G_SRC_PATH)
  109. # 删除基础部分vscode配置文件
  110. shutil.rmtree(G_SRC_PATH + "\\.vscode")
  111. # 模块编译
  112. def compile_resources():
  113. # 编译lua文件
  114. cocos_compile_cmd = "cocos luacompile -s " + G_SRC_PATH + " -d " + G_SRC_PATH + " --disable-compile" + " -e -k " + G_ENCRYPT_KEY + " -b " + G_ENCRYPT_SIGN
  115. os.system(cocos_compile_cmd)
  116. # 删除lua文件
  117. for fold_name, sub_folders, file_names in os.walk(G_SRC_PATH):
  118. for file_name in file_names:
  119. if file_name.endswith('.lua'):
  120. os.remove(os.path.join(fold_name, file_name))
  121. # 处理res资源
  122. print(">>skip compile res...")
  123. # 添加版本文件
  124. def add_version_file(path, version):
  125. version_file = path + "\\version.json"
  126. print(">>add version file:" + version_file)
  127. with open(version_file,'w')as file:
  128. file.write("{\"version\":" + str(version) + "}")
  129. # 提取大厅资源
  130. def split_hall_resources():
  131. print(">>split hall resources...")
  132. for key in G_HALL_VERSION:
  133. hall_version = G_HALL_VERSION[key]
  134. print(">>dealing " + key + " version = " + str(hall_version))
  135. new_path = G_RUN_PATH + "\\" + key + "\\" + str(hall_version)
  136. if os.path.exists(new_path):
  137. continue
  138. os.makedirs(new_path)
  139. G_NEW_VERSION[key] = hall_version
  140. new_res_path = new_path + "\\res"
  141. new_src_path = new_path + "\\src"
  142. copy_files(G_RES_PATH, new_res_path)
  143. copy_files(G_SRC_PATH, new_src_path)
  144. add_version_file(new_res_path + "\\game_overseas", hall_version)
  145. # 删除游戏资源
  146. shutil.rmtree(new_res_path + "\\game_overseas\games")
  147. game_src_path = new_src_path + "\\app\games"
  148. for filename in os.listdir(game_src_path):
  149. if filename.startswith("game") and os.path.isdir(game_src_path + "\\" + filename):
  150. shutil.rmtree(game_src_path + "\\" + filename)
  151. print(">>split hall resources finish...")
  152. # 提取游戏资源
  153. def split_game_resources():
  154. print(">>split game resources...")
  155. for key in G_GAME_VERSION:
  156. game_version = G_GAME_VERSION[key]
  157. print(">>dealing " + key + " version = " + str(game_version))
  158. new_path = G_RUN_PATH + "\\" + key + "\\" + str(game_version)
  159. if os.path.exists(new_path):
  160. continue
  161. os.makedirs(new_path)
  162. G_NEW_VERSION[key] = game_version
  163. res_path_suffix = "\\game_overseas\games\game" + key
  164. src_path_suffix = "\\app\games\game" + key
  165. from_res_path = G_RES_PATH + res_path_suffix
  166. from_src_path = G_SRC_PATH + src_path_suffix
  167. to_res_path = new_path + "\\res\\" + res_path_suffix
  168. to_src_path = new_path + "\\src\\" + src_path_suffix
  169. copy_files(from_res_path, to_res_path)
  170. copy_files(from_src_path, to_src_path)
  171. add_version_file(to_res_path, game_version)
  172. print(">>split game resources finish...")
  173. # 提取资源
  174. def split_resources():
  175. split_hall_resources()
  176. split_game_resources()
  177. # 生成更新整包
  178. def gen_full_zip():
  179. print(">>generate full zips start...")
  180. for key in G_NEW_VERSION:
  181. str_version = str(G_NEW_VERSION[key])
  182. zip_path = G_RUN_PATH + "\\" + key + "\\" + str_version + "\\"
  183. zip_name = key + "_" + str_version + ".zip"
  184. print(">>zipping " + zip_name)
  185. zip_file(zip_path, zip_name)
  186. print(">>moving " + zip_name)
  187. src_zip = zip_path + zip_name
  188. dst_path = G_OUT_PATH + "\\full\\" + key + "\\"
  189. create_dir(dst_path)
  190. shutil.move(src_zip, dst_path)
  191. print(">>finish " + zip_name)
  192. print(">>generate full zips finish...")
  193. # 生成更新差分包
  194. def gen_diff_zip():
  195. print(">>generate diff zips start...")
  196. for key in G_NEW_VERSION:
  197. zip_path = G_OUT_PATH + "\\diff\\" + key + "\\"
  198. create_dir(zip_path)
  199. cur_version = G_NEW_VERSION[key]
  200. min_version = max(G_MIN_VERSION, cur_version - G_DIFF_VERSION)
  201. for tmp_version in range(min_version, cur_version):
  202. print(">>generate diff " + key + " " + str(tmp_version) + " -> " + str(cur_version))
  203. pre_path = G_RUN_PATH + "\\" + key + "\\" + str(tmp_version) + "\\"
  204. cur_path = G_RUN_PATH + "\\" + key + "\\" + str(cur_version) + "\\"
  205. tmp_path = G_RUN_PATH + "\\" + key + "\\" + str(tmp_version) + "_" + str(cur_version) + "\\"
  206. if not os.path.exists(pre_path):
  207. print(">>generate diff " + key + " no version " + str(tmp_version))
  208. continue
  209. create_dir(tmp_path)
  210. diff_list = get_diff_list(pre_path, cur_path)
  211. for diff_file in diff_list:
  212. dst_path = os.path.dirname(tmp_path + diff_file)
  213. if not os.path.exists(dst_path):
  214. os.makedirs(dst_path)
  215. shutil.copy(cur_path + diff_file, dst_path)
  216. zip_name = key + "_" + str(tmp_version) + "_" + str(cur_version) + ".zip"
  217. print(">>zipping " + zip_name)
  218. zip_file(tmp_path, zip_name)
  219. print(">>moving " + zip_name)
  220. src_zip = tmp_path + zip_name
  221. shutil.move(src_zip, zip_path)
  222. print(">>finish " + zip_name)
  223. shutil.rmtree(tmp_path)
  224. print(">>generate diff zips finish...")
  225. def gen_zip():
  226. print(">>find new version:")
  227. for key in G_NEW_VERSION:
  228. print(">>" + key + " => " + str(G_NEW_VERSION[key]))
  229. create_dir(G_OUT_PATH)
  230. gen_full_zip()
  231. gen_diff_zip()
  232. def start():
  233. copy_resources()
  234. compile_resources()
  235. split_resources()
  236. gen_zip()
  237. if __name__ == '__main__':
  238. print(">>hotupdate zip start...")
  239. start()
  240. print(">>hotupdate zip finish...")