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