(raulenrique) | dfdda47 | 2018-06-04 12:02:29 -0700 | [diff] [blame] | 1 | # Copyright (C) 2018 The Android Open Source Project |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | # you may not use this file except in compliance with the License. |
| 5 | # You may obtain a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. |
| 14 | """Helper functions for updaters.""" |
| 15 | |
| 16 | import os |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 17 | import re |
(raulenrique) | dfdda47 | 2018-06-04 12:02:29 -0700 | [diff] [blame] | 18 | import subprocess |
| 19 | import sys |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 20 | from pathlib import Path |
| 21 | from typing import List, Tuple, Type |
| 22 | |
| 23 | from base_updater import Updater |
ThiƩbaud Weksteen | 4ac289b | 2020-09-28 15:23:29 +0200 | [diff] [blame] | 24 | # pylint: disable=import-error |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 25 | import metadata_pb2 # type: ignore |
(raulenrique) | dfdda47 | 2018-06-04 12:02:29 -0700 | [diff] [blame] | 26 | |
| 27 | |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 28 | def create_updater(metadata: metadata_pb2.MetaData, proj_path: Path, |
| 29 | updaters: List[Type[Updater]]) -> Updater: |
(raulenrique) | dfdda47 | 2018-06-04 12:02:29 -0700 | [diff] [blame] | 30 | """Creates corresponding updater object for a project. |
| 31 | |
| 32 | Args: |
| 33 | metadata: Parsed proto for METADATA file. |
| 34 | proj_path: Absolute path for the project. |
| 35 | |
| 36 | Returns: |
| 37 | An updater object. |
| 38 | |
| 39 | Raises: |
| 40 | ValueError: Occurred when there's no updater for all urls. |
| 41 | """ |
| 42 | for url in metadata.third_party.url: |
Haibo Huang | 329e681 | 2020-05-29 14:12:20 -0700 | [diff] [blame] | 43 | for updater_cls in updaters: |
| 44 | updater = updater_cls(proj_path, url, metadata.third_party.version) |
| 45 | if updater.is_supported_url(): |
| 46 | return updater |
(raulenrique) | dfdda47 | 2018-06-04 12:02:29 -0700 | [diff] [blame] | 47 | |
| 48 | raise ValueError('No supported URL.') |
| 49 | |
| 50 | |
Joel Galenson | 40a5a4a | 2021-05-20 09:50:44 -0700 | [diff] [blame] | 51 | def replace_package(source_dir, target_dir, temp_file=None) -> None: |
(raulenrique) | dfdda47 | 2018-06-04 12:02:29 -0700 | [diff] [blame] | 52 | """Invokes a shell script to prepare and update a project. |
| 53 | |
| 54 | Args: |
| 55 | source_dir: Path to the new downloaded and extracted package. |
| 56 | target_dir: The path to the project in Android source tree. |
| 57 | """ |
| 58 | |
| 59 | print('Updating {} using {}.'.format(target_dir, source_dir)) |
Haibo Huang | 329e681 | 2020-05-29 14:12:20 -0700 | [diff] [blame] | 60 | script_path = os.path.join(os.path.dirname(sys.argv[0]), |
| 61 | 'update_package.sh') |
Joel Galenson | 40a5a4a | 2021-05-20 09:50:44 -0700 | [diff] [blame] | 62 | subprocess.check_call(['bash', script_path, source_dir, target_dir, |
| 63 | "" if temp_file is None else temp_file]) |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 64 | |
Haibo Huang | 329e681 | 2020-05-29 14:12:20 -0700 | [diff] [blame] | 65 | |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 66 | VERSION_SPLITTER_PATTERN: str = r'[\.\-_]' |
| 67 | VERSION_PATTERN: str = (r'^(?P<prefix>[^\d]*)' + r'(?P<version>\d+(' + |
| 68 | VERSION_SPLITTER_PATTERN + r'\d+)*)' + |
| 69 | r'(?P<suffix>.*)$') |
| 70 | VERSION_RE: re.Pattern = re.compile(VERSION_PATTERN) |
| 71 | VERSION_SPLITTER_RE: re.Pattern = re.compile(VERSION_SPLITTER_PATTERN) |
| 72 | |
| 73 | ParsedVersion = Tuple[List[int], str, str] |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 74 | |
| 75 | |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 76 | def _parse_version(version: str) -> ParsedVersion: |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 77 | match = VERSION_RE.match(version) |
| 78 | if match is None: |
| 79 | raise ValueError('Invalid version.') |
| 80 | try: |
Haibo Huang | 329e681 | 2020-05-29 14:12:20 -0700 | [diff] [blame] | 81 | prefix, version, suffix = match.group('prefix', 'version', 'suffix') |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 82 | versions = [int(v) for v in VERSION_SPLITTER_RE.split(version)] |
| 83 | return (versions, str(prefix), str(suffix)) |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 84 | except IndexError: |
ThiƩbaud Weksteen | 4ac289b | 2020-09-28 15:23:29 +0200 | [diff] [blame] | 85 | # pylint: disable=raise-missing-from |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 86 | raise ValueError('Invalid version.') |
| 87 | |
| 88 | |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 89 | def _match_and_get_version(old_ver: ParsedVersion, |
| 90 | version: str) -> Tuple[bool, bool, List[int]]: |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 91 | try: |
Haibo Huang | 3ffcec1 | 2020-04-09 15:35:57 -0700 | [diff] [blame] | 92 | new_ver = _parse_version(version) |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 93 | except ValueError: |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 94 | return (False, False, []) |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 95 | |
Haibo Huang | 3ffcec1 | 2020-04-09 15:35:57 -0700 | [diff] [blame] | 96 | right_format = (new_ver[1:] == old_ver[1:]) |
| 97 | right_length = len(new_ver[0]) == len(old_ver[0]) |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 98 | |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 99 | return (right_format, right_length, new_ver[0]) |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 100 | |
| 101 | |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 102 | def get_latest_version(current_version: str, version_list: List[str]) -> str: |
Haibo Huang | cd2c612 | 2018-09-04 14:24:20 -0700 | [diff] [blame] | 103 | """Gets the latest version name from a list of versions. |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 104 | |
Haibo Huang | cd2c612 | 2018-09-04 14:24:20 -0700 | [diff] [blame] | 105 | The new version must have the same prefix and suffix with old version. |
| 106 | If no matched version is newer, current version name will be returned. |
| 107 | """ |
Haibo Huang | 3ffcec1 | 2020-04-09 15:35:57 -0700 | [diff] [blame] | 108 | parsed_current_ver = _parse_version(current_version) |
Haibo Huang | cd2c612 | 2018-09-04 14:24:20 -0700 | [diff] [blame] | 109 | |
Haibo Huang | 329e681 | 2020-05-29 14:12:20 -0700 | [diff] [blame] | 110 | latest = max( |
| 111 | version_list, |
| 112 | key=lambda ver: _match_and_get_version(parsed_current_ver, ver), |
Haibo Huang | a08fb60 | 2020-05-29 16:24:13 -0700 | [diff] [blame] | 113 | default=None) |
Haibo Huang | 8845e1e | 2018-09-06 17:02:45 -0700 | [diff] [blame] | 114 | if not latest: |
| 115 | raise ValueError('No matching version.') |
Haibo Huang | 0d3810f | 2018-08-31 20:44:25 -0700 | [diff] [blame] | 116 | return latest |