• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"""Base class for all updaters."""
15
16from pathlib import Path
17
18import git_utils
19import fileutils
20# pylint: disable=import-error
21import metadata_pb2  # type: ignore
22
23
24class Updater:
25    """Base Updater that defines methods common for all updaters."""
26    def __init__(self, proj_path: Path, old_identifier: metadata_pb2.Identifier,
27                 old_ver: str) -> None:
28        self._proj_path = fileutils.get_absolute_project_path(proj_path)
29        self._old_identifier = old_identifier
30        self._old_identifier.version = old_identifier.version if old_identifier.version else old_ver
31
32        self._new_identifier = metadata_pb2.Identifier()
33        self._new_identifier.CopyFrom(old_identifier)
34
35        self._alternative_new_ver: str | None = None
36
37        self._has_errors = False
38
39    def is_supported_url(self) -> bool:
40        """Returns whether the url is supported."""
41        raise NotImplementedError()
42
43    def setup_remote(self) -> None:
44        raise NotImplementedError()
45
46    def validate(self) -> str:
47        """Checks whether aosp version is what it claims to be."""
48        self.setup_remote()
49        return git_utils.diff_stat(self._proj_path, 'a', self._old_identifier.version)
50
51    def check(self) -> None:
52        """Checks whether a new version is available."""
53        raise NotImplementedError()
54
55    def update(self) -> Path | None:
56        """Updates the package.
57
58        Has to call check() before this function. Returns either the temporary
59        dir it stored the old version in after upgrading or None.
60        """
61        raise NotImplementedError()
62
63    def rollback(self) -> bool:
64        """Rolls the current update back.
65
66        This is an optional operation.  Returns whether the rollback succeeded.
67        """
68        return False
69
70    def update_metadata(self, metadata: metadata_pb2.MetaData) -> metadata_pb2:
71        """Rewrites the metadata file."""
72        updated_metadata = metadata_pb2.MetaData()
73        updated_metadata.CopyFrom(metadata)
74        updated_metadata.third_party.ClearField("version")
75        for identifier in updated_metadata.third_party.identifier:
76            if identifier == self.current_identifier:
77                identifier.CopyFrom(self.latest_identifier)
78        return updated_metadata
79
80    @property
81    def project_path(self) -> Path:
82        """Gets absolute path to the project."""
83        return self._proj_path
84
85    @property
86    def current_version(self) -> str:
87        """Gets the current version."""
88        return self._old_identifier.version
89
90    @property
91    def current_identifier(self) -> metadata_pb2.Identifier:
92        """Gets the current identifier."""
93        return self._old_identifier
94
95    @property
96    def latest_version(self) -> str:
97        """Gets latest version."""
98        return self._new_identifier.version
99
100    @property
101    def latest_identifier(self) -> metadata_pb2.Identifier:
102        """Gets identifier for latest version."""
103        return self._new_identifier
104
105    @property
106    def has_errors(self) -> bool:
107        """Gets whether this update had an error."""
108        return self._has_errors
109
110    @property
111    def alternative_latest_version(self) -> str | None:
112        """Gets alternative latest version."""
113        return self._alternative_new_ver
114
115    def refresh_without_upgrading(self) -> None:
116        """Uses current version and url as the latest to refresh project."""
117        self._new_identifier.version = self._old_identifier.version
118        self._new_identifier.value = self._old_identifier.value
119
120    def set_new_version(self, version: str) -> None:
121        """Uses the passed version as the latest to upgrade project."""
122        self._new_identifier.version = version
123
124    def set_custom_version(self, custom_version: str) -> None:
125        """Uses the passed version as the latest to upgrade project if the
126        passed version is not older than the current version."""
127        if git_utils.is_ancestor(self._proj_path, self._old_identifier.version, custom_version):
128            self._new_identifier.version = custom_version
129        else:
130            raise RuntimeError(
131                f"Cannot upgrade to {custom_version}. "
132                f"Either the current version is newer than {custom_version} "
133                f"or the current version in the METADATA file is not correct.")
134