get_bugzilla_patches.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. from urllib3 import PoolManager
  2. import json
  3. import sys
  4. import re
  5. def get_patches(bugzillaID):
  6. http = PoolManager()
  7. # first find when the bug was fixed
  8. history = 'https://bugzilla.mozilla.org/rest/bug/{}/history'.format(
  9. bugzillaID)
  10. request = http.request('GET', history, retries=10)
  11. j = json.loads(request.data)
  12. times = [change['when'] for change in j['bugs'][0]['history']
  13. if "FIXED" in [c["added"] for c in change["changes"]]]
  14. # then look through all the fix comments for patch URLs
  15. comments = 'https://bugzilla.mozilla.org/rest/bug/{}/comment'.format(
  16. bugzillaID)
  17. request = http.request('GET', comments, retries=10)
  18. j = json.loads(request.data)
  19. urlregex = r'https?://hg\.mozilla\.org/(?:mozilla-central|releases/[^/]+)'\
  20. '/rev/[0-9a-f]+'
  21. fix_comments = [comment for comment in j['bugs'][bugzillaID]['comments']
  22. if comment['creation_time'] in times]
  23. for comment in fix_comments:
  24. for urlmatch in re.findall(urlregex, comment['text']):
  25. patch_url = urlmatch.replace('/rev/', '/raw-rev/')
  26. yield http.request('GET', patch_url, retries=10).data.decode(
  27. errors='ignore')
  28. def get_title_lines(bugzillaID):
  29. for patch in get_patches(bugzillaID):
  30. for line in patch.split('\n'):
  31. line = line.strip()
  32. if len(line) != 0 and line[0] != '#':
  33. yield line
  34. break
  35. def get_affected_files(bugzillaID):
  36. for patch in get_patches(bugzillaID):
  37. for line in patch.split('\n'):
  38. if len(line) > 5 and (
  39. line[:5] == '--- a' or
  40. line[:5] == '+++ b'):
  41. yield line[6:]
  42. def get_deleted_files(bugzillaID):
  43. fetch_next = False
  44. for patch in get_patches(bugzillaID):
  45. for line in patch.split('\n'):
  46. if len(line) >= 17 and \
  47. line[:17] == "deleted file mode" and \
  48. not fetch_next:
  49. fetch_next = True
  50. elif fetch_next:
  51. assert(line[:5] == '--- a')
  52. yield line[6:]
  53. fetch_next = False
  54. if __name__ == '__main__':
  55. command = sys.argv[1]
  56. bugzillaID = sys.argv[2]
  57. if command == 'titles':
  58. line_generator = get_title_lines(bugzillaID)
  59. elif command == 'files':
  60. line_generator = get_affected_files(bugzillaID)
  61. elif command == 'deleted':
  62. line_generator = get_deleted_files(bugzillaID)
  63. else:
  64. print("Bad command: " + command)
  65. sys.exit(1)
  66. for item in line_generator:
  67. print(item)