/autopatch/changelist.py

https://gitlab.com/Tu-dou520/FlymeOS5-tools · Python · 185 lines · 105 code · 53 blank · 27 comment · 19 complexity · b89d0d72efbb963bbf538be063deb8ec MD5 · raw file

  1. #!/usr/bin/python
  2. # Filename: changelist.py
  3. """
  4. Usage: $shell changelist.py [OPTIONS]
  5. OPTIONS:
  6. --make : Make the change list out
  7. --show : Show the change list out
  8. """
  9. __author__ = 'duanqz@gmail.com'
  10. import shutil
  11. import os, sys
  12. import subprocess
  13. import tempfile
  14. import xml.dom.minidom
  15. from config import Config
  16. from formatters.log import Log
  17. try:
  18. import xml.etree.cElementTree as ET
  19. except ImportError:
  20. import xml.etree.ElementTree as ET
  21. #from lxml import etree as ET
  22. TAG="changelist"
  23. class ChangeList:
  24. def __init__(self, olderRoot, newerRoot, patchXML):
  25. ChangeList.OLDER_ROOT = olderRoot
  26. ChangeList.NEWER_ROOT = newerRoot
  27. ChangeList.PATCH_XML = patchXML
  28. def make(self, force=True):
  29. """ Generate the change list into XML.
  30. Set force as False not to generate again if exists.
  31. """
  32. if not force and os.path.exists(ChangeList.PATCH_XML):
  33. Log.d(TAG, "Using the existing %s" % ChangeList.PATCH_XML)
  34. return True
  35. Log.i(TAG, "Generating %s" % ChangeList.PATCH_XML)
  36. hasChange = ChangeList.XMLFromDiff()
  37. return hasChange
  38. @staticmethod
  39. def XMLFromDiff():
  40. (dom, feature) = ChangeList.createXML()
  41. tmp = ChangeList.fuse()
  42. hasChange = False
  43. for (dirpath, dirnames, filenames) in os.walk(tmp):
  44. dirnames = dirnames # No use, just avoid of warning
  45. for filename in filenames:
  46. path = os.path.join(dirpath, filename)
  47. target = os.path.relpath(path, tmp)
  48. older = os.path.join(ChangeList.OLDER_ROOT, target)
  49. newer = os.path.join(ChangeList.NEWER_ROOT, target)
  50. olderExists = os.path.exists(older)
  51. newerExists = os.path.exists(newer)
  52. if olderExists and newerExists:
  53. subp = subprocess.Popen(["diff", older, newer], stdout=subprocess.PIPE)
  54. subp.communicate()
  55. # 0 if inputs are the same
  56. # 1 if different
  57. # 2 if trouble, we do not handle this case
  58. if subp.returncode == 1:
  59. ChangeList.appendReivse(dom, feature, "MERGE", target)
  60. hasChange = True
  61. elif olderExists:
  62. ChangeList.appendReivse(dom, feature, "DELETE", target)
  63. hasChange = True
  64. elif newerExists:
  65. ChangeList.appendReivse(dom, feature, "ADD", target)
  66. hasChange = True
  67. shutil.rmtree(tmp)
  68. ChangeList.writeXML(dom)
  69. return hasChange
  70. @staticmethod
  71. def fuse():
  72. tmp = tempfile.mktemp()
  73. os.makedirs(tmp)
  74. for subdir in os.listdir(ChangeList.OLDER_ROOT):
  75. src = os.path.join(ChangeList.OLDER_ROOT, subdir)
  76. subprocess.Popen(["cp", "-frp", src, tmp], stdout=subprocess.PIPE).communicate()
  77. for subdir in os.listdir(ChangeList.NEWER_ROOT):
  78. src = os.path.join(ChangeList.NEWER_ROOT, subdir)
  79. subprocess.Popen(["cp", "-frp", src, tmp], stdout=subprocess.PIPE).communicate()
  80. return tmp
  81. @staticmethod
  82. def createXML():
  83. # root = ET.Element('features')
  84. # feature = ET.Element('feature',
  85. # {'description' : 'These files are diff from %s and %s' %(ChangeList.OLDER_ROOT, ChangeList.NEWER_ROOT)})
  86. # root.append(feature)
  87. impl = xml.dom.minidom.getDOMImplementation()
  88. dom = impl.createDocument(None, "features", None)
  89. root = dom.documentElement
  90. feature = dom.createElement("feature")
  91. feature.setAttribute("description", "These files are diff from %s and %s" % (ChangeList.OLDER_ROOT, ChangeList.NEWER_ROOT))
  92. root.appendChild(feature)
  93. return (dom, feature)
  94. @staticmethod
  95. def writeXML(dom):
  96. # tree = ET.ElementTree(root)
  97. # tree.write(ChangeList.PATCH_XML, #pretty_print=True,
  98. # xml_declaration=True, encoding='utf-8')
  99. f = open(ChangeList.PATCH_XML, 'w')
  100. dom.writexml(f, addindent=' ', newl='\n', encoding='utf-8')
  101. f.close()
  102. Log.i(TAG, "%s is generated" % ChangeList.PATCH_XML)
  103. @staticmethod
  104. def appendReivse(dom, feature, action, target):
  105. # revise = ET.Element('revise',
  106. # {'action' : action,
  107. # 'target' : target})
  108. #
  109. revise = dom.createElement("revise")
  110. revise.setAttribute("action", action)
  111. revise.setAttribute("target", target)
  112. feature.appendChild(revise)
  113. def show(self):
  114. if not os.path.exists(ChangeList.PATCH_XML):
  115. print ChangeList.PATCH_XML + " not exists. Use `make` to generate."
  116. return
  117. changelist = []
  118. revises = ET.parse(ChangeList.PATCH_XML).findall("feature/revise")
  119. for revise in revises:
  120. target = revise.attrib["target"]
  121. changelist.append(target)
  122. print "\n".join(changelist)
  123. if __name__ == "__main__":
  124. for arg in sys.argv:
  125. if arg in ("--make", "-m"):
  126. ChangeList(Config.AOSP_ROOT, Config.BOSP_ROOT, Config.PATCHALL_XML).make()
  127. sys.exit(0)
  128. elif arg in ("--show", "-s"):
  129. ChangeList(Config.AOSP_ROOT, Config.BOSP_ROOT, Config.PATCHALL_XML).show()
  130. sys.exit(0)
  131. print __doc__