PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/buildtools/ensure_gn_version.py

http://github.com/chromium/chromium
Python | 134 lines | 102 code | 15 blank | 17 comment | 10 complexity | d79aa7cdefc7eaa191df95672a2cc129 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, BSD-2-Clause, LGPL-2.1, MPL-2.0, 0BSD, EPL-1.0, MPL-2.0-no-copyleft-exception, GPL-2.0, BitTorrent-1.0, CPL-1.0, LGPL-3.0, Unlicense, BSD-3-Clause, CC0-1.0, JSON, MIT, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0
  1. #!/usr/bin/env python
  2. # Copyright 2019 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Ensure that CIPD fetched the right GN version.
  6. Due to crbug.com/944367, using cipd in gclient to fetch GN binaries
  7. may not always work right. This is a script that can be used as
  8. a backup method to force-install GN at the right revision, just in case.
  9. It should be used as a gclient hook alongside fetching GN via CIPD
  10. until we have a proper fix in place.
  11. TODO(crbug.com/944667): remove this script when it is no longer needed.
  12. """
  13. from __future__ import print_function
  14. import argparse
  15. import errno
  16. import io
  17. import os
  18. import re
  19. import stat
  20. import subprocess
  21. import sys
  22. try:
  23. import urllib2 as urllib
  24. except ImportError:
  25. import urllib.request as urllib
  26. import zipfile
  27. BUILDTOOLS_DIR = os.path.abspath(os.path.dirname(__file__))
  28. SRC_DIR = os.path.dirname(BUILDTOOLS_DIR)
  29. def ChmodGnFile(path_to_exe):
  30. """Makes the gn binary executable for all and writable for the user."""
  31. os.chmod(path_to_exe,
  32. stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | # This is 0o755.
  33. stat.S_IRGRP | stat.S_IXGRP |
  34. stat.S_IROTH | stat.S_IXOTH)
  35. def main():
  36. parser = argparse.ArgumentParser()
  37. parser.add_argument('version',
  38. help='CIPD "git_revision:XYZ" label for GN to sync to')
  39. args = parser.parse_args()
  40. if not args.version.startswith('git_revision:'):
  41. print('Unknown version format: %s' % args.version)
  42. return 2
  43. desired_revision = args.version[len('git_revision:'):]
  44. if sys.platform == 'darwin':
  45. platform, member, dest_dir = ('mac-amd64', 'gn', 'mac')
  46. elif sys.platform == 'win32':
  47. platform, member, dest_dir = ('windows-amd64', 'gn.exe', 'win')
  48. else:
  49. platform, member, dest_dir = ('linux-amd64', 'gn', 'linux64')
  50. path_to_exe = os.path.join(BUILDTOOLS_DIR, dest_dir, member)
  51. cmd = [path_to_exe, '--version']
  52. cmd_str = ' '.join(cmd)
  53. try:
  54. out = subprocess.check_output(cmd,
  55. stderr=subprocess.STDOUT,
  56. cwd=SRC_DIR).decode(errors='replace')
  57. except subprocess.CalledProcessError as e:
  58. print('`%s` returned %d:\n%s' % (cmd_str, e.returncode, e.output))
  59. return 1
  60. except OSError as e:
  61. if e.errno != errno.ENOENT:
  62. print('`%s` failed:\n%s' % (cmd_str, e.strerror))
  63. return 1
  64. # The tool doesn't exist, so redownload it.
  65. out = ''
  66. if out:
  67. current_revision_match = re.findall(r'\((.*)\)', out)
  68. if current_revision_match:
  69. current_revision = current_revision_match[0]
  70. if desired_revision.startswith(current_revision):
  71. # We're on the right version, so we're done.
  72. return 0
  73. print("`%s` returned '%s', which wasn't what we were expecting."
  74. % (cmd_str, out.strip()))
  75. print("Force-installing %s to update it." % desired_revision)
  76. url = 'https://chrome-infra-packages.appspot.com/dl/gn/gn/%s/+/%s' % (
  77. platform, args.version)
  78. try:
  79. zipdata = urllib.urlopen(url).read()
  80. except urllib.HTTPError as e:
  81. print('Failed to download the package from %s: %d %s' % (
  82. url, e.code, e.reason))
  83. return 1
  84. try:
  85. # Make the existing file writable so that we can overwrite it.
  86. ChmodGnFile(path_to_exe)
  87. except OSError as e:
  88. if e.errno != errno.ENOENT:
  89. print('Failed to make %s writable:\n%s\n' % (path_to_exe, e.strerror))
  90. return 1
  91. try:
  92. zf = zipfile.ZipFile(io.BytesIO(zipdata))
  93. zf.extract(member, os.path.join(BUILDTOOLS_DIR, dest_dir))
  94. except OSError as e:
  95. print('Failed to extract the binary:\n%s\n' % e.strerror)
  96. return 1
  97. except (zipfile.LargeZipFile, zipfile.BadZipfile) as e:
  98. print('Zip containing gn was corrupt:\n%s\n' % e)
  99. return 1
  100. try:
  101. ChmodGnFile(path_to_exe)
  102. except OSError as e:
  103. print('Failed to make %s executable:\n%s\n' % (path_to_exe, e.strerror))
  104. return 1
  105. return 0
  106. if __name__ == '__main__':
  107. sys.exit(main())