21 changed files with 414 additions and 0 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@ |
|||||
|
cd . |
||||
|
python main.py |
||||
|
pause |
@ -0,0 +1 @@ |
|||||
|
{"10001": "1.0.0"} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,14 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"platform":"android", |
||||
|
"version":"1.0.0", |
||||
|
"buildDir":"build\\{#}\\data\\assets\\", |
||||
|
"filters":["frame","internal","main"], |
||||
|
"only":["10001"], |
||||
|
"fileName":"assets", |
||||
|
"disName":"game_hot", |
||||
|
"suffix":"zip", |
||||
|
"maxFileSize":2.5, |
||||
|
"pkgName":"game" |
||||
|
} |
||||
|
] |
@ -0,0 +1,60 @@ |
|||||
|
import hashlib |
||||
|
import json |
||||
|
import os |
||||
|
|
||||
|
#获取目录下的全部文件列表 |
||||
|
def get_all_filenames(parentPath,folder_path,isRootPath): |
||||
|
filenames = [] |
||||
|
contents = os.listdir(folder_path) |
||||
|
for content in contents: |
||||
|
path = os.path.join(folder_path, content) |
||||
|
if isRootPath == True: |
||||
|
path=path.replace("/","\\") |
||||
|
filenames.append(path) |
||||
|
else: |
||||
|
if os.path.isfile(path): |
||||
|
filePath=os.path.join(folder_path,content) |
||||
|
filePath=filePath.replace(parentPath+"\\","") |
||||
|
filePath=filePath.replace("/","\\") |
||||
|
filenames.append(filePath) |
||||
|
else: |
||||
|
subfolder_filenames = get_all_filenames(parentPath,path,isRootPath) |
||||
|
filenames.extend(subfolder_filenames) |
||||
|
return filenames |
||||
|
|
||||
|
#验证某个文件路径是否在文件list列表中 |
||||
|
def hasInList(fn,list): |
||||
|
for f in list: |
||||
|
if f in fn: |
||||
|
return True |
||||
|
return False |
||||
|
|
||||
|
#获取某个文件的MD5码 |
||||
|
def getHas(filePath): |
||||
|
pathArr = filePath.split(".") |
||||
|
if len(pathArr) > 2 and pathArr[2] != "json": |
||||
|
return pathArr[2] |
||||
|
return None |
||||
|
|
||||
|
# 根据路径创建一个md5字符串 |
||||
|
def create_md5(input_str): |
||||
|
md5 = hashlib.md5() # 创建一个md5对象 |
||||
|
md5.update(input_str.encode('utf-8')) # 使用utf-8编码 |
||||
|
return md5.hexdigest() # 返回十六进制的哈希值 |
||||
|
|
||||
|
#检查文件路径是否存在,如果不存在就创建一个目录 |
||||
|
def existsDir(path): |
||||
|
if not os.path.exists(path): |
||||
|
os.makedirs(path, exist_ok=True) |
||||
|
# 读取json文件 |
||||
|
def readJson(path): |
||||
|
if os.path.exists(path): |
||||
|
f=open(path,encoding="utf-8") |
||||
|
jsonobj = json.load(f) |
||||
|
f.close(); |
||||
|
return jsonobj |
||||
|
# 写json数据到本地 |
||||
|
def writeJson(path,content): |
||||
|
f=open(path,"w") |
||||
|
json.dump(content,f) |
||||
|
f.close() |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
|||||
|
{"gameId": "10001", "version": "1a47b", "list": ["10001.1", "10001.2", "10001.3", "10001.4", "10001.5"]} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
|||||
|
{"gameId": "10001", "version": "1a47b", "list": ["10001.1", "10001.2", "10001.3", "10001.4", "10001.5"]} |
@ -0,0 +1,297 @@ |
|||||
|
import json |
||||
|
import os |
||||
|
import zipfile |
||||
|
import fileTools |
||||
|
from zipTools import create_split_zip |
||||
|
|
||||
|
#加载配置 |
||||
|
config = fileTools.readJson("config.json") |
||||
|
#本地文件缓存 |
||||
|
local_version_list=[] |
||||
|
|
||||
|
def getPathItem(path,list): |
||||
|
if len(list) <= 0:return None |
||||
|
for file in list: |
||||
|
if file["path"] == path: |
||||
|
return file |
||||
|
return None |
||||
|
#文件是否别改变 |
||||
|
def isChanged(file): |
||||
|
path=targetDir+file["path"] |
||||
|
current_time = os.stat(path).st_mtime |
||||
|
return current_time > float(file["st"]) |
||||
|
#获取版本 |
||||
|
def getVer(ver): |
||||
|
verArr = ver.split(".") |
||||
|
index=len(verArr) -1 |
||||
|
verArr[index]=int(verArr[index]) + 1 |
||||
|
if verArr[index] >= 100 : |
||||
|
verArr[index]=0; |
||||
|
verArr[index-1]=int(verArr[index-1])+1 |
||||
|
if verArr[index-1] >= 100 : |
||||
|
verArr[index-1]=0; |
||||
|
verArr[index-2]=int(verArr[index-2])+1 |
||||
|
return f'{verArr[0]}.{verArr[1]}.{verArr[2]}' |
||||
|
|
||||
|
def getVerCode(ver): |
||||
|
verArr = ver.split(".") |
||||
|
count=0 |
||||
|
for i in range(0,len(verArr)): |
||||
|
count +=int(verArr[i]) |
||||
|
return count |
||||
|
|
||||
|
#处理配置对象 |
||||
|
def handleConfigObject(obj,dirpath): |
||||
|
cachePath=currentPath+"\\cache_files\\";#缓存当前版本变化量 |
||||
|
fileTools.existsDir(cachePath) |
||||
|
local_ver_path=cachePath+"files.json" |
||||
|
local_version={} |
||||
|
local_version["list"]=[] |
||||
|
local_version["version"]=obj["version"] |
||||
|
#加载本地版本缓存 |
||||
|
if os.path.exists(local_ver_path): |
||||
|
local_version = fileTools.readJson(local_ver_path) |
||||
|
else: |
||||
|
fileTools.writeJson(local_ver_path,local_version["list"]) |
||||
|
files = fileTools.get_all_filenames(dirpath,dirpath,False) |
||||
|
filters = obj["filters"] |
||||
|
versionList=[] |
||||
|
base_ver_list=[] |
||||
|
fversion=local_version["version"] |
||||
|
for file_path in files: |
||||
|
if not fileTools.hasInList(file_path,filters): |
||||
|
md5 = fileTools.getHas(file_path) |
||||
|
cur_file_path = file_path.replace(dirpath, "") |
||||
|
if md5 == None: |
||||
|
md5 = fileTools.create_md5(cur_file_path) |
||||
|
file_item=getPathItem(cur_file_path,local_version["list"]) |
||||
|
fileArr=cur_file_path.split("\\") |
||||
|
newFileObj={} |
||||
|
newFileObj["bundleName"]= fileArr[0] |
||||
|
newFileObj["path"]=cur_file_path |
||||
|
newFileObj["st"]=os.stat(file_path).st_mtime |
||||
|
base_ver_list.append(newFileObj) |
||||
|
def addObj(ver): |
||||
|
if file_item!= None: |
||||
|
file_item["st"]=os.stat(file_path).st_mtime |
||||
|
if ver == local_version["version"]: |
||||
|
ver=getVer(local_version["version"]) |
||||
|
local_version["version"]=ver |
||||
|
else: |
||||
|
local_version["list"].append(newFileObj) |
||||
|
#版本路径数据 |
||||
|
versionList.append(newFileObj) |
||||
|
if file_item == None or isChanged(file_item): |
||||
|
if len(obj["only"]) > 0: |
||||
|
if fileTools.hasInList(fileArr[0],obj["only"]): |
||||
|
addObj(fversion) |
||||
|
else: |
||||
|
addObj(fversion) |
||||
|
if len(versionList) <= 0 : |
||||
|
print("=======================暂无热更资源发布================================") |
||||
|
return |
||||
|
print("=======================开始发布资源================================") |
||||
|
verConfigPath=cur_version_path+local_version["version"] |
||||
|
zipFileHotPathDir=verConfigPath+"\\hot\\assets\\" |
||||
|
fileTools.existsDir(zipFileHotPathDir) |
||||
|
zipFileHotPath=zipFileHotPathDir+"\\"+obj["fileName"]+"."+obj["suffix"] |
||||
|
if os.path.exists(zipFileHotPath): |
||||
|
os.remove(zipFileHotPath) |
||||
|
zf = zipfile.ZipFile(zipFileHotPath, "w", zipfile.zlib.DEFLATED) |
||||
|
for tar in versionList: |
||||
|
print("bundleName-> "+tar["bundleName"]+"\t\t开始写入文件 --- > "+tar["path"]) |
||||
|
fullpath=targetDir+"\\"+tar["path"] |
||||
|
zf.write(fullpath,tar["path"]) |
||||
|
zf.close() |
||||
|
print("=======================开始对资源进行分包处理================================") |
||||
|
print(f'当前资源版本 -> {local_version["version"]}') |
||||
|
list = create_split_zip(zipFileHotPath,zipFileHotPathDir,1000 * 1000 * obj["maxFileSize"],obj["suffix"]) |
||||
|
new_config_list=[] |
||||
|
for fi in list: |
||||
|
newob={} |
||||
|
newob["name"]=obj["pkgName"] |
||||
|
newob["resName"]=fi |
||||
|
#newob["version"]=local_version["version"] |
||||
|
new_config_list.append(newob) |
||||
|
configPath=zipFileHotPathDir[:zipFileHotPathDir.find("\\assets")]+"\\config.json" |
||||
|
fileTools.writeJson(configPath,new_config_list) |
||||
|
#删除原有包 |
||||
|
if os.path.exists(zipFileHotPath): |
||||
|
os.remove(zipFileHotPath) |
||||
|
print("-------------------------分包完成-----------------------------------------") |
||||
|
zipFileBasePathDir=verConfigPath+"\\base\\assets\\" |
||||
|
fileTools.existsDir(zipFileBasePathDir) |
||||
|
zipFileBasePath=zipFileBasePathDir+"\\"+obj["fileName"]+"."+obj["suffix"] |
||||
|
if os.path.exists(zipFileBasePath): |
||||
|
os.remove(zipFileBasePath) |
||||
|
zf = zipfile.ZipFile(zipFileBasePath, "w", zipfile.zlib.DEFLATED) |
||||
|
for tar in base_ver_list: |
||||
|
print("bundleName-> "+tar["bundleName"]+"\t\t开始写入文件 --- > "+tar["path"]) |
||||
|
fullpath=targetDir+"\\"+tar["path"] |
||||
|
zf.write(fullpath,tar["path"]) |
||||
|
zf.close() |
||||
|
print("=======================开始对资源进行分包处理================================") |
||||
|
list = create_split_zip(zipFileBasePath,zipFileBasePathDir,1000 * 1000 * obj["maxFileSize"],obj["suffix"]) |
||||
|
new_config_list=[] |
||||
|
for fi in list: |
||||
|
newob={} |
||||
|
newob["name"]=obj["pkgName"] |
||||
|
newob["resName"]=fi |
||||
|
#newob["version"]=local_version["version"] |
||||
|
new_config_list.append(newob) |
||||
|
configPath=zipFileBasePathDir[:zipFileBasePathDir.find("\\assets")]+"\\config.json" |
||||
|
fileTools.writeJson(configPath,new_config_list) |
||||
|
#删除原有包 |
||||
|
if os.path.exists(zipFileBasePath): |
||||
|
os.remove(zipFileBasePath) |
||||
|
print("-------------------------开始写入分包配置----------------------------------") |
||||
|
print(f'当前资源版本 -> {local_version["version"]}') |
||||
|
#写入数据缓存 |
||||
|
fileTools.writeJson(local_ver_path,local_version) |
||||
|
|
||||
|
def handleGameObject(obj,dirpath): |
||||
|
cachePath=currentPath+"\\cache_files\\";#缓存当前版本变化量 |
||||
|
fileTools.existsDir(cachePath) |
||||
|
game_local_version_list=[] |
||||
|
game_bundle_ver_list={} |
||||
|
for gn in obj["only"]: |
||||
|
local_ver_path_dir=f'{cachePath}{gn}' |
||||
|
local_ver_path=f'{local_ver_path_dir}\\files.json' |
||||
|
local_bundle_ver_path=f'{local_ver_path_dir}\\bundle.ver.json' |
||||
|
fileTools.existsDir(local_ver_path_dir) |
||||
|
gameObj={} |
||||
|
gameObj["name"]=gn |
||||
|
gameObj["local_ver_path"]=local_ver_path |
||||
|
gameObj["cache_list"]=[] |
||||
|
gameObj["list"]=[] |
||||
|
gameObj["ver_list"]=[] |
||||
|
if os.path.exists(local_ver_path): |
||||
|
gameObj["cache_list"] = fileTools.readJson(local_ver_path) |
||||
|
else: |
||||
|
fileTools.writeJson(local_ver_path,gameObj["cache_list"]) |
||||
|
game_local_version_list.append(gameObj) |
||||
|
#bundle list |
||||
|
if os.path.exists(local_bundle_ver_path): |
||||
|
game_bundle_ver_list= fileTools.readJson(local_bundle_ver_path) |
||||
|
else: |
||||
|
fileTools.writeJson(local_bundle_ver_path,game_bundle_ver_list) |
||||
|
|
||||
|
def getGameItem(gn): |
||||
|
for fn in game_local_version_list: |
||||
|
if fn["name"] == gn : |
||||
|
return fn |
||||
|
return None |
||||
|
files = fileTools.get_all_filenames(dirpath,dirpath,False) |
||||
|
filters = obj["filters"] |
||||
|
gameVer={} |
||||
|
for file_path in files: |
||||
|
if not fileTools.hasInList(file_path,filters): |
||||
|
md5 = fileTools.getHas(file_path) |
||||
|
cur_file_path = file_path.replace(dirpath, "") |
||||
|
fileArr=cur_file_path.split("\\") |
||||
|
if fileTools.hasInList(fileArr[0],obj["only"]): |
||||
|
subGameObj=getGameItem(fileArr[0]) |
||||
|
if subGameObj != None: |
||||
|
file_item=getPathItem(cur_file_path,subGameObj["cache_list"]) |
||||
|
|
||||
|
newFileObj={} |
||||
|
newFileObj["bundleName"]= fileArr[0] |
||||
|
newFileObj["path"]=cur_file_path |
||||
|
newFileObj["st"]=os.stat(file_path).st_mtime |
||||
|
subGameObj["ver_list"].append(newFileObj) |
||||
|
if "config" in cur_file_path : |
||||
|
subGameObj["md5"]=md5 |
||||
|
if not fileArr[0] in game_bundle_ver_list: |
||||
|
game_bundle_ver_list[fileArr[0]]=obj["version"] |
||||
|
if file_item == None or isChanged(file_item): |
||||
|
def addObj(): |
||||
|
if file_item != None: |
||||
|
file_item["st"]=os.stat(file_path).st_mtime |
||||
|
if not fileArr[0] in gameVer: |
||||
|
gameVer[fileArr[0]]=game_bundle_ver_list[fileArr[0]] |
||||
|
game_bundle_ver_list[fileArr[0]]=getVer(gameVer[fileArr[0]]) |
||||
|
else: |
||||
|
gameObj["cache_list"].append(newFileObj) |
||||
|
|
||||
|
subGameObj["list"].append(newFileObj) |
||||
|
if len(obj["only"]) > 0: |
||||
|
if fileTools.hasInList(fileArr[0],obj["only"]): |
||||
|
addObj() |
||||
|
else: |
||||
|
addObj() |
||||
|
print("=======================开始发布资源================================") |
||||
|
for fn in game_local_version_list: |
||||
|
id=fn["name"] |
||||
|
verConfigPath=cur_version_path+id+"\\"+game_bundle_ver_list[id]+"\\" |
||||
|
if len(fn["list"]) <=0 : |
||||
|
print(f'======================={id}暂无资源发布============================') |
||||
|
continue; |
||||
|
zipFileHotPathDir=verConfigPath+"\\hot\\assets\\" |
||||
|
fileTools.existsDir(zipFileHotPathDir) |
||||
|
zipFileHotPath=zipFileHotPathDir+"\\"+id+"."+"."+obj["suffix"] |
||||
|
if os.path.exists(zipFileHotPath): |
||||
|
os.remove(zipFileHotPath) |
||||
|
zf = zipfile.ZipFile(zipFileHotPath, "w", zipfile.zlib.DEFLATED) |
||||
|
for tar in fn["list"]: |
||||
|
print("bundleName-> "+tar["bundleName"]+"\t\t开始写入文件 --- > "+tar["path"]) |
||||
|
fullpath=targetDir+"\\"+tar["path"] |
||||
|
zf.write(fullpath,tar["path"]) |
||||
|
zf.close() |
||||
|
print(f'=======================开始对资源【{id}】进行分包处理================================') |
||||
|
list = create_split_zip(zipFileHotPath,zipFileHotPathDir,1000 * 1000 * obj["maxFileSize"],obj["suffix"]) |
||||
|
configPath=zipFileHotPathDir[:zipFileHotPathDir.find("\\assets")]+"\\config.json" |
||||
|
configObj={} |
||||
|
configObj["gameId"]=id |
||||
|
configObj["version"]=fn["md5"] |
||||
|
configObj["list"]=list |
||||
|
fileTools.writeJson(configPath,configObj) |
||||
|
#删除原有包 |
||||
|
if os.path.exists(zipFileHotPath): |
||||
|
os.remove(zipFileHotPath) |
||||
|
#基础版本 |
||||
|
zipFileHotPathDir=verConfigPath+"\\base\\assets\\" |
||||
|
fileTools.existsDir(zipFileHotPathDir) |
||||
|
zipFileHotPath=zipFileHotPathDir+"\\"+id+"."+"."+obj["suffix"] |
||||
|
if os.path.exists(zipFileHotPath): |
||||
|
os.remove(zipFileHotPath) |
||||
|
zf = zipfile.ZipFile(zipFileHotPath, "w", zipfile.zlib.DEFLATED) |
||||
|
for tar in fn["ver_list"]: |
||||
|
print("bundleName-> "+tar["bundleName"]+"\t\t开始写入文件 --- > "+tar["path"]) |
||||
|
fullpath=targetDir+"\\"+tar["path"] |
||||
|
zf.write(fullpath,tar["path"]) |
||||
|
zf.close() |
||||
|
print(f'=======================开始对资源【{id}】进行分包处理================================') |
||||
|
|
||||
|
list = create_split_zip(zipFileHotPath,zipFileHotPathDir,1000 * 1000 * obj["maxFileSize"],obj["suffix"]) |
||||
|
configPath=zipFileHotPathDir[:zipFileHotPathDir.find("\\assets")]+"\\config.json" |
||||
|
configObj={} |
||||
|
configObj["gameId"]=id |
||||
|
configObj["version"]=fn["md5"] |
||||
|
configObj["list"]=list |
||||
|
fileTools.writeJson(configPath,configObj) |
||||
|
#删除原有包 |
||||
|
if os.path.exists(zipFileHotPath): |
||||
|
os.remove(zipFileHotPath) |
||||
|
#写入数据缓存 |
||||
|
fileTools.writeJson(fn["local_ver_path"],fn["cache_list"]) |
||||
|
#写入版本 |
||||
|
fileTools.writeJson(local_bundle_ver_path,game_bundle_ver_list) |
||||
|
print(f'当前资源版本 -> {game_bundle_ver_list[id]}') |
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
currentPath = os.getcwd().replace('\\', '\\') # 获取当前程序运行路径 |
||||
|
parentPath = os.path.dirname(currentPath) # 获取上一级目录 |
||||
|
for itemObj in config: |
||||
|
#处理打包文件目标目录 |
||||
|
targetDir = parentPath +"\\"+itemObj["buildDir"] |
||||
|
targetDir=targetDir.replace("{#}",itemObj["platform"]) |
||||
|
cur_version_path=currentPath+"\\"+itemObj["disName"]+"\\" |
||||
|
fileTools.existsDir(cur_version_path) |
||||
|
if itemObj["pkgName"] == "base": |
||||
|
handleConfigObject(itemObj,targetDir) |
||||
|
elif itemObj["pkgName"] == "game": |
||||
|
handleGameObject(itemObj,targetDir) |
||||
|
else: |
||||
|
print("没有找到处理handler") |
||||
|
|
||||
|
|
@ -0,0 +1,36 @@ |
|||||
|
|
||||
|
import os |
||||
|
import zipfile |
||||
|
|
||||
|
|
||||
|
def get_file_name(path): |
||||
|
return os.path.splitext(os.path.basename(path))[0] |
||||
|
#将zip文件拆分成多个zip字文件 |
||||
|
def create_split_zip(src_zip_path, dst_dir, max_size,suffix="zip"): |
||||
|
cur_file_Name=get_file_name(src_zip_path) |
||||
|
files=[] |
||||
|
with zipfile.ZipFile(src_zip_path, 'r') as z: |
||||
|
file_list = z.infolist() |
||||
|
chunk_number = 1 |
||||
|
dst_zip = None |
||||
|
file_size=0 |
||||
|
for file_info in file_list: |
||||
|
file_data = z.read(file_info.filename) |
||||
|
file_size += file_info.compress_size |
||||
|
if file_size >= max_size : |
||||
|
if dst_zip: |
||||
|
dst_zip.close() |
||||
|
dst_zip=None |
||||
|
chunk_number+=1 |
||||
|
file_size=0 |
||||
|
if dst_zip == None : |
||||
|
fileName=f'{cur_file_Name}{chunk_number}' |
||||
|
files.append(fileName) |
||||
|
dst_zip_name = os.path.join(dst_dir, f'{fileName}.{suffix}') |
||||
|
if os.path.exists(dst_zip_name): |
||||
|
os.remove(dst_zip_name) |
||||
|
dst_zip = zipfile.ZipFile(dst_zip_name, 'w', zipfile.ZIP_DEFLATED) |
||||
|
dst_zip.writestr(file_info.filename, file_data) |
||||
|
if dst_zip != None : |
||||
|
dst_zip.close() |
||||
|
return files |
Loading…
Reference in new issue