#!/usr/bin/python # -*- coding: utf-8 -*- import zipfile, sys, re, os, traceback from biplist import * from Common import Setting, Debug, PathConvert, StringFormat Setting.SetDefaultencodingUTF8() import shutil import datetime import random TEMP_OUT_PATH = r"\ipaTemp" VALID_CMD_ARGV = {"-help", "-resVer", "-checkInfo", "-resPath", "-outPath", "-inPath"} def PrintHelp(): Debug.Log('') Debug.Log('') Debug.Log('命令参数说明') Debug.Log('') Debug.Log('-help 查看帮助') Debug.Log('') Debug.Log('') Debug.Log('-checkInfo 查看ipa里的信息') Debug.Log(' 使用该参数时必须要-inPath') Debug.Log(' 且不会生成新ipa') Debug.Log('') Debug.Log('') Debug.Log('-inPath 原始ipa路径') Debug.Log('-outPath 生成的新ipa路径') Debug.Log('-resVer 生成的新ipa的资源版本号') Debug.Log('-resPath 更新的资源文件路径') Debug.Log(' 原始资源在XCode项目中里XCodeProj/Data/Raw/ios目录下') Debug.Log(' 写入到ipa里Payload/*.app/Data/Raw/ios目录下') Debug.Log('') Debug.Log('') def CheckInfo(inputPath): if not os.path.exists(inputPath): Debug.LogError(inputPath + "不存在") return with zipfile.ZipFile(inputPath, 'r') as ipaFileIn: pattern = re.compile(r'Payload/[^/]*.app/Info.plist') for path in ipaFileIn.infolist(): m = pattern.match(path.filename) if m is not None: plistfp = ipaFileIn.open(path.filename) plistData = plistfp.read() plist = readPlistFromString(plistData) for k in plist: Debug.Log(str(k) + " " + str(plist[k])) def ExecTools(inputPath, outPath, resVer, resPath): if not os.path.exists(inputPath): Debug.LogError(inputPath + "不存在") return if not outPath or outPath == "": Debug.LogError(outPath + "目标目录无效") return if not resVer or resVer == "": Debug.LogError(resVer + "资源版本号无效") return if not os.path.exists(resPath): Debug.LogError(resPath + "不存在") return resVer = int(resVer) dirOutPath = os.path.dirname(outPath) tempOutPath = dirOutPath + TEMP_OUT_PATH if os.path.exists(tempOutPath): Debug.LogError(tempOutPath + "临时解压目录已存在,请先删除") return appPath = None with zipfile.ZipFile(inputPath, 'r') as ipaFileIn: pattern = re.compile(r'Payload/[^/]*.app/Info.plist') for path in ipaFileIn.infolist(): m = pattern.match(path.filename) if m is not None: appPath = path.filename[0:-10] break ipaFileIn.extractall(tempOutPath) plistPath = os.path.join(tempOutPath, appPath, 'Info.plist') plist = readPlist(plistPath) Debug.Log('') Debug.LogSuccess('修改前资源版本' + str(plist['LEBIAN_VERCODE']) + " -> " + str(resVer)) Debug.Log('') Debug.Log('') plist['LEBIAN_VERCODE'] = resVer writePlist(plist, plistPath) lbTimestampPath = os.path.join(tempOutPath, appPath, 'LBTimestamp') with open(lbTimestampPath, 'w') as lbTimestampfp: content = datetime.datetime.now().strftime('%Y%m%d%H%M%S') val1 = random.randint(97,122) val2 = random.randint(97,122) content = content + chr(val1) + chr(val2) Debug.LogSuccess('乐变唯一参数' + content) Debug.Log('') Debug.Log('') lbTimestampfp.write(content) tempResOutPath = os.path.join(tempOutPath, appPath, "Data", "Raw", "ios") for dirpath, dirnames, filenames in os.walk(resPath): fpath = dirpath.replace(resPath, '') fpath = fpath and fpath + os.sep or '' for filename in filenames: shutil.copy(os.path.join(dirpath, filename), os.path.join(tempResOutPath, fpath + filename)) with zipfile.ZipFile(outPath, 'w') as ipaFileOut: for dirpath, dirnames, filenames in os.walk(tempOutPath): fpath = dirpath.replace(tempOutPath, '') if fpath and fpath != '': fpath = fpath + os.sep if len(filenames) == 0: if fpath[0] == '\\' or fpath[0] == '/': fpath = fpath[1:] ipaFileOut.writestr(fpath, '') else: for filename in filenames: ipaFileOut.write(os.path.join(dirpath, filename), fpath + filename, zipfile.ZIP_DEFLATED) shutil.rmtree(tempOutPath) Debug.LogSuccess('生成ipa成功 ' + StringFormat.FormatStdinString(outPath)) Debug.Log('') Debug.Log('') def Main(): args = sys.argv[1:] dic = {} num = len(args) for i in range(num): arg = args[i] if arg.startswith('-'): if not arg in VALID_CMD_ARGV: Debug.LogError(StringFormat.FormatStdinString(arg) + " 不是有效的参数") PrintHelp() return if i + 1 >= num: Debug.LogSuccess(StringFormat.FormatStdinString(arg)) dic[arg] = '' else: if args[i + 1].startswith('-'): Debug.LogSuccess(arg) dic[arg] = '' else: Debug.LogSuccess(StringFormat.FormatStdinString(arg) + " " + StringFormat.FormatStdinString(args[i + 1])) dic[arg] = args[i + 1] if len(dic) <= 0: PrintHelp() return if ('-help' in dic): PrintHelp() return if not ('-inPath' in dic): Debug.Log('') Debug.Log('') Debug.LogError('-inPath 不能为空') Debug.Log('') Debug.Log('') return if ('-checkInfo' in dic): CheckInfo(dic['-inPath']) return if not ('-outPath' in dic): PrintHelp() Debug.Log('') Debug.Log('') Debug.LogError('-outPath 不能为空') Debug.Log('') Debug.Log('') return if not ('-resVer' in dic): PrintHelp() Debug.Log('') Debug.Log('') Debug.LogError('-resVer 不能为空') Debug.Log('') Debug.Log('') return if not ('-resPath' in dic): PrintHelp() Debug.Log('') Debug.Log('') Debug.LogError('-resPath 不能为空') Debug.Log('') Debug.Log('') return Debug.Log('') Debug.Log('') ExecTools(dic['-inPath'], dic['-outPath'], dic['-resVer'], dic['-resPath']) if __name__ == '__main__': try: Main() except Exception as e: Debug.LogError(e) Debug.LogError(traceback.format_exc(), True) sys.exit(1)