blob: 209a1cde8bfb555e22588f2f91c58ebeae3b8ed8 [file] [log] [blame]
(raulenrique)dfdda472018-06-04 12:02:29 -07001# 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
16import os
Haibo Huang0d3810f2018-08-31 20:44:25 -070017import re
(raulenrique)dfdda472018-06-04 12:02:29 -070018import subprocess
19import sys
Haibo Huanga08fb602020-05-29 16:24:13 -070020from pathlib import Path
21from typing import List, Tuple, Type
22
23from base_updater import Updater
ThiƩbaud Weksteen4ac289b2020-09-28 15:23:29 +020024# pylint: disable=import-error
Haibo Huanga08fb602020-05-29 16:24:13 -070025import metadata_pb2 # type: ignore
(raulenrique)dfdda472018-06-04 12:02:29 -070026
27
Haibo Huanga08fb602020-05-29 16:24:13 -070028def create_updater(metadata: metadata_pb2.MetaData, proj_path: Path,
29 updaters: List[Type[Updater]]) -> Updater:
(raulenrique)dfdda472018-06-04 12:02:29 -070030 """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 Huang329e6812020-05-29 14:12:20 -070043 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)dfdda472018-06-04 12:02:29 -070047
48 raise ValueError('No supported URL.')
49
50
Joel Galenson40a5a4a2021-05-20 09:50:44 -070051def replace_package(source_dir, target_dir, temp_file=None) -> None:
(raulenrique)dfdda472018-06-04 12:02:29 -070052 """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 Huang329e6812020-05-29 14:12:20 -070060 script_path = os.path.join(os.path.dirname(sys.argv[0]),
61 'update_package.sh')
Joel Galenson40a5a4a2021-05-20 09:50:44 -070062 subprocess.check_call(['bash', script_path, source_dir, target_dir,
63 "" if temp_file is None else temp_file])
Haibo Huang0d3810f2018-08-31 20:44:25 -070064
Haibo Huang329e6812020-05-29 14:12:20 -070065
Haibo Huanga08fb602020-05-29 16:24:13 -070066VERSION_SPLITTER_PATTERN: str = r'[\.\-_]'
67VERSION_PATTERN: str = (r'^(?P<prefix>[^\d]*)' + r'(?P<version>\d+(' +
68 VERSION_SPLITTER_PATTERN + r'\d+)*)' +
69 r'(?P<suffix>.*)$')
70VERSION_RE: re.Pattern = re.compile(VERSION_PATTERN)
71VERSION_SPLITTER_RE: re.Pattern = re.compile(VERSION_SPLITTER_PATTERN)
72
73ParsedVersion = Tuple[List[int], str, str]
Haibo Huang0d3810f2018-08-31 20:44:25 -070074
75
Haibo Huanga08fb602020-05-29 16:24:13 -070076def _parse_version(version: str) -> ParsedVersion:
Haibo Huang0d3810f2018-08-31 20:44:25 -070077 match = VERSION_RE.match(version)
78 if match is None:
79 raise ValueError('Invalid version.')
80 try:
Haibo Huang329e6812020-05-29 14:12:20 -070081 prefix, version, suffix = match.group('prefix', 'version', 'suffix')
Haibo Huanga08fb602020-05-29 16:24:13 -070082 versions = [int(v) for v in VERSION_SPLITTER_RE.split(version)]
83 return (versions, str(prefix), str(suffix))
Haibo Huang0d3810f2018-08-31 20:44:25 -070084 except IndexError:
ThiƩbaud Weksteen4ac289b2020-09-28 15:23:29 +020085 # pylint: disable=raise-missing-from
Haibo Huang0d3810f2018-08-31 20:44:25 -070086 raise ValueError('Invalid version.')
87
88
Haibo Huanga08fb602020-05-29 16:24:13 -070089def _match_and_get_version(old_ver: ParsedVersion,
90 version: str) -> Tuple[bool, bool, List[int]]:
Haibo Huang0d3810f2018-08-31 20:44:25 -070091 try:
Haibo Huang3ffcec12020-04-09 15:35:57 -070092 new_ver = _parse_version(version)
Haibo Huang0d3810f2018-08-31 20:44:25 -070093 except ValueError:
Haibo Huanga08fb602020-05-29 16:24:13 -070094 return (False, False, [])
Haibo Huang0d3810f2018-08-31 20:44:25 -070095
Haibo Huang3ffcec12020-04-09 15:35:57 -070096 right_format = (new_ver[1:] == old_ver[1:])
97 right_length = len(new_ver[0]) == len(old_ver[0])
Haibo Huang0d3810f2018-08-31 20:44:25 -070098
Haibo Huanga08fb602020-05-29 16:24:13 -070099 return (right_format, right_length, new_ver[0])
Haibo Huang0d3810f2018-08-31 20:44:25 -0700100
101
Haibo Huanga08fb602020-05-29 16:24:13 -0700102def get_latest_version(current_version: str, version_list: List[str]) -> str:
Haibo Huangcd2c6122018-09-04 14:24:20 -0700103 """Gets the latest version name from a list of versions.
Haibo Huang0d3810f2018-08-31 20:44:25 -0700104
Haibo Huangcd2c6122018-09-04 14:24:20 -0700105 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 Huang3ffcec12020-04-09 15:35:57 -0700108 parsed_current_ver = _parse_version(current_version)
Haibo Huangcd2c6122018-09-04 14:24:20 -0700109
Haibo Huang329e6812020-05-29 14:12:20 -0700110 latest = max(
111 version_list,
112 key=lambda ver: _match_and_get_version(parsed_current_ver, ver),
Haibo Huanga08fb602020-05-29 16:24:13 -0700113 default=None)
Haibo Huang8845e1e2018-09-06 17:02:45 -0700114 if not latest:
115 raise ValueError('No matching version.')
Haibo Huang0d3810f2018-08-31 20:44:25 -0700116 return latest