File.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. # -*- coding:utf-8 -*-
  2. import os
  3. import shutil
  4. import xml.etree.ElementTree as ET
  5. import re
  6. import platform
  7. from V1.PrintLog import printlog
  8. from V1 import Contants
  9. SEPARATOR = ""
  10. if platform.system() == "Windows":
  11. SEPARATOR = "\\"
  12. else:
  13. SEPARATOR = "/"
  14. def copyFiles(fromDir,toDir):
  15. #必须合并的列表
  16. mergeList = ["attrs.xml","colors.xml","dimens.xml","drawables.xml","ids.xml","public.xml","strings.xml","style.xml"]
  17. printlog(">>>>>>>>>>>>>>>>>>>>>>>>fromDir:<<<<<<<<<<<<<<<<<<<<<<<<<< %s" % fromDir)
  18. if os.path.exists(fromDir) == False:
  19. printlog("fromDir or toDir is not exists!")
  20. return 1
  21. #value文件夹下的xml如果有同名必须合并
  22. valuePattern = re.compile(r".*/values.*")
  23. for parent, dirs,files in os.walk(fromDir):
  24. toFileParent = parent.replace(fromDir, toDir)
  25. for fileName in files:
  26. oriFile = "%s/%s"%(parent, fileName)
  27. toFile = "%s/%s"%(toFileParent, fileName)
  28. # PrintLog("oriFile: %s"%oriFile)
  29. # PrintLog("toFile: %s"%toFile)
  30. # PrintLog("parent:%s"%parent)
  31. #是value文件夹 and 渠道资源与包有相同的文件
  32. if valuePattern.match(parent) and os.path.exists(toFile):
  33. # PrintLog("merge file %s to file %s-------------------------"%(oriFile, toFile))
  34. mergeResFile(oriFile, toFile)
  35. #当包里没有与渠道相同的文件
  36. elif os.path.exists(toFile) == False:
  37. # PrintLog("copy file %s to file %s--------------------------"%(oriFile, toFile))
  38. os.system("mkdir -p %s"%(os.path.dirname(toFile)))
  39. shutil.copyfile(oriFile, toFile)
  40. pass
  41. return 0
  42. def mergeResFile(fromFile,toFile):
  43. if not os.path.exists(fromFile):
  44. printlog("fromFile or toFile is not exists")
  45. return 1
  46. # PrintLog("start to merge %s and %s "%(fromFile,toFile))
  47. sourceTree = ET.parse(fromFile)
  48. desTree = ET.parse(toFile)
  49. # 临时打包目录
  50. sourceRoot = sourceTree.getroot()
  51. desRoot = desTree.getroot()
  52. #SDK
  53. sourceChildren = list(sourceRoot)
  54. desChildren = list(desRoot)
  55. #获取原文件attrib,用于排重
  56. desNames = []
  57. publicDict = {}
  58. prefixDict = {}
  59. for child in desChildren:
  60. # PrintLog(child.attrib)
  61. desNames.append(child.attrib["name"])
  62. #保存每个属性的最大id值
  63. if fromFile.find("public.xml") > 0:
  64. if child.attrib["type"] not in publicDict.keys():
  65. publicDict[child.attrib["type"]] = int(child.attrib["id"],16)
  66. if child.attrib["type"] not in prefixDict.keys():
  67. prefixDict[child.attrib["type"]] = child.attrib["id"][0:6]
  68. # PrintLog("prefixDict ---- ")
  69. # PrintLog(prefixDict)
  70. else:
  71. newPublicId = int(child.attrib["id"],16)
  72. oldPublicId = publicDict[child.attrib["type"]]
  73. #publicDict[child.attrib["type"]] = newPublicId if newPublicId > oldPublicId else oldPublicId
  74. if newPublicId > oldPublicId:
  75. publicDict[child.attrib["type"]] = newPublicId
  76. # PrintLog("replace type:%s"%publicDict[child.attrib["type"]])
  77. # PrintLog("replace oldPublicId:%d with newPublicId:%d"%(oldPublicId,newPublicId))
  78. #打印测试信息
  79. # PrintLog("print publicDict ----------------------------")
  80. # PrintLog(publicDict)
  81. # PrintLog("print publicDict ----------------------------")
  82. for child in sourceChildren:
  83. if child.attrib["name"] in desNames:
  84. #若有重复,使用原包里的的
  85. index = desNames.index(child.attrib["name"])
  86. # PrintLog("confilct child:%s"%desChildren[index].attrib["name"])
  87. continue
  88. # PrintLog("append child name:%s"%child.attrib["name"])
  89. #public.xml需要特殊合并
  90. if fromFile.find("public.xml") > 0:
  91. if child.attrib["type"] in publicDict:
  92. # PrintLog("old id:%s --------------- type:%s"%(child.attrib["id"],child.attrib["type"]))
  93. publicDict[child.attrib["type"]] = publicDict[child.attrib["type"]] + 1
  94. child.attrib["id"] = hex(publicDict[child.attrib["type"]])
  95. # PrintLog("new id:%s ---------------"%child.attrib["id"])
  96. #如果ID不存在,则直接清0
  97. elif child.attrib["type"] not in publicDict:
  98. # PrintLog("reset id to 00")
  99. # PrintLog("old id:%s ---------------"%child.attrib["id"])
  100. last_preffix = sorted(prefixDict.values())[-1]
  101. # PrintLog("last object:%s"%last_preffix[-2:])
  102. preffixNum = hex(int(last_preffix[-2:],16)+1)[last_preffix.index("x")+1:]
  103. if len(preffixNum) < 2:
  104. preffixNum = "0"+preffixNum
  105. preffix = "0x7f"+preffixNum
  106. # PrintLog("preffix_suffix:%s"%preffix)
  107. prefixDict[child.attrib["type"]] = preffix
  108. publicDict[child.attrib["type"]] = int(preffix+"0000",16)
  109. # PrintLog("publicDict with type:%s and value:%s"%(child.attrib["type"],publicDict[child.attrib["type"]]))
  110. child.attrib["id"] = hex(publicDict[child.attrib["type"]])
  111. # PrintLog("publicDict[child.attrib['type']:%s"%publicDict[child.attrib["type"]])
  112. # PrintLog("new id:%s ---------------"%child.attrib["id"])
  113. desRoot.append(child)
  114. #PrintLog("print prefixDict ----------------------------")
  115. #PrintLog(prefixDict)
  116. #PrintLog("print prefixDict ----------------------------")
  117. # if fromFile.find("public.xml") > 0:
  118. # desRoot.getchildren().sort()
  119. # PrintLog("start to write xml")
  120. desTree.write(toFile,"utf-8",xml_declaration=True)
  121. # PrintLog("finished writing xml")
  122. # PrintLog("merging files finished")
  123. return 0
  124. #比较函数,用于etree排序
  125. def cmp(x,y):
  126. if x.attrib["type"] > y.attrib["type"]:
  127. return 1
  128. elif x.attrib["type"] < y.attrib["type"]:
  129. return -1
  130. else:
  131. return 0
  132. def mergeManifest(targetM,sdkConfig,debug = False):
  133. #注册命名空间
  134. ET.register_namespace('android',"http://schemas.android.com/apk/res/android")
  135. printlog("targetM:%s" % targetM)
  136. printlog("sdkConfig:%s" % sdkConfig)
  137. if os.path.exists(targetM) == False or os.path.exists(sdkConfig) == False:
  138. printlog("targetM or sdkConfig is not exists!")
  139. return 1
  140. sdkRoot = ET.parse(sdkConfig).getroot()
  141. if sdkRoot == None:
  142. printlog("cant parse sdkConfig!")
  143. return 1
  144. targetTree = ET.parse(targetM)
  145. targetRoot = targetTree.getroot()
  146. if targetRoot == None:
  147. printlog("cant parse targetTree")
  148. return 1
  149. targetApplicationRoot = targetRoot.find("application")
  150. #合并activity和service
  151. sdkActivities = sdkRoot.find("sdk_activity").iter("activity")
  152. sdkActivities_alicas = sdkRoot.find("sdk_activity").iter("activity-alias")
  153. sdkServices = sdkRoot.find("sdk_activity").iter("service")
  154. sdkReceiver = sdkRoot.find("sdk_activity").iter("receiver")
  155. sdkProvider = sdkRoot.find("sdk_activity").iter("provider")
  156. sdkQueries = sdkRoot.find("sdk_activity").iter("queries")
  157. for activity in sdkActivities:
  158. targetApplicationRoot.append(activity)
  159. for service in sdkServices:
  160. targetApplicationRoot.append(service)
  161. for receiver in sdkReceiver:
  162. targetApplicationRoot.append(receiver)
  163. for provider in sdkProvider:
  164. targetApplicationRoot.append(provider)
  165. for alicas in sdkActivities_alicas:
  166. targetApplicationRoot.append(alicas)
  167. for queries in sdkQueries:
  168. targetApplicationRoot.append(queries)
  169. printlog("merging activity and service completed!")
  170. #合并meta-data
  171. sdkMetas = sdkRoot.find("sdk_meta").iter("meta-data")
  172. for meta in sdkMetas:
  173. targetApplicationRoot.append(meta)
  174. printlog("merging meta-data completed!")
  175. #合并permission
  176. sdkPermissions = []
  177. for per in sdkRoot.find("sdk_permission").findall("uses-permission"):
  178. sdkPermissions.append(list(per.attrib.values())[0])
  179. targetPermissions = []
  180. for per in targetRoot.findall("uses-permission"):
  181. targetPermissions.append(list(per.attrib.values())[0])
  182. targetRoot.remove(per)
  183. #利用set排重
  184. mergePermissions = list(set(sdkPermissions) | set(targetPermissions))
  185. for per in mergePermissions:
  186. element = ET.Element("uses-permission")
  187. element.attrib = {"android:name":per}
  188. element.tail = "\n\t"
  189. targetRoot.append(element)
  190. printlog("merging permission completed!")
  191. if debug:
  192. targetTree.write("test.xml","utf-8",xml_declaration=True)
  193. else:
  194. targetTree.write("%s"%targetM,"utf-8",xml_declaration=True)
  195. printlog("writing AndroidManifest.xml completed!")
  196. return 0
  197. #fromDir SDK toDir game
  198. def mergeDir(fromDir, toDir):
  199. if os.path.exists(fromDir) == False:
  200. return 1
  201. compareFile(fromDir, toDir)
  202. return 0
  203. pass
  204. def compareFile(cmpFile, oriFile):
  205. exceptList = [ ]
  206. for parent, dirName, fileNames in os.walk(cmpFile):
  207. oriParent = parent.replace(cmpFile, oriFile)
  208. shouldRewrite = parent.rfind("third/sdk")
  209. for fileName in fileNames:
  210. if shouldRewrite >= 0 or (os.path.exists("%s/%s"%(oriParent, fileName)) == False
  211. and parent.find(Contants.getIgnorePackagePath()) < 0):
  212. fromDir = "%s/%s"%(parent , fileName)
  213. # PrintLog("fromDir :%s"%fromDir)
  214. toDir = "%s/%s"%(oriParent, fileName)
  215. # PrintLog("toDir: %s"%toDir)
  216. copyFileForCompareFile(fromDir, toDir)
  217. pass
  218. def copyAllFile(fromFile,toFile):
  219. for parent, dirName, fileNames in os.walk(fromFile):
  220. oriParent = parent.replace(fromFile, toFile)
  221. for fileName in fileNames:
  222. fromDir = "%s/%s"%(parent , fileName)
  223. # PrintLog("fromDir :%s"%fromDir)
  224. toDir = "%s/%s"%(oriParent, fileName)
  225. # PrintLog("toDir: %s"%toDir)
  226. copyFileForCompareFile(fromDir, toDir)
  227. pass
  228. def copyFileForCompareFile(fromFile, toFile):
  229. if os.path.exists(fromFile) == False:
  230. printlog("file %s is not exists" % fromFile)
  231. return
  232. filePattern = re.compile(r".*\..*")
  233. toDir = toFile
  234. if filePattern.match(toFile):
  235. toDir = os.path.dirname(toFile)
  236. if os.path.exists(toDir) == False:
  237. os.makedirs(toDir)
  238. shutil.copy(fromFile, toFile)
  239. pass
  240. #文件修改时间比较
  241. #file1 > file2 return 1
  242. #file1 == file2 return 0
  243. #file1 < file2 return -1
  244. #任意一个文件不存在则返回None
  245. def compareFileModifyTime(file1, file2):
  246. result = 0
  247. if not os.path.exists(file1):
  248. err = "file %s is not exists"%file1
  249. printlog(err)
  250. return None
  251. if not os.path.exists(file2):
  252. err = "file %s is not exists"%file2
  253. printlog(err)
  254. return None
  255. file1MTime = os.stat(file1).st_mtime
  256. file2MTime = os.stat(file2).st_mtime
  257. printlog("[file1MTime]: %s" % file1MTime)
  258. printlog("[file2MTime]: %s" % file2MTime)
  259. if file1MTime > file2MTime:
  260. return 1
  261. elif file1MTime < file2MTime:
  262. return -1
  263. else:
  264. return 0
  265. pass
  266. #合并apktool.yml中的unkown内容
  267. def mergeYmlContent(fromFilePath, toFilePath):
  268. printlog("----------------------start mergeYmlContent --------------")
  269. if os.path.exists(fromFilePath) == False:
  270. return 0
  271. if os.path.exists(toFilePath) == False:
  272. shutil.copy(fromFile, toFilePath)
  273. return 1
  274. unknownFiles = "unknownFiles:"
  275. toFileLines = open(toFilePath).readlines()
  276. toFile = open(toFilePath, "w")
  277. toFileHasUnknowFilesMark = False #目标文件是否存在unknownFiles属性
  278. for line in toFileLines:
  279. if line.find(unknownFiles) >= 0:
  280. toFileHasUnknowFilesMark = True
  281. #当存在unknownFiles属性但为空时去掉{}重新写入
  282. if line.find("{}") >= 0:
  283. line = line.replace("{}", "")
  284. toFile.write(line)
  285. writeYmlContent(fromFilePath, toFile)
  286. continue
  287. pass
  288. toFile.write(line)
  289. pass
  290. if toFileHasUnknowFilesMark == False:
  291. toFile.write(unknownFiles)
  292. toFile.write("\n")
  293. writeYmlContent(fromFilePath, toFile)
  294. return 1
  295. pass
  296. def writeYmlContent(fromFilePath, toFile):
  297. unknownFiles = "unknownFiles:"
  298. lines = open(fromFilePath).readlines()
  299. unknowFilesMarkFound = False
  300. for line in lines:
  301. if unknowFilesMarkFound:
  302. if line.find(" ") == 0:
  303. toFile.write(line)
  304. else:
  305. break
  306. if line.find(unknownFiles) >= 0:
  307. if line.find("{}") >= 0:
  308. break
  309. else:
  310. unknowFilesMarkFound = True
  311. pass
  312. pass
  313. #文件安全删除
  314. def safeFileDelete(filePath):
  315. if os.path.exists(filePath):
  316. if os.path.isdir(filePath):
  317. shutil.rmtree(filePath)
  318. printlog(">>>>>>>>>>>>>>>>>>>>>>>>delete isdir filePath:<<<<<<<<<<<<<<<<<<<<<<<<<< %s" % filePath)
  319. elif os.path.isfile(filePath):
  320. printlog(">>>>>>>>>>>>>>>>>>>>>>>>delete isfile filePath:<<<<<<<<<<<<<<<<<<<<<<<<<< %s" % filePath)
  321. os.remove(filePath)
  322. return
  323. #删除文件但不删除文件夹
  324. def del_file(path_data):
  325. for i in os.listdir(path_data) :# os.listdir(path_data)#返回一个列表,里面是当前目录下面的所有东西的相对路径
  326. file_data = path_data + "/" + i#当前文件夹的下面的所有东西的绝对路径
  327. if os.path.isfile(file_data) == True:#os.path.isfile判断是否为文件,如果是文件,就删除.如果是文件夹.递归给del_file.
  328. os.remove(file_data)
  329. else:
  330. del_file(file_data)
  331. if __name__ == "__main__":
  332. #mergeManifest("AndroidManifest.xml","test_sdk_config.xml",True)
  333. #copyFiles("test","toDir")
  334. fromFile ="apktool.yml"
  335. toFile = "des_apktool.yml"
  336. mergeYmlContent(fromFile, toFile)
  337. pass