# Copyright (C) 2017-2021 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import re from webkitcorepy import Version from webkitpy.common.memoized import memoized PUBLIC_TABLE = 'public' INTERNAL_TABLE = 'internal' class VersionNameMap(object): # Allows apple_additions to define a custom mapping @staticmethod @memoized def map(platform=None): from webkitpy.port.config import apple_additions if apple_additions(): return apple_additions().version_name_mapping(platform) return VersionNameMap(platform=platform) def __init__(self, platform=None): if platform is None: from webkitpy.common.system.systemhost import SystemHost platform = SystemHost().platform self.mapping = {} self.default_system_platform = platform.os_name self.mapping[PUBLIC_TABLE] = { 'mac': { 'Leopard': Version(10, 5), 'Snow Leopard': Version(10, 6), 'Lion': Version(10, 7), 'Mountain Lion': Version(10, 8), 'Mavericks': Version(10, 9), 'Yosemite': Version(10, 10), 'El Capitan': Version(10, 11), 'Sierra': Version(10, 12), 'High Sierra': Version(10, 13), 'Mojave': Version(10, 14), 'Catalina': Version(10, 15), 'Big Sur': Version(11, 0), 'Monterey': Version(12, 0), 'Ventura': Version(13, 0), }, 'ios': self._automap_to_major_version('iOS', minimum=Version(10), maximum=Version(16)), 'tvos': self._automap_to_major_version('tvOS', minimum=Version(10), maximum=Version(16)), 'watchos': self._automap_to_major_version('watchOS', minimum=Version(1), maximum=Version(9)), 'win': { 'Win10': Version(10), '8.1': Version(6, 3), '8': Version(6, 2), '7sp0': Version(6, 1, 7600), 'Vista': Version(6), 'XP': Version(5, 1), }, # This entry avoids hitting the assert in mapping_for_platform() on Linux, # but otherwise shouldn't contain any useful key-value pairs. 'linux': {}, } # wincairo uses the same versions as Windows self.mapping[PUBLIC_TABLE]['wincairo'] = self.mapping[PUBLIC_TABLE]['win'] # FTW uses the same versions as Windows self.mapping[PUBLIC_TABLE]['ftw'] = self.mapping[PUBLIC_TABLE]['win'] @classmethod def _automap_to_major_version(cls, prefix, minimum=Version(1), maximum=Version(1)): result = {} assert minimum <= maximum for i in range((maximum.major + 1) - minimum.major): result['{} {}'.format(prefix, str(Version(minimum.major + i)))] = Version(minimum.major + i) return result def to_name(self, version, platform=None, table=PUBLIC_TABLE): closest_match = (None, None) for os_name, os_version in self.mapping_for_platform(platform, table).items(): if version == os_version: return os_name elif version in os_version: if closest_match[1] and closest_match[1] in os_version: continue closest_match = (os_name, os_version) return closest_match[0] def max_public_version(self, platform=None): found_max_version = None for os_name, os_version in self.mapping_for_platform(platform, PUBLIC_TABLE).items(): if os_version > found_max_version: found_max_version = os_version return found_max_version @staticmethod def strip_name_formatting(name): # major.minor.tiny should map to major if ' ' in name: try: name = '{}{}'.format(''.join(name.split(' ')[:-1]), Version.from_string(name.split(' ')[-1]).major) except ValueError: pass else: try: split = re.split(r'\d', name) name = '{}{}'.format(split[0], Version.from_string(name[(len(split) - 1):]).major) except ValueError: pass # Strip out any spaces, make everything lower-case result = name.replace(' ', '').lower() return result def from_name(self, name): # Exact match for _, map in self.mapping.items(): for os_name, os_map in map.items(): if name in os_map: return (os_name, os_map[name]) # It's not an exact match, let's try unifying formatting unformatted = self.strip_name_formatting(name) for _, map in self.mapping.items(): for os_name, os_map in map.items(): for version_name, version in os_map.items(): if self.strip_name_formatting(version_name) == unformatted: return (os_name, version) return (None, None) def names(self, platform=None, table=PUBLIC_TABLE): """return list of os_name for platform""" mapping = self.mapping_for_platform(platform, table) names = [os_name for os_name in mapping] return sorted(names, key=lambda os_name: mapping[os_name]) def mapping_for_platform(self, platform=None, table=PUBLIC_TABLE): # Alias macos to mac here. Adding a separate entry to the table # would cause from_name() to return either 'mac' or 'macos'. if platform == 'macos': platform = 'mac' """return proper os_name: os_version mapping for platform""" platform = self.default_system_platform if platform is None else platform return self.mapping.get(table, {}).get(platform, {})