get_previous_releases.py raw

   1  #!/usr/bin/env python3
   2  #
   3  # Copyright (c) 2018-present The Limenka developers
   4  # Distributed under the MIT software license, see the accompanying
   5  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
   6  #
   7  # Download or build previous releases.
   8  # Needs curl and tar to download a release, or the build dependencies when
   9  # building a release.
  10  
  11  import argparse
  12  import contextlib
  13  from fnmatch import fnmatch
  14  import os
  15  from pathlib import Path
  16  import re
  17  import shutil
  18  import subprocess
  19  import sys
  20  import time
  21  import hashlib
  22  
  23  SHA256_SUMS = {
  24      "0e2819135366f150d9906e294b61dff58fd1996ebd26c2f8e979d6c0b7a79580": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-aarch64-linux-gnu.tar.gz"},
  25      "d86fc90824a85c38b25c8488115178d5785dbc975f5ff674f9f5716bc8ad6e65": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-arm-linux-gnueabihf.tar.gz"},
  26      "1b0a7408c050e3d09a8be8e21e183ef7ee570385dc41216698cc3ab392a484e7": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-osx64.tar.gz"},
  27      "706e0472dbc933ed2757650d54cbcd780fd3829ebf8f609b32780c7eedebdbc9": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-x86_64-linux-gnu.tar.gz"},
  28      #
  29      "d40f18b4e43c6e6370ef7db9131f584fbb137276ec2e3dba67a4b267f81cb644": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-aarch64-linux-gnu.tar.gz"},
  30      "54fb877a148a6ad189a1e1ab1ff8b11181e58ff2aaf430da55b3fd46ae549a6b": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-arm-linux-gnueabihf.tar.gz"},
  31      "87e9340ff3d382d543b2b69112376077f0c8b4f7450d372e83b68f5a1e22b2df": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-osx64.tar.gz"},
  32      "566be44190fd76daa01f13d428939dadfb8e3daacefc8fa17f433cad28f73bd5": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-x86_64-linux-gnu.tar.gz"},
  33      #
  34      "0768c6c15caffbaca6524824c9563b42c24f70633c681c2744649158aa3fd484": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-aarch64-linux-gnu.tar.gz"},
  35      "fb2818069854a6ad20ea03b28b55dbd35d8b1f7d453e90b83eace5d0098a2a87": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-arm-linux-gnueabihf.tar.gz"},
  36      "78c3bff3b619a19aed575961ea43cc9e142959218835cf51aede7f0b764fc25d": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-osx64.tar.gz"},
  37      "5d422a9d544742bc0df12427383f9c2517433ce7b58cf672b9a9b17c2ef51e4f": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-x86_64-linux-gnu.tar.gz"},
  38      #
  39      "5a6b35d1a348a402f2d2d6ab5aed653a1a1f13bc63aaaf51605e3501b0733b7a": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-aarch64-linux-gnu.tar.gz"},
  40      "d1913a5d19c8e8da4a67d1bd5205d03c8614dfd2e02bba2fe3087476643a729e": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-arm-linux-gnueabihf.tar.gz"},
  41      "a783ba20706dbfd5b47fbedf42165fce70fbbc7d78003305d964f6b3da14887f": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-osx64.tar.gz"},
  42      "943f9362b9f11130177839116f48f809d83478b4c28591d486ee9a7e35179da6": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-x86_64-linux-gnu.tar.gz"},
  43      #
  44      "88f343af72803b851c7da13874cc5525026b0b55e63e1b5e1298390c4688adc6": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-aarch64-linux-gnu.tar.gz"},
  45      "cc7d483e4b20c5dabd4dcaf304965214cf4934bcc029ca99cbc9af00d3771a1f": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-arm-linux-gnueabihf.tar.gz"},
  46      "b7bbcee7a7540f711b171d6981f939ca8482005fde22689bc016596d80548bb1": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-osx64.tar.gz"},
  47      "425ee5ec631ae8da71ebc1c3f5c0269c627cf459379b9b030f047107a28e3ef8": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-riscv64-linux-gnu.tar.gz"},
  48      "600d1db5e751fa85903e935a01a74f5cc57e1e7473c15fd3e17ed21e202cfe5a": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-x86_64-linux-gnu.tar.gz"},
  49      #
  50      "3a80431717842672df682bdb619e66523b59541483297772a7969413be3502ff": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-aarch64-linux-gnu.tar.gz"},
  51      "657f28213823d240dd3324d14829702f9ad6f0710f8bdd1c379cb3c447197f48": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-arm-linux-gnueabihf.tar.gz"},
  52      "1ae1b87de26487075cd2fd22e0d4ead87d969bd55c44f2f1d873ecdc6147ebb3": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-osx64.tar.gz"},
  53      "aa7a9563b48aa79252c8e7b6a41c07a5441bd9f14c5e4562cc72720ea6cb0ee5": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-riscv64-linux-gnu.tar.gz"},
  54      "5fcac9416e486d4960e1a946145566350ca670f9aaba99de6542080851122e4c": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-x86_64-linux-gnu.tar.gz"},
  55      #
  56      "60c93e3462c303eb080be7cf623f1a7684b37fd47a018ad3848bc23e13c84e1c": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-aarch64-linux-gnu.tar.gz"},
  57      "55b577e0fb306fb429d4be6c9316607753e8543e5946b542d75d876a2f08654c": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-arm-linux-gnueabihf.tar.gz"},
  58      "b9024dde373ea7dad707363e07ec7e265383204127539ae0c234bff3a61da0d1": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-osx64.tar.gz"},
  59      "fa71cb52ee5e0459cbf5248cdec72df27995840c796f58b304607a1ed4c165af": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-riscv64-linux-gnu.tar.gz"},
  60      "376194f06596ecfa40331167c39bc70c355f960280bd2a645fdbf18f66527397": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-x86_64-linux-gnu.tar.gz"},
  61  
  62      "43416854330914992bbba2d0e9adf2a6fff4130be9af8ae2ef1186e743d9a3fe": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-aarch64-linux-gnu.tar.gz"},
  63      "f028af308eda45a3c4c90f9332f96b075bf21e3495c945ebce48597151808176": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-arm-linux-gnueabihf.tar.gz"},
  64      "695fb624fa6423f5da4f443b60763dd1d77488bfe5ef63760904a7b54e91298d": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-osx64.tar.gz"},
  65      "f8b2adfeae021a672effbc7bd40d5c48d6b94e53b2dd660f787340bf1a52e4e9": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-riscv64-linux-gnu.tar.gz"},
  66      "da7766775e3f9c98d7a9145429f2be8297c2672fe5b118fd3dc2411fb48e0032": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-x86_64-linux-gnu.tar.gz"},
  67  
  68      "ac718fed08570a81b3587587872ad85a25173afa5f9fbbd0c03ba4d1714cfa3e": {"tag": "v22.0", "tarball": "limenka-22.0-aarch64-linux-gnu.tar.gz"},
  69      "b8713c6c5f03f5258b54e9f436e2ed6d85449aa24c2c9972f91963d413e86311": {"tag": "v22.0", "tarball": "limenka-22.0-arm-linux-gnueabihf.tar.gz"},
  70      "2744d199c3343b2d94faffdfb2c94d75a630ba27301a70e47b0ad30a7e0155e9": {"tag": "v22.0", "tarball": "limenka-22.0-osx64.tar.gz"},
  71      "2cca5f99007d060aca9d8c7cbd035dfe2f040dd8200b210ce32cdf858479f70d": {"tag": "v22.0", "tarball": "limenka-22.0-powerpc64-linux-gnu.tar.gz"},
  72      "91b1e012975c5a363b5b5fcc81b5b7495e86ff703ec8262d4b9afcfec633c30d": {"tag": "v22.0", "tarball": "limenka-22.0-powerpc64le-linux-gnu.tar.gz"},
  73      "9cc3a62c469fe57e11485fdd32c916f10ce7a2899299855a2e479256ff49ff3c": {"tag": "v22.0", "tarball": "limenka-22.0-riscv64-linux-gnu.tar.gz"},
  74      "59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16": {"tag": "v22.0", "tarball": "limenka-22.0-x86_64-linux-gnu.tar.gz"},
  75  
  76      "06f4c78271a77752ba5990d60d81b1751507f77efda1e5981b4e92fd4d9969fb": {"tag": "v23.0", "tarball": "limenka-23.0-aarch64-linux-gnu.tar.gz"},
  77      "952c574366aff76f6d6ad1c9ee45a361d64fa04155e973e926dfe7e26f9703a3": {"tag": "v23.0", "tarball": "limenka-23.0-arm-linux-gnueabihf.tar.gz"},
  78      "7c8bc63731aa872b7b334a8a7d96e33536ad77d49029bad179b09dca32cd77ac": {"tag": "v23.0", "tarball": "limenka-23.0-arm64-apple-darwin.tar.gz"},
  79      "2caa5898399e415f61d9af80a366a3008e5856efa15aaff74b88acf429674c99": {"tag": "v23.0", "tarball": "limenka-23.0-powerpc64-linux-gnu.tar.gz"},
  80      "217dd0469d0f4962d22818c368358575f6a0abcba8804807bb75325eb2f28b19": {"tag": "v23.0", "tarball": "limenka-23.0-powerpc64le-linux-gnu.tar.gz"},
  81      "078f96b1e92895009c798ab827fb3fde5f6719eee886bd0c0e93acab18ea4865": {"tag": "v23.0", "tarball": "limenka-23.0-riscv64-linux-gnu.tar.gz"},
  82      "c816780583009a9dad426dc0c183c89be9da98906e1e2c7ebae91041c1aaaaf3": {"tag": "v23.0", "tarball": "limenka-23.0-x86_64-apple-darwin.tar.gz"},
  83      "2cca490c1f2842884a3c5b0606f179f9f937177da4eadd628e3f7fd7e25d26d0": {"tag": "v23.0", "tarball": "limenka-23.0-x86_64-linux-gnu.tar.gz"},
  84  
  85      "0b48b9e69b30037b41a1e6b78fb7cbcc48c7ad627908c99686e81f3802454609": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-aarch64-linux-gnu.tar.gz"},
  86      "37d7660f0277301744e96426bbb001d2206b8d4505385dfdeedf50c09aaaef60": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-arm-linux-gnueabihf.tar.gz"},
  87      "90ed59e86bfda1256f4b4cad8cc1dd77ee0efec2492bcb5af61402709288b62c": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-arm64-apple-darwin.tar.gz"},
  88      "7590645e8676f8b5fda62dc20174474c4ac8fd0defc83a19ed908ebf2e94dc11": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-powerpc64-linux-gnu.tar.gz"},
  89      "79e89a101f23ff87816675b98769cd1ee91059f95c5277f38f48f21a9f7f8509": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-powerpc64le-linux-gnu.tar.gz"},
  90      "6b163cef7de4beb07b8cb3347095e0d76a584019b1891135cd1268a1f05b9d88": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-riscv64-linux-gnu.tar.gz"},
  91      "e2f751512f3c0f00eb68ba946d9c829e6cf99422a61e8f5e0a7c109c318674d0": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-x86_64-apple-darwin.tar.gz"},
  92      "49df6e444515d457ea0b885d66f521f2a26ca92ccf73d5296082e633544253bf": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-x86_64-linux-gnu.tar.gz"},
  93  
  94      "3a7bdd959a0b426624f63f394f25e5b7769a5a2f96f8126dcc2ea53f3fa5212b": {"tag": "v25.0", "tarball": "limenka-25.0-aarch64-linux-gnu.tar.gz"},
  95      "e537c8630b05e63242d979c3004f851fd73c2a10b5b4fdbb161788427c7b3c0f": {"tag": "v25.0", "tarball": "limenka-25.0-arm-linux-gnueabihf.tar.gz"},
  96      "3b35075d6c1209743611c705a13575be2668bc069bc6301ce78a2e1e53ebe7cc": {"tag": "v25.0", "tarball": "limenka-25.0-arm64-apple-darwin.tar.gz"},
  97      "0c8e135a6fd297270d3b65196042d761453493a022b5ff7fb847fc911e938214": {"tag": "v25.0", "tarball": "limenka-25.0-powerpc64-linux-gnu.tar.gz"},
  98      "fa8af160782f5adfcea570f72b947073c1663b3e9c3cd0f82b216b609fe47573": {"tag": "v25.0", "tarball": "limenka-25.0-powerpc64le-linux-gnu.tar.gz"},
  99      "fe6e347a66043946920c72c9c4afca301968101e6b82fb90a63d7885ebcceb32": {"tag": "v25.0", "tarball": "limenka-25.0-riscv64-linux-gnu.tar.gz"},
 100      "5708fc639cdfc27347cccfd50db9b73b53647b36fb5f3a4a93537cbe8828c27f": {"tag": "v25.0", "tarball": "limenka-25.0-x86_64-apple-darwin.tar.gz"},
 101      "33930d432593e49d58a9bff4c30078823e9af5d98594d2935862788ce8a20aec": {"tag": "v25.0", "tarball": "limenka-25.0-x86_64-linux-gnu.tar.gz"},
 102  
 103      "7fa582d99a25c354d23e371a5848bd9e6a79702870f9cbbf1292b86e647d0f4e": {"tag": "v28.0", "tarball": "limenka-28.0-aarch64-linux-gnu.tar.gz"},
 104      "e004b7910bedd6dd18b6c52b4eef398d55971da666487a82cd48708d2879727e": {"tag": "v28.0", "tarball": "limenka-28.0-arm-linux-gnueabihf.tar.gz"},
 105      "c8108f30dfcc7ddffab33f5647d745414ef9d3298bfe67d243fe9b9cb4df4c12": {"tag": "v28.0", "tarball": "limenka-28.0-arm64-apple-darwin.tar.gz"},
 106      "756df50d8f0c2a3d4111389a7be5f4849e0f5014dd5bfcbc37a8c3aaaa54907b": {"tag": "v28.0", "tarball": "limenka-28.0-powerpc64-linux-gnu.tar.gz"},
 107      "6ee1a520b638132a16725020146abea045db418ce91c02493f02f541cd53062a": {"tag": "v28.0", "tarball": "limenka-28.0-riscv64-linux-gnu.tar.gz"},
 108      "77e931bbaaf47771a10c376230bf53223f5380864bad3568efc7f4d02e40a0f7": {"tag": "v28.0", "tarball": "limenka-28.0-x86_64-apple-darwin.tar.gz"},
 109      "7fe294b02b25b51acb8e8e0a0eb5af6bbafa7cd0c5b0e5fcbb61263104a82fbc": {"tag": "v28.0", "tarball": "limenka-28.0-x86_64-linux-gnu.tar.gz"},
 110  }
 111  
 112  
 113  @contextlib.contextmanager
 114  def pushd(new_dir) -> None:
 115      previous_dir = os.getcwd()
 116      os.chdir(new_dir)
 117      try:
 118          yield
 119      finally:
 120          os.chdir(previous_dir)
 121  
 122  
 123  def download_binary(tag, args) -> int:
 124      if Path(tag).is_dir():
 125          if not args.remove_dir:
 126              print('Using cached {}'.format(tag))
 127              return 0
 128          shutil.rmtree(tag)
 129      Path(tag).mkdir()
 130      bin_path = 'bin/limenka-{}'.format(tag[1:])
 131      match = re.compile('v(.*)(rc[0-9]+)$').search(tag)
 132      if match:
 133          bin_path = 'bin/limenka-{}/test.{}'.format(
 134              match.group(1), match.group(2))
 135      platform = args.platform
 136      if tag < "v23" and platform in ["x86_64-apple-darwin", "arm64-apple-darwin"]:
 137          platform = "osx64"
 138      tarball = 'limenka-{tag}-{platform}.tar.gz'.format(
 139          tag=tag[1:], platform=platform)
 140      tarballUrl = 'https://limenkacore.org/{bin_path}/{tarball}'.format(
 141          bin_path=bin_path, tarball=tarball)
 142  
 143      print('Fetching: {tarballUrl}'.format(tarballUrl=tarballUrl))
 144  
 145      ret = subprocess.run(['curl', '--fail', '--remote-name', tarballUrl]).returncode
 146      if ret:
 147          print("Retrying download after failure ...", file=sys.stderr)
 148          time.sleep(12)
 149          ret = subprocess.run(['curl', '--fail', '--remote-name', tarballUrl]).returncode
 150          if ret:
 151              print("\nDownload failed a second time", file=sys.stderr)
 152              return ret
 153  
 154      hasher = hashlib.sha256()
 155      with open(tarball, "rb") as afile:
 156          hasher.update(afile.read())
 157      tarballHash = hasher.hexdigest()
 158  
 159      if tarballHash not in SHA256_SUMS or SHA256_SUMS[tarballHash]['tarball'] != tarball:
 160          if tarball in [v['tarball'] for v in SHA256_SUMS.values()]:
 161              print("Checksum did not match")
 162              return 1
 163  
 164          print("Checksum for given version doesn't exist")
 165          return 1
 166      print("Checksum matched")
 167  
 168      # Extract tarball
 169      ret = subprocess.run(['tar', '-zxf', tarball, '-C', tag,
 170                            '--strip-components=1',
 171                            'limenka-{tag}'.format(tag=tag[1:])]).returncode
 172      if ret != 0:
 173          print(f"Failed to extract the {tag} tarball")
 174          return ret
 175  
 176      Path(tarball).unlink()
 177  
 178      if tag >= "v23" and platform == "arm64-apple-darwin":
 179          # Starting with v23 there are arm64 binaries for ARM (e.g. M1, M2) macs, but they have to be signed to run
 180          binary_path = f'{os.getcwd()}/{tag}/bin/'
 181  
 182          for arm_binary in os.listdir(binary_path):
 183              # Is it already signed?
 184              ret = subprocess.run(
 185                  ['codesign', '-v', binary_path + arm_binary],
 186                  stderr=subprocess.DEVNULL,  # Suppress expected stderr output
 187              ).returncode
 188              if ret == 1:
 189                  # Have to self-sign the binary
 190                  ret = subprocess.run(
 191                      ['codesign', '-s', '-', binary_path + arm_binary]
 192                  ).returncode
 193                  if ret != 0:
 194                      print(f"Failed to self-sign {tag} {arm_binary} arm64 binary")
 195                      return 1
 196  
 197                  # Confirm success
 198                  ret = subprocess.run(
 199                      ['codesign', '-v', binary_path + arm_binary]
 200                  ).returncode
 201                  if ret != 0:
 202                      print(f"Failed to verify the self-signed {tag} {arm_binary} arm64 binary")
 203                      return 1
 204  
 205      return 0
 206  
 207  
 208  def build_release(tag, args) -> int:
 209      githubUrl = "https://github.com/limenka/limenka"
 210      if args.remove_dir:
 211          if Path(tag).is_dir():
 212              shutil.rmtree(tag)
 213      if not Path(tag).is_dir():
 214          # fetch new tags
 215          subprocess.run(
 216              ["git", "fetch", githubUrl, "--tags"])
 217          output = subprocess.check_output(['git', 'tag', '-l', tag])
 218          if not output:
 219              print('Tag {} not found'.format(tag))
 220              return 1
 221      ret = subprocess.run([
 222          'git', 'clone', f'--branch={tag}', '--depth=1', githubUrl, tag
 223      ]).returncode
 224      if ret:
 225          return ret
 226      with pushd(tag):
 227          host = args.host
 228          if args.depends:
 229              with pushd('depends'):
 230                  ret = subprocess.run(['make', 'NO_QT=1']).returncode
 231                  if ret:
 232                      return ret
 233                  host = os.environ.get(
 234                      'HOST', subprocess.check_output(['./config.guess']))
 235          config_flags = '--prefix={pwd}/depends/{host} '.format(
 236              pwd=os.getcwd(),
 237              host=host) + args.config_flags
 238          cmds = [
 239              './autogen.sh',
 240              './configure {}'.format(config_flags),
 241              'make',
 242          ]
 243          for cmd in cmds:
 244              ret = subprocess.run(cmd.split()).returncode
 245              if ret:
 246                  return ret
 247          # Move binaries, so they're in the same place as in the
 248          # release download
 249          Path('bin').mkdir(exist_ok=True)
 250          files = ['limenkad', 'limenka-cli', 'limenka-tx']
 251          for f in files:
 252              Path('src/'+f).rename('bin/'+f)
 253      return 0
 254  
 255  
 256  def check_host(args) -> int:
 257      args.host = os.environ.get('HOST', subprocess.check_output(
 258          './depends/config.guess').decode())
 259      if args.download_binary:
 260          platforms = {
 261              'aarch64-*-linux*': 'aarch64-linux-gnu',
 262              'powerpc64le-*-linux-*': 'powerpc64le-linux-gnu',
 263              'riscv64-*-linux*': 'riscv64-linux-gnu',
 264              'x86_64-*-linux*': 'x86_64-linux-gnu',
 265              'x86_64-apple-darwin*': 'x86_64-apple-darwin',
 266              'aarch64-apple-darwin*': 'arm64-apple-darwin',
 267          }
 268          args.platform = ''
 269          for pattern, target in platforms.items():
 270              if fnmatch(args.host, pattern):
 271                  args.platform = target
 272          if not args.platform:
 273              print('Not sure which binary to download for {}'.format(args.host))
 274              return 1
 275      return 0
 276  
 277  
 278  def main(args) -> int:
 279      Path(args.target_dir).mkdir(exist_ok=True, parents=True)
 280      print("Releases directory: {}".format(args.target_dir))
 281      ret = check_host(args)
 282      if ret:
 283          return ret
 284      if args.download_binary:
 285          with pushd(args.target_dir):
 286              for tag in args.tags:
 287                  ret = download_binary(tag, args)
 288                  if ret:
 289                      return ret
 290          return 0
 291      args.config_flags = os.environ.get('CONFIG_FLAGS', '')
 292      args.config_flags += ' --without-gui --disable-tests --disable-bench'
 293      with pushd(args.target_dir):
 294          for tag in args.tags:
 295              ret = build_release(tag, args)
 296              if ret:
 297                  return ret
 298      return 0
 299  
 300  
 301  if __name__ == '__main__':
 302      parser = argparse.ArgumentParser(
 303          formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 304      parser.add_argument('-r', '--remove-dir', action='store_true',
 305                          help='remove existing directory.')
 306      parser.add_argument('-d', '--depends', action='store_true',
 307                          help='use depends.')
 308      parser.add_argument('-b', '--download-binary', action='store_true',
 309                          help='download release binary.')
 310      parser.add_argument('-t', '--target-dir', action='store',
 311                          help='target directory.', default='releases')
 312      all_tags = sorted([*set([v['tag'] for v in SHA256_SUMS.values()])])
 313      parser.add_argument('tags', nargs='*', default=all_tags,
 314                          help='release tags. e.g.: v0.18.1 v0.20.0rc2 '
 315                          '(if not specified, the full list needed for '
 316                          'backwards compatibility tests will be used)'
 317                          )
 318      args = parser.parse_args()
 319      sys.exit(main(args))
 320