123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- # -*- coding:utf-8 -*-
- import os
- import shutil
- import xml.etree.ElementTree as ET
- import re
- import platform
- from V1.PrintLog import printlog
- from V1 import Contants
- SEPARATOR = ""
- if platform.system() == "Windows":
- SEPARATOR = "\\"
- else:
- SEPARATOR = "/"
- def copyFiles(fromDir,toDir):
- #必须合并的列表
- mergeList = ["attrs.xml","colors.xml","dimens.xml","drawables.xml","ids.xml","public.xml","strings.xml","style.xml"]
- printlog(">>>>>>>>>>>>>>>>>>>>>>>>fromDir:<<<<<<<<<<<<<<<<<<<<<<<<<< %s" % fromDir)
- if os.path.exists(fromDir) == False:
- printlog("fromDir or toDir is not exists!")
- return 1
- #value文件夹下的xml如果有同名必须合并
- valuePattern = re.compile(r".*/values.*")
- for parent, dirs,files in os.walk(fromDir):
- toFileParent = parent.replace(fromDir, toDir)
- for fileName in files:
- oriFile = "%s/%s"%(parent, fileName)
- toFile = "%s/%s"%(toFileParent, fileName)
- # PrintLog("oriFile: %s"%oriFile)
- # PrintLog("toFile: %s"%toFile)
- # PrintLog("parent:%s"%parent)
- #是value文件夹 and 渠道资源与包有相同的文件
- if valuePattern.match(parent) and os.path.exists(toFile):
- # PrintLog("merge file %s to file %s-------------------------"%(oriFile, toFile))
- mergeResFile(oriFile, toFile)
- #当包里没有与渠道相同的文件
- elif os.path.exists(toFile) == False:
- # PrintLog("copy file %s to file %s--------------------------"%(oriFile, toFile))
- os.system("mkdir -p %s"%(os.path.dirname(toFile)))
- shutil.copyfile(oriFile, toFile)
- pass
- return 0
- def mergeResFile(fromFile,toFile):
- if not os.path.exists(fromFile):
- printlog("fromFile or toFile is not exists")
- return 1
- # PrintLog("start to merge %s and %s "%(fromFile,toFile))
- sourceTree = ET.parse(fromFile)
- desTree = ET.parse(toFile)
- # 临时打包目录
- sourceRoot = sourceTree.getroot()
- desRoot = desTree.getroot()
- #SDK
- sourceChildren = list(sourceRoot)
- desChildren = list(desRoot)
- #获取原文件attrib,用于排重
- desNames = []
- publicDict = {}
- prefixDict = {}
- for child in desChildren:
- # PrintLog(child.attrib)
- desNames.append(child.attrib["name"])
-
- #保存每个属性的最大id值
- if fromFile.find("public.xml") > 0:
- if child.attrib["type"] not in publicDict.keys():
- publicDict[child.attrib["type"]] = int(child.attrib["id"],16)
- if child.attrib["type"] not in prefixDict.keys():
- prefixDict[child.attrib["type"]] = child.attrib["id"][0:6]
-
- # PrintLog("prefixDict ---- ")
- # PrintLog(prefixDict)
- else:
- newPublicId = int(child.attrib["id"],16)
- oldPublicId = publicDict[child.attrib["type"]]
- #publicDict[child.attrib["type"]] = newPublicId if newPublicId > oldPublicId else oldPublicId
- if newPublicId > oldPublicId:
- publicDict[child.attrib["type"]] = newPublicId
- # PrintLog("replace type:%s"%publicDict[child.attrib["type"]])
- # PrintLog("replace oldPublicId:%d with newPublicId:%d"%(oldPublicId,newPublicId))
- #打印测试信息
- # PrintLog("print publicDict ----------------------------")
- # PrintLog(publicDict)
- # PrintLog("print publicDict ----------------------------")
- for child in sourceChildren:
- if child.attrib["name"] in desNames:
- #若有重复,使用原包里的的
- index = desNames.index(child.attrib["name"])
- # PrintLog("confilct child:%s"%desChildren[index].attrib["name"])
- continue
- # PrintLog("append child name:%s"%child.attrib["name"])
- #public.xml需要特殊合并
- if fromFile.find("public.xml") > 0:
- if child.attrib["type"] in publicDict:
- # PrintLog("old id:%s --------------- type:%s"%(child.attrib["id"],child.attrib["type"]))
- publicDict[child.attrib["type"]] = publicDict[child.attrib["type"]] + 1
- child.attrib["id"] = hex(publicDict[child.attrib["type"]])
- # PrintLog("new id:%s ---------------"%child.attrib["id"])
- #如果ID不存在,则直接清0
- elif child.attrib["type"] not in publicDict:
- # PrintLog("reset id to 00")
- # PrintLog("old id:%s ---------------"%child.attrib["id"])
-
- last_preffix = sorted(prefixDict.values())[-1]
- # PrintLog("last object:%s"%last_preffix[-2:])
- preffixNum = hex(int(last_preffix[-2:],16)+1)[last_preffix.index("x")+1:]
- if len(preffixNum) < 2:
- preffixNum = "0"+preffixNum
- preffix = "0x7f"+preffixNum
- # PrintLog("preffix_suffix:%s"%preffix)
- prefixDict[child.attrib["type"]] = preffix
- publicDict[child.attrib["type"]] = int(preffix+"0000",16)
- # PrintLog("publicDict with type:%s and value:%s"%(child.attrib["type"],publicDict[child.attrib["type"]]))
- child.attrib["id"] = hex(publicDict[child.attrib["type"]])
- # PrintLog("publicDict[child.attrib['type']:%s"%publicDict[child.attrib["type"]])
- # PrintLog("new id:%s ---------------"%child.attrib["id"])
- desRoot.append(child)
- #PrintLog("print prefixDict ----------------------------")
- #PrintLog(prefixDict)
- #PrintLog("print prefixDict ----------------------------")
- # if fromFile.find("public.xml") > 0:
- # desRoot.getchildren().sort()
- # PrintLog("start to write xml")
- desTree.write(toFile,"utf-8",xml_declaration=True)
- # PrintLog("finished writing xml")
- # PrintLog("merging files finished")
- return 0
- #比较函数,用于etree排序
- def cmp(x,y):
- if x.attrib["type"] > y.attrib["type"]:
- return 1
- elif x.attrib["type"] < y.attrib["type"]:
- return -1
- else:
- return 0
-
- def mergeManifest(targetM,sdkConfig,debug = False):
- #注册命名空间
- ET.register_namespace('android',"http://schemas.android.com/apk/res/android")
- printlog("targetM:%s" % targetM)
- printlog("sdkConfig:%s" % sdkConfig)
- if os.path.exists(targetM) == False or os.path.exists(sdkConfig) == False:
- printlog("targetM or sdkConfig is not exists!")
- return 1
- sdkRoot = ET.parse(sdkConfig).getroot()
- if sdkRoot == None:
- printlog("cant parse sdkConfig!")
- return 1
- targetTree = ET.parse(targetM)
- targetRoot = targetTree.getroot()
- if targetRoot == None:
- printlog("cant parse targetTree")
- return 1
- targetApplicationRoot = targetRoot.find("application")
- #合并activity和service
- sdkActivities = sdkRoot.find("sdk_activity").iter("activity")
- sdkActivities_alicas = sdkRoot.find("sdk_activity").iter("activity-alias")
- sdkServices = sdkRoot.find("sdk_activity").iter("service")
- sdkReceiver = sdkRoot.find("sdk_activity").iter("receiver")
- sdkProvider = sdkRoot.find("sdk_activity").iter("provider")
- sdkQueries = sdkRoot.find("sdk_activity").iter("queries")
- for activity in sdkActivities:
- targetApplicationRoot.append(activity)
- for service in sdkServices:
- targetApplicationRoot.append(service)
- for receiver in sdkReceiver:
- targetApplicationRoot.append(receiver)
- for provider in sdkProvider:
- targetApplicationRoot.append(provider)
- for alicas in sdkActivities_alicas:
- targetApplicationRoot.append(alicas)
- for queries in sdkQueries:
- targetApplicationRoot.append(queries)
- printlog("merging activity and service completed!")
- #合并meta-data
- sdkMetas = sdkRoot.find("sdk_meta").iter("meta-data")
- for meta in sdkMetas:
- targetApplicationRoot.append(meta)
- printlog("merging meta-data completed!")
- #合并permission
- sdkPermissions = []
- for per in sdkRoot.find("sdk_permission").findall("uses-permission"):
- sdkPermissions.append(list(per.attrib.values())[0])
- targetPermissions = []
- for per in targetRoot.findall("uses-permission"):
- targetPermissions.append(list(per.attrib.values())[0])
- targetRoot.remove(per)
- #利用set排重
- mergePermissions = list(set(sdkPermissions) | set(targetPermissions))
- for per in mergePermissions:
- element = ET.Element("uses-permission")
- element.attrib = {"android:name":per}
- element.tail = "\n\t"
- targetRoot.append(element)
- printlog("merging permission completed!")
- if debug:
- targetTree.write("test.xml","utf-8",xml_declaration=True)
- else:
- targetTree.write("%s"%targetM,"utf-8",xml_declaration=True)
- printlog("writing AndroidManifest.xml completed!")
- return 0
- #fromDir SDK toDir game
- def mergeDir(fromDir, toDir):
- if os.path.exists(fromDir) == False:
- return 1
-
- compareFile(fromDir, toDir)
- return 0
- pass
- def compareFile(cmpFile, oriFile):
- exceptList = [ ]
- for parent, dirName, fileNames in os.walk(cmpFile):
- oriParent = parent.replace(cmpFile, oriFile)
- shouldRewrite = parent.rfind("third/sdk")
- for fileName in fileNames:
- if shouldRewrite >= 0 or (os.path.exists("%s/%s"%(oriParent, fileName)) == False
- and parent.find(Contants.getIgnorePackagePath()) < 0):
- fromDir = "%s/%s"%(parent , fileName)
- # PrintLog("fromDir :%s"%fromDir)
- toDir = "%s/%s"%(oriParent, fileName)
- # PrintLog("toDir: %s"%toDir)
- copyFileForCompareFile(fromDir, toDir)
- pass
- def copyAllFile(fromFile,toFile):
- for parent, dirName, fileNames in os.walk(fromFile):
- oriParent = parent.replace(fromFile, toFile)
- for fileName in fileNames:
- fromDir = "%s/%s"%(parent , fileName)
- # PrintLog("fromDir :%s"%fromDir)
- toDir = "%s/%s"%(oriParent, fileName)
- # PrintLog("toDir: %s"%toDir)
- copyFileForCompareFile(fromDir, toDir)
- pass
- def copyFileForCompareFile(fromFile, toFile):
- if os.path.exists(fromFile) == False:
- printlog("file %s is not exists" % fromFile)
- return
-
- filePattern = re.compile(r".*\..*")
- toDir = toFile
- if filePattern.match(toFile):
- toDir = os.path.dirname(toFile)
-
- if os.path.exists(toDir) == False:
- os.makedirs(toDir)
- shutil.copy(fromFile, toFile)
- pass
- #文件修改时间比较
- #file1 > file2 return 1
- #file1 == file2 return 0
- #file1 < file2 return -1
- #任意一个文件不存在则返回None
- def compareFileModifyTime(file1, file2):
- result = 0
- if not os.path.exists(file1):
- err = "file %s is not exists"%file1
- printlog(err)
- return None
- if not os.path.exists(file2):
- err = "file %s is not exists"%file2
- printlog(err)
- return None
- file1MTime = os.stat(file1).st_mtime
- file2MTime = os.stat(file2).st_mtime
- printlog("[file1MTime]: %s" % file1MTime)
- printlog("[file2MTime]: %s" % file2MTime)
- if file1MTime > file2MTime:
- return 1
- elif file1MTime < file2MTime:
- return -1
- else:
- return 0
- pass
- #合并apktool.yml中的unkown内容
- def mergeYmlContent(fromFilePath, toFilePath):
- printlog("----------------------start mergeYmlContent --------------")
- if os.path.exists(fromFilePath) == False:
- return 0
- if os.path.exists(toFilePath) == False:
- shutil.copy(fromFile, toFilePath)
- return 1
- unknownFiles = "unknownFiles:"
- toFileLines = open(toFilePath).readlines()
- toFile = open(toFilePath, "w")
- toFileHasUnknowFilesMark = False #目标文件是否存在unknownFiles属性
- for line in toFileLines:
- if line.find(unknownFiles) >= 0:
- toFileHasUnknowFilesMark = True
- #当存在unknownFiles属性但为空时去掉{}重新写入
- if line.find("{}") >= 0:
- line = line.replace("{}", "")
- toFile.write(line)
- writeYmlContent(fromFilePath, toFile)
- continue
- pass
- toFile.write(line)
- pass
- if toFileHasUnknowFilesMark == False:
- toFile.write(unknownFiles)
- toFile.write("\n")
- writeYmlContent(fromFilePath, toFile)
- return 1
- pass
- def writeYmlContent(fromFilePath, toFile):
- unknownFiles = "unknownFiles:"
- lines = open(fromFilePath).readlines()
- unknowFilesMarkFound = False
- for line in lines:
- if unknowFilesMarkFound:
- if line.find(" ") == 0:
- toFile.write(line)
- else:
- break
- if line.find(unknownFiles) >= 0:
- if line.find("{}") >= 0:
- break
- else:
- unknowFilesMarkFound = True
- pass
- pass
- #文件安全删除
- def safeFileDelete(filePath):
- if os.path.exists(filePath):
- if os.path.isdir(filePath):
- shutil.rmtree(filePath)
- printlog(">>>>>>>>>>>>>>>>>>>>>>>>delete isdir filePath:<<<<<<<<<<<<<<<<<<<<<<<<<< %s" % filePath)
- elif os.path.isfile(filePath):
- printlog(">>>>>>>>>>>>>>>>>>>>>>>>delete isfile filePath:<<<<<<<<<<<<<<<<<<<<<<<<<< %s" % filePath)
- os.remove(filePath)
- return
- #删除文件但不删除文件夹
- def del_file(path_data):
- for i in os.listdir(path_data) :# os.listdir(path_data)#返回一个列表,里面是当前目录下面的所有东西的相对路径
- file_data = path_data + "/" + i#当前文件夹的下面的所有东西的绝对路径
- if os.path.isfile(file_data) == True:#os.path.isfile判断是否为文件,如果是文件,就删除.如果是文件夹.递归给del_file.
- os.remove(file_data)
- else:
- del_file(file_data)
- if __name__ == "__main__":
- #mergeManifest("AndroidManifest.xml","test_sdk_config.xml",True)
- #copyFiles("test","toDir")
- fromFile ="apktool.yml"
- toFile = "des_apktool.yml"
- mergeYmlContent(fromFile, toFile)
- pass
|