Remove remote if it is not consistent with METADATA am: a08fb60ea4
Change-Id: Ibb38b4766e6add9f02d1f1925182040be0688481
diff --git a/external_updater.py b/external_updater.py
index 6c4759f..31cdbbd 100644
--- a/external_updater.py
+++ b/external_updater.py
@@ -29,8 +29,6 @@
from typing import Dict, Iterator, List, Union, Tuple, Type
from pathlib import Path
-from google.protobuf import text_format # type: ignore
-
from base_updater import Updater
from crates_updater import CratesUpdater
from git_updater import GitUpdater
@@ -61,7 +59,7 @@
END_COLOR = '\033[0m'
-def color_string(string: str, color: Color):
+def color_string(string: str, color: Color) -> str:
"""Changes the color of a string when print to terminal."""
if not USE_COLOR:
return string
@@ -185,7 +183,7 @@
dirs.sort(key=lambda d: d.lower())
-def check(args: argparse.Namespace):
+def check(args: argparse.Namespace) -> None:
"""Handler for check command."""
paths = _list_all_metadata() if args.all else args.paths
results = _check_path(args, paths, args.delay)
@@ -254,7 +252,7 @@
return parser.parse_args()
-def main():
+def main() -> None:
"""The main entry."""
args = parse_args()
diff --git a/fileutils.py b/fileutils.py
index bd5c29c..d7dd0fa 100644
--- a/fileutils.py
+++ b/fileutils.py
@@ -29,25 +29,25 @@
METADATA_FILENAME = 'METADATA'
-def get_absolute_project_path(project_path) -> Path:
+def get_absolute_project_path(proj_path: Path) -> Path:
"""Gets absolute path of a project.
Path resolution starts from external/.
"""
- return EXTERNAL_PATH / project_path
+ return EXTERNAL_PATH / proj_path
-def get_metadata_path(project_path) -> Path:
+def get_metadata_path(proj_path: Path) -> Path:
"""Gets the absolute path of METADATA for a project."""
- return get_absolute_project_path(project_path) / METADATA_FILENAME
+ return get_absolute_project_path(proj_path) / METADATA_FILENAME
-def get_relative_project_path(project_path) -> Path:
+def get_relative_project_path(proj_path: Path) -> Path:
"""Gets the relative path of a project starting from external/."""
- return get_absolute_project_path(project_path).relative_to(EXTERNAL_PATH)
+ return get_absolute_project_path(proj_path).relative_to(EXTERNAL_PATH)
-def read_metadata(proj_path) -> metadata_pb2.MetaData:
+def read_metadata(proj_path: Path) -> metadata_pb2.MetaData:
"""Reads and parses METADATA file for a project.
Args:
@@ -66,7 +66,7 @@
return text_format.Parse(metadata, metadata_pb2.MetaData())
-def write_metadata(proj_path, metadata) -> None:
+def write_metadata(proj_path: Path, metadata: metadata_pb2.MetaData) -> None:
"""Writes updated METADATA file for a project.
This function updates last_upgrade_date in metadata and write to the project
diff --git a/git_updater.py b/git_updater.py
index 7e94890..4c02821 100644
--- a/git_updater.py
+++ b/git_updater.py
@@ -22,7 +22,7 @@
class GitUpdater(base_updater.Updater):
"""Updater for Git upstream."""
- upstream_remote_name: str
+ UPSTREAM_REMOTE_NAME: str = "update_origin"
android_remote_name: str
def is_supported_url(self) -> bool:
@@ -30,23 +30,25 @@
def _setup_remote(self) -> None:
remotes = git_utils.list_remotes(self._proj_path)
- upstream_remote_name = None
+ current_remote_url = None
for name, url in remotes.items():
- if url == self._old_url.value:
- upstream_remote_name = name
+ if name == self.UPSTREAM_REMOTE_NAME:
+ current_remote_url = url
# Guess android remote name.
if '/platform/external/' in url:
self.android_remote_name = name
- if upstream_remote_name is None:
- upstream_remote_name = "update_origin"
- git_utils.add_remote(self._proj_path, upstream_remote_name,
+ if current_remote_url is not None and current_remote_url != self._old_url.value:
+ git_utils.remove_remote(self._proj_path, self.UPSTREAM_REMOTE_NAME)
+ current_remote_url = None
+
+ if current_remote_url is None:
+ git_utils.add_remote(self._proj_path, self.UPSTREAM_REMOTE_NAME,
self._old_url.value)
- self.upstream_remote_name = upstream_remote_name
git_utils.fetch(self._proj_path,
- [self.upstream_remote_name, self.android_remote_name])
+ [self.UPSTREAM_REMOTE_NAME, self.android_remote_name])
def check(self) -> None:
"""Checks upstream and returns whether a new version is available."""
@@ -58,14 +60,14 @@
# Update to latest version tag.
self._check_tag()
- def _check_tag(self):
+ def _check_tag(self) -> None:
tags = git_utils.list_remote_tags(self._proj_path,
- self.upstream_remote_name)
+ self.UPSTREAM_REMOTE_NAME)
self._new_ver = updater_utils.get_latest_version(self._old_ver, tags)
- def _check_head(self):
+ def _check_head(self) -> None:
self._new_ver = git_utils.get_sha_for_branch(
- self._proj_path, self.upstream_remote_name + '/master')
+ self._proj_path, self.UPSTREAM_REMOTE_NAME + '/master')
def update(self) -> None:
"""Updates the package.
diff --git a/git_utils.py b/git_utils.py
index bdbc05c..69dcfba 100644
--- a/git_utils.py
+++ b/git_utils.py
@@ -46,6 +46,11 @@
_run(['git', 'remote', 'add', name, url], cwd=proj_path)
+def remove_remote(proj_path: Path, name: str) -> None:
+ """Removes a git remote."""
+ _run(['git', 'remote', 'remove', name], cwd=proj_path)
+
+
def list_remotes(proj_path: Path) -> Dict[str, str]:
"""Lists all Git remotes.
diff --git a/github_archive_updater.py b/github_archive_updater.py
index d5a4e29..cc3840f 100644
--- a/github_archive_updater.py
+++ b/github_archive_updater.py
@@ -102,9 +102,9 @@
]
return (data[self.VERSION_FIELD], supported_assets)
- def _fetch_latest_tag(self):
+ def _fetch_latest_tag(self) -> Tuple[str, List[str]]:
page = 1
- tags = []
+ tags: List[str] = []
# fetches at most 20 pages.
for page in range(1, 21):
# Sleeps 10s to avoid rate limit.
@@ -119,8 +119,8 @@
def _fetch_latest_version(self) -> None:
"""Checks upstream and gets the latest release tag."""
- self._new_ver, urls = self._fetch_latest_release(
- ) or self._fetch_latest_tag()
+ self._new_ver, urls = (self._fetch_latest_release()
+ or self._fetch_latest_tag())
# Adds source code urls.
urls.append('https://github.com/{}/{}/archive/{}.tar.gz'.format(
@@ -137,9 +137,11 @@
with urllib.request.urlopen(url) as request:
data = json.loads(request.read().decode())
self._new_ver = data['sha']
- self._new_url.value = f'https://github.com/{self.owner}/{self.repo}/archive/{self._new_ver}.zip'
+ self._new_url.value = (
+ f'https://github.com/{self.owner}/{self.repo}/archive/{self._new_ver}.zip'
+ )
- def check(self):
+ def check(self) -> None:
"""Checks update for package.
Returns True if a new version is available.
@@ -149,14 +151,15 @@
else:
self._fetch_latest_version()
- def update(self):
+ def update(self) -> None:
"""Updates the package.
Has to call check() before this function.
"""
temporary_dir = None
try:
- temporary_dir = archive_utils.download_and_extract(self._new_url.value)
+ temporary_dir = archive_utils.download_and_extract(
+ self._new_url.value)
package_dir = archive_utils.find_archive_root(temporary_dir)
updater_utils.replace_package(package_dir, self._proj_path)
finally:
diff --git a/notifier.py b/notifier.py
index 12daeb2..d061181 100644
--- a/notifier.py
+++ b/notifier.py
@@ -31,28 +31,27 @@
import git_utils
+
def parse_args():
"""Parses commandline arguments."""
parser = argparse.ArgumentParser(
description='Check updates for third party projects in external/.')
- parser.add_argument(
- '--history',
- help='Path of history file. If doesn'
- 't exist, a new one will be created.')
+ parser.add_argument('--history',
+ help='Path of history file. If doesn'
+ 't exist, a new one will be created.')
parser.add_argument(
'--recipients',
help='Comma separated recipients of notification email.')
parser.add_argument(
'--generate_change',
help='If set, an upgrade change will be uploaded to Gerrit.',
- action='store_true', required=False)
- parser.add_argument(
- 'paths', nargs='*',
- help='Paths of the project.')
- parser.add_argument(
- '--all', action='store_true',
- help='Checks all projects.')
+ action='store_true',
+ required=False)
+ parser.add_argument('paths', nargs='*', help='Paths of the project.')
+ parser.add_argument('--all',
+ action='store_true',
+ help='Checks all projects.')
return parser.parse_args()
@@ -89,10 +88,12 @@
msg += '\n\n'
msg += upgrade_log
- subprocess.run(['sendgmr', '--to=' + recipient,
- '--subject=' + proj], check=True,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- input=msg, encoding='ascii')
+ subprocess.run(['sendgmr', '--to=' + recipient, '--subject=' + proj],
+ check=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ input=msg,
+ encoding='ascii')
NOTIFIED_TIME_KEY_NAME = 'latest_notified_time'
@@ -155,10 +156,12 @@
def _upgrade(proj):
- out = subprocess.run(['out/soong/host/linux-x86/bin/external_updater',
- 'update', '--branch_and_commit', '--push_change',
- proj],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ out = subprocess.run([
+ 'out/soong/host/linux-x86/bin/external_updater', 'update',
+ '--branch_and_commit', '--push_change', proj
+ ],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
cwd=_get_android_top())
stdout = out.stdout.decode('utf-8')
stderr = out.stderr.decode('utf-8')
@@ -175,9 +178,10 @@
def _check_updates(args):
- params = ['out/soong/host/linux-x86/bin/external_updater',
- 'check', '--json_output', RESULT_FILE_PATH,
- '--delay', '30']
+ params = [
+ 'out/soong/host/linux-x86/bin/external_updater', 'check',
+ '--json_output', RESULT_FILE_PATH, '--delay', '30'
+ ]
if args.all:
params.append('--all')
else:
diff --git a/updater_utils.py b/updater_utils.py
index 02f227a..3301e8f 100644
--- a/updater_utils.py
+++ b/updater_utils.py
@@ -17,9 +17,15 @@
import re
import subprocess
import sys
+from pathlib import Path
+from typing import List, Tuple, Type
+
+from base_updater import Updater
+import metadata_pb2 # type: ignore
-def create_updater(metadata, proj_path, updaters):
+def create_updater(metadata: metadata_pb2.MetaData, proj_path: Path,
+ updaters: List[Type[Updater]]) -> Updater:
"""Creates corresponding updater object for a project.
Args:
@@ -55,38 +61,42 @@
subprocess.check_call(['bash', script_path, source_dir, target_dir])
-VERSION_SPLITTER_PATTERN = r'[\.\-_]'
-VERSION_PATTERN = (r'^(?P<prefix>[^\d]*)' + r'(?P<version>\d+(' +
- VERSION_SPLITTER_PATTERN + r'\d+)*)' + r'(?P<suffix>.*)$')
-VERSION_RE = re.compile(VERSION_PATTERN)
-VERSION_SPLITTER_RE = re.compile(VERSION_SPLITTER_PATTERN)
+VERSION_SPLITTER_PATTERN: str = r'[\.\-_]'
+VERSION_PATTERN: str = (r'^(?P<prefix>[^\d]*)' + r'(?P<version>\d+(' +
+ VERSION_SPLITTER_PATTERN + r'\d+)*)' +
+ r'(?P<suffix>.*)$')
+VERSION_RE: re.Pattern = re.compile(VERSION_PATTERN)
+VERSION_SPLITTER_RE: re.Pattern = re.compile(VERSION_SPLITTER_PATTERN)
+
+ParsedVersion = Tuple[List[int], str, str]
-def _parse_version(version):
+def _parse_version(version: str) -> ParsedVersion:
match = VERSION_RE.match(version)
if match is None:
raise ValueError('Invalid version.')
try:
prefix, version, suffix = match.group('prefix', 'version', 'suffix')
- version = [int(v) for v in VERSION_SPLITTER_RE.split(version)]
- return (version, prefix, suffix)
+ versions = [int(v) for v in VERSION_SPLITTER_RE.split(version)]
+ return (versions, str(prefix), str(suffix))
except IndexError:
raise ValueError('Invalid version.')
-def _match_and_get_version(old_ver, version):
+def _match_and_get_version(old_ver: ParsedVersion,
+ version: str) -> Tuple[bool, bool, List[int]]:
try:
new_ver = _parse_version(version)
except ValueError:
- return []
+ return (False, False, [])
right_format = (new_ver[1:] == old_ver[1:])
right_length = len(new_ver[0]) == len(old_ver[0])
- return [right_format, right_length, new_ver[0]]
+ return (right_format, right_length, new_ver[0])
-def get_latest_version(current_version, version_list):
+def get_latest_version(current_version: str, version_list: List[str]) -> str:
"""Gets the latest version name from a list of versions.
The new version must have the same prefix and suffix with old version.
@@ -97,7 +107,7 @@
latest = max(
version_list,
key=lambda ver: _match_and_get_version(parsed_current_ver, ver),
- default=[])
+ default=None)
if not latest:
raise ValueError('No matching version.')
return latest