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"""Module to check updates from Git upstream."""
15
16import base_updater
17import git_utils
18# pylint: disable=import-error
19import metadata_pb2  # type: ignore
20import updater_utils
21
22
23class GitUpdater(base_updater.Updater):
24    """Updater for Git upstream."""
25    UPSTREAM_REMOTE_NAME: str = "update_origin"
26    android_remote_name: str
27
28    def is_supported_url(self) -> bool:
29        return self._old_url.type == metadata_pb2.URL.GIT
30
31    def _setup_remote(self) -> None:
32        remotes = git_utils.list_remotes(self._proj_path)
33        current_remote_url = None
34        for name, url in remotes.items():
35            if name == self.UPSTREAM_REMOTE_NAME:
36                current_remote_url = url
37
38            # Guess android remote name.
39            if '/platform/external/' in url:
40                self.android_remote_name = name
41
42        if current_remote_url is not None and current_remote_url != self._old_url.value:
43            git_utils.remove_remote(self._proj_path, self.UPSTREAM_REMOTE_NAME)
44            current_remote_url = None
45
46        if current_remote_url is None:
47            git_utils.add_remote(self._proj_path, self.UPSTREAM_REMOTE_NAME,
48                                 self._old_url.value)
49
50        git_utils.fetch(self._proj_path,
51                        [self.UPSTREAM_REMOTE_NAME, self.android_remote_name])
52
53    def check(self) -> None:
54        """Checks upstream and returns whether a new version is available."""
55        self._setup_remote()
56        if git_utils.is_commit(self._old_ver):
57            # Update to remote head.
58            self._check_head()
59        else:
60            # Update to latest version tag.
61            self._check_tag()
62
63    def _check_tag(self) -> None:
64        tags = git_utils.list_remote_tags(self._proj_path,
65                                          self.UPSTREAM_REMOTE_NAME)
66        self._new_ver = updater_utils.get_latest_version(self._old_ver, tags)
67
68    def _check_head(self) -> None:
69        self._new_ver = git_utils.get_sha_for_branch(
70            self._proj_path, self.UPSTREAM_REMOTE_NAME + '/master')
71
72    def update(self) -> None:
73        """Updates the package.
74
75        Has to call check() before this function.
76        """
77        print(f"Running `git merge {self._new_ver}`...")
78        git_utils.merge(self._proj_path, self._new_ver)
79