update_tzdata.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!/usr/bin/env python
  2. import glob
  3. import hashlib
  4. import os
  5. import re
  6. import shutil
  7. import string
  8. import subprocess
  9. import sys
  10. import tarfile
  11. import tempfile
  12. import urllib2
  13. def create_cmakelists(zoneinfo_dir):
  14. tz_to_hash = {}
  15. hash_to_content = {}
  16. total_size = 0
  17. for dirpath, _, filenames in os.walk(zoneinfo_dir):
  18. for fn in filenames:
  19. tz_file_name = os.path.join(dirpath, fn)
  20. with open(tz_file_name) as f:
  21. tz_content = f.read()
  22. if not tz_content.startswith('TZif'):
  23. continue
  24. tz_hash = hashlib.md5(tz_content).hexdigest()
  25. tz_name = tz_file_name.replace(zoneinfo_dir, '').lstrip('/')
  26. tz_to_hash[tz_name] = tz_hash
  27. hash_to_content[tz_hash] = tz_content
  28. total_size += len(tz_content)
  29. print 'Total data size in bytes:', total_size
  30. generated_dir = 'generated'
  31. if not os.path.isdir(generated_dir):
  32. os.mkdir(generated_dir)
  33. for tz_hash, tz_content in hash_to_content.iteritems():
  34. with open(os.path.join(generated_dir, tz_hash), 'w') as f:
  35. f.write(tz_content)
  36. yamake_template = (
  37. 'RESOURCE(\n'
  38. '{}\n'
  39. ')'
  40. )
  41. resources = '\n'.join(' generated/{} /cctz/tzdata/{}'.format(tz_hash, tz_name) for tz_name, tz_hash in sorted(tz_to_hash.iteritems()))
  42. all_hashes = set(tz_to_hash.values())
  43. hash_pattern = os.path.join('generated', '[{}]'.format(string.hexdigits) * 32)
  44. for fn in glob.glob(hash_pattern):
  45. cmd = 'add' if os.path.basename(fn) in all_hashes else 'rm'
  46. subprocess.check_call(['arc', cmd, fn])
  47. with open('ya.make.resources', 'w') as f:
  48. print >>f, yamake_template.format(resources)
  49. def get_latest_iana_version():
  50. index_html = urllib2.urlopen('http://www.iana.org/time-zones').read()
  51. version_match = re.search('<a href="[^"]*">tzdata(.*).tar.gz</a>', index_html)
  52. if not version_match:
  53. raise Exception('Failed to determine the latest tzdata version')
  54. return version_match.group(1)
  55. def get_current_version():
  56. try:
  57. with open('VERSION') as f:
  58. return f.read()
  59. except:
  60. return 0
  61. def prepare_tzdata(version):
  62. temp_dir = tempfile.mkdtemp()
  63. try:
  64. for file_type in ('data', 'code'):
  65. file_name = 'tz{}{}.tar.gz'.format(file_type, version)
  66. full_url = 'http://www.iana.org/time-zones/repository/releases/{}'.format(file_name)
  67. print 'Downloading {}'.format(full_url)
  68. local_file_name = os.path.join(temp_dir, file_name)
  69. with open(local_file_name, 'w') as f:
  70. f.write(urllib2.urlopen(full_url).read())
  71. print 'Extracting {}'.format(local_file_name)
  72. with tarfile.open(local_file_name) as f:
  73. f.extractall(path=temp_dir)
  74. print 'Converting tzdata to binary format'
  75. subprocess.check_call(['make', '-s', '-C', temp_dir, 'TOPDIR={}'.format(temp_dir), 'install'])
  76. print 'Preparing ya.make.resources'
  77. zoneinfo_dir = os.path.join(temp_dir, 'usr', 'share', 'zoneinfo')
  78. create_cmakelists(zoneinfo_dir)
  79. finally:
  80. shutil.rmtree(temp_dir)
  81. def main():
  82. current_version, latest_version = get_current_version(), get_latest_iana_version()
  83. print 'The current version of tzdata is {}'.format(current_version)
  84. print 'The latest version of tzdata on the IANA site is {}'.format(latest_version)
  85. if current_version == latest_version:
  86. print 'You already have the latest version'
  87. return
  88. print 'Updating from {} to {}'.format(current_version, latest_version)
  89. prepare_tzdata(latest_version)
  90. with open('VERSION', 'w') as f:
  91. f.write(latest_version)
  92. print 'All good! Now make sure the tests pass, and run this:'
  93. print 'arc add VERSION update_tzdata.py ya.make.resources'
  94. print 'arc co -b tzdata.{}'.format(latest_version)
  95. print 'arc ci . -m "Updated tzdata from {} to {}"'.format(current_version, latest_version)
  96. if __name__ == '__main__':
  97. main()