import argparse
from collections import namedtuple
_PACKAGE_NAMES = {
'CHROME': 0,
'CHROME_MODERN': 10,
'MONOCHROME': 20,
'TRICHROME': 30,
'TRICHROME_BETA': 40,
'TRICHROME_AUTO': 50,
'TRICHROME_DESKTOP': 60,
'CHROME_DESKTOP': 70,
'CHROME_DESKTOP_BETA': 80,
'WEBVIEW_STABLE': 0,
'WEBVIEW_BETA': 10,
'WEBVIEW_DEV': 20,
'WEBVIEW_AUTO': 70,
'WEBVIEW_DESKTOP': 80
}
_NEXT_BUILD_VERSION_CODE_DIFF = 50000
_APKS = {
'32': [
('CHROME', 'CHROME', '32'),
('CHROME_MODERN', 'CHROME_MODERN', '32'),
('MONOCHROME', 'MONOCHROME', '32'),
('TRICHROME', 'TRICHROME', '32'),
('TRICHROME_AUTO', 'TRICHROME_AUTO', '32'),
('TRICHROME_BETA', 'TRICHROME_BETA', '32'),
('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '32'),
('WEBVIEW_BETA', 'WEBVIEW_BETA', '32'),
('WEBVIEW_DEV', 'WEBVIEW_DEV', '32'),
('WEBVIEW_AUTO', 'WEBVIEW_AUTO', '32'),
],
'64': [
('CHROME', 'CHROME', '64'),
('CHROME_MODERN', 'CHROME_MODERN', '64'),
('MONOCHROME', 'MONOCHROME', '64'),
('TRICHROME', 'TRICHROME', '64'),
('TRICHROME_AUTO', 'TRICHROME_AUTO', '64'),
('TRICHROME_BETA', 'TRICHROME_BETA', '64'),
('TRICHROME_DESKTOP', 'TRICHROME_DESKTOP', '64'),
('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '64'),
('WEBVIEW_BETA', 'WEBVIEW_BETA', '64'),
('WEBVIEW_DEV', 'WEBVIEW_DEV', '64'),
('WEBVIEW_AUTO', 'WEBVIEW_AUTO', '64'),
('WEBVIEW_DESKTOP', 'WEBVIEW_DESKTOP', '64'),
],
'hybrid': [
('CHROME', 'CHROME', '64_32'),
('CHROME_HIGH', 'CHROME', '64'),
('CHROME_HIGH_BETA', 'CHROME_MODERN', '64'),
('CHROME_32', 'CHROME', '32'),
('CHROME_MODERN', 'CHROME_MODERN', '64'),
('MONOCHROME', 'MONOCHROME', '32_64'),
('MONOCHROME_32', 'MONOCHROME', '32'),
('MONOCHROME_32_64', 'MONOCHROME', '32_64'),
('MONOCHROME_64_32', 'MONOCHROME', '64_32'),
('MONOCHROME_64', 'MONOCHROME', '64'),
('TRICHROME', 'TRICHROME', '32_64'),
('TRICHROME_32', 'TRICHROME', '32'),
('TRICHROME_32_64', 'TRICHROME', '32_64'),
('TRICHROME_64_32', 'TRICHROME', '64_32'),
('TRICHROME_64_32_HIGH', 'TRICHROME', '64_32_high'),
('TRICHROME_64', 'TRICHROME', '64'),
('TRICHROME_AUTO', 'TRICHROME_AUTO', '32_64'),
('TRICHROME_AUTO_32', 'TRICHROME_AUTO', '32'),
('TRICHROME_AUTO_32_64', 'TRICHROME_AUTO', '32_64'),
('TRICHROME_AUTO_64', 'TRICHROME_AUTO', '64'),
('TRICHROME_AUTO_64_32', 'TRICHROME_AUTO', '64_32'),
('TRICHROME_AUTO_64_32_HIGH', 'TRICHROME_AUTO', '64_32_high'),
('TRICHROME_BETA', 'TRICHROME_BETA', '32_64'),
('TRICHROME_32_BETA', 'TRICHROME_BETA', '32'),
('TRICHROME_32_64_BETA', 'TRICHROME_BETA', '32_64'),
('TRICHROME_64_32_BETA', 'TRICHROME_BETA', '64_32'),
('TRICHROME_64_32_HIGH_BETA', 'TRICHROME_BETA', '64_32_high'),
('TRICHROME_DESKTOP_64', 'TRICHROME_DESKTOP', '64'),
('TRICHROME_64_BETA', 'TRICHROME_BETA', '64'),
('CHROME_DESKTOP', 'CHROME_DESKTOP', '64'),
('CHROME_DESKTOP_BETA', 'CHROME_DESKTOP_BETA', '64'),
('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '32_64'),
('WEBVIEW_32_STABLE', 'WEBVIEW_STABLE', '32'),
('WEBVIEW_32_64_STABLE', 'WEBVIEW_STABLE', '32_64'),
('WEBVIEW_64_STABLE', 'WEBVIEW_STABLE', '64'),
('WEBVIEW_64_32_STABLE', 'WEBVIEW_STABLE', '64_32'),
('WEBVIEW_64_32_HIGH_STABLE', 'WEBVIEW_STABLE', '64_32_high'),
('WEBVIEW_BETA', 'WEBVIEW_BETA', '32_64'),
('WEBVIEW_32_BETA', 'WEBVIEW_BETA', '32'),
('WEBVIEW_32_64_BETA', 'WEBVIEW_BETA', '32_64'),
('WEBVIEW_64_BETA', 'WEBVIEW_BETA', '64'),
('WEBVIEW_64_32_BETA', 'WEBVIEW_BETA', '64_32'),
('WEBVIEW_64_32_HIGH_BETA', 'WEBVIEW_BETA', '64_32_high'),
('WEBVIEW_DEV', 'WEBVIEW_DEV', '32_64'),
('WEBVIEW_32_DEV', 'WEBVIEW_DEV', '32'),
('WEBVIEW_64_DEV', 'WEBVIEW_DEV', '64'),
('WEBVIEW_64_32_DEV', 'WEBVIEW_DEV', '64_32'),
('WEBVIEW_AUTO', 'WEBVIEW_AUTO', '32_64'),
('WEBVIEW_AUTO_32', 'WEBVIEW_AUTO', '32'),
('WEBVIEW_AUTO_32_64', 'WEBVIEW_AUTO', '32_64'),
('WEBVIEW_AUTO_64', 'WEBVIEW_AUTO', '64'),
('WEBVIEW_AUTO_64_32', 'WEBVIEW_AUTO', '64_32'),
('WEBVIEW_AUTO_64_32_HIGH', 'WEBVIEW_AUTO', '64_32_high'),
('WEBVIEW_DESKTOP_64', 'WEBVIEW_DESKTOP', '64'),
]
}
_ARCH_TO_MFG_AND_BITNESS = {
'arm': ('arm', '32'),
'arm64': ('arm', 'hybrid'),
'riscv64': ('arm', '64'),
'x86': ('intel', '32'),
'x64': ('intel', 'hybrid'),
}
ARCH_CHOICES = _ARCH_TO_MFG_AND_BITNESS.keys()
def _GetAbisToDigitMask(build_number, patch_number):
use_new_scheme = (build_number >= 5750
or (build_number == 5672 and patch_number >= 176)
or (build_number == 5735 and patch_number >= 53))
if use_new_scheme:
return {
'arm': {
'32': 0,
'32_64': 1,
'64_32': 2,
'64_32_high': 3,
'64_high': 4,
'64': 4,
},
'intel': {
'32': 6,
'32_64': 7,
'64_32': 8,
'64': 9,
},
}
return {
'arm': {
'32': 0,
'32_64': 3,
'64_32': 4,
'64': 5,
'64_32_high': 9,
},
'intel': {
'32': 1,
'32_64': 6,
'64_32': 7,
'64': 8,
},
}
VersionCodeComponents = namedtuple('VersionCodeComponents', [
'build_number',
'patch_number',
'package_name',
'abi',
'is_next_build',
])
def TranslateVersionCode(version_code, is_webview=False):
if len(version_code) == 9:
build_number = int(version_code[:4])
else:
build_number = int(version_code[:5])
is_next_build = False
patch_number_plus_extra = int(version_code[-5:])
if patch_number_plus_extra >= _NEXT_BUILD_VERSION_CODE_DIFF:
is_next_build = True
patch_number_plus_extra -= _NEXT_BUILD_VERSION_CODE_DIFF
patch_number = patch_number_plus_extra // 100
if build_number >= 3992:
abi_digit = int(version_code[-1])
package_digit = int(version_code[-2])
else:
abi_digit = int(version_code[-2])
package_digit = int(version_code[-1])
if build_number < 4844 and package_digit >= 5:
is_next_build = True
package_digit -= 5
package_name = None
for package, number in _PACKAGE_NAMES.items():
if number == package_digit * 10:
if is_webview == ('WEBVIEW' in package):
package_name = package
break
if not package_name:
raise Error(f'Unable to match package with package_digit={package_digit} '
f'and is_webview={is_webview}')
for arch, bitness_to_number in (_GetAbisToDigitMask(build_number,
patch_number).items()):
for bitness, number in bitness_to_number.items():
if abi_digit == number:
abi = arch if arch != 'intel' else 'x86'
if bitness != '32':
abi += '_' + bitness
break
return VersionCodeComponents(build_number, patch_number, package_name, abi,
is_next_build)
def GenerateVersionCodes(build_number, patch_number, arch):
base_version_code = (build_number * 1000 + patch_number) * 100
mfg, bitness = _ARCH_TO_MFG_AND_BITNESS[arch]
version_codes = {}
abi_to_digit_mask = _GetAbisToDigitMask(build_number, patch_number)
for apk, package, abis in _APKS[bitness]:
if abis == '64_32_high' and arch != 'arm64':
continue
abi_part = abi_to_digit_mask[mfg][abis]
package_part = _PACKAGE_NAMES[package]
version_code_name = apk + '_VERSION_CODE'
version_code_val = base_version_code + package_part + abi_part
version_codes[version_code_name] = str(version_code_val)
return version_codes
def main():
parser = argparse.ArgumentParser(description='Parses version codes.')
g1 = parser.add_argument_group('To Generate Version Name')
g1.add_argument('--version-code', help='Version code (e.g. 529700010).')
g1.add_argument('--webview',
action='store_true',
help='Whether this is a webview version code.')
g2 = parser.add_argument_group('To Generate Version Code')
g2.add_argument('--version-name', help='Version name (e.g. 124.0.6355.0).')
g2.add_argument('--arch',
choices=ARCH_CHOICES,
help='Set which cpu architecture the build is for.')
args = parser.parse_args()
if args.version_code:
print(TranslateVersionCode(args.version_code, is_webview=args.webview))
elif args.version_name:
if not args.arch:
parser.error('Required --arch')
_, _, build, patch = args.version_name.split('.')
values = GenerateVersionCodes(int(build), int(patch), args.arch)
for k, v in values.items():
print(f'{k}={v}')
else:
parser.print_help()
if __name__ == '__main__':
main()