# Copyright (C) 2018 The Android Open Source Project
|
#
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
# you may not use this file except in compliance with the License.
|
# You may obtain a copy of the License at
|
#
|
# http://www.apache.org/licenses/LICENSE-2.0
|
#
|
# Unless required by applicable law or agreed to in writing, software
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# See the License for the specific language governing permissions and
|
# limitations under the License.
|
"""Module to check updates from Git upstream."""
|
|
|
import datetime
|
|
import fileutils
|
import git_utils
|
import metadata_pb2 # pylint: disable=import-error
|
import updater_utils
|
|
|
class GitUpdater():
|
"""Updater for Git upstream."""
|
|
def __init__(self, url, proj_path, metadata):
|
if url.type != metadata_pb2.URL.GIT:
|
raise ValueError('Only support GIT upstream.')
|
self.proj_path = proj_path
|
self.metadata = metadata
|
self.upstream_url = url
|
self.upstream_remote_name = None
|
self.android_remote_name = None
|
self.new_version = None
|
|
def _setup_remote(self):
|
remotes = git_utils.list_remotes(self.proj_path)
|
for name, url in remotes.items():
|
if url == self.upstream_url.value:
|
self.upstream_remote_name = name
|
|
# Guess android remote name.
|
if '/platform/external/' in url:
|
self.android_remote_name = name
|
|
if self.upstream_remote_name is None:
|
self.upstream_remote_name = "update_origin"
|
git_utils.add_remote(self.proj_path, self.upstream_remote_name,
|
self.upstream_url.value)
|
|
git_utils.fetch(self.proj_path,
|
[self.upstream_remote_name, self.android_remote_name])
|
|
def check(self):
|
"""Checks upstream and returns whether a new version is available."""
|
|
self._setup_remote()
|
if git_utils.is_commit(self.metadata.third_party.version):
|
# Update to remote head.
|
self._check_head()
|
else:
|
# Update to latest version tag.
|
self._check_tag()
|
|
def get_current_version(self):
|
"""Returns the latest version name recorded in METADATA."""
|
return self.metadata.third_party.version
|
|
def get_latest_version(self):
|
"""Returns the latest version name in upstream."""
|
return self.new_version
|
|
def _check_tag(self):
|
tags = git_utils.list_remote_tags(self.proj_path,
|
self.upstream_remote_name)
|
current_ver = self.get_current_version()
|
self.new_version = updater_utils.get_latest_version(
|
current_ver, tags)
|
print('Current version: {}. Latest version: {}'.format(
|
current_ver, self.new_version), end='')
|
|
def _check_head(self):
|
commits = git_utils.get_commits_ahead(
|
self.proj_path, self.upstream_remote_name + '/master',
|
self.android_remote_name + '/master')
|
|
if not commits:
|
self.new_version = self.get_current_version()
|
return
|
|
self.new_version = commits[0]
|
|
commit_time = git_utils.get_commit_time(self.proj_path, commits[-1])
|
time_behind = datetime.datetime.now() - commit_time
|
print('{} commits ({} days) behind.'.format(
|
len(commits), time_behind.days), end='')
|
|
def _write_metadata(self, path):
|
updated_metadata = metadata_pb2.MetaData()
|
updated_metadata.CopyFrom(self.metadata)
|
updated_metadata.third_party.version = self.new_version
|
fileutils.write_metadata(path, updated_metadata)
|
|
def update(self):
|
"""Updates the package.
|
|
Has to call check() before this function.
|
"""
|
upstream_branch = self.upstream_remote_name + '/master'
|
|
print("Running `git merge {merge_branch}`..."
|
.format(merge_branch=self.new_version))
|
git_utils.merge(self.proj_path, self.new_version)
|
self._write_metadata(self.proj_path)
|
git_utils.add_file(self.proj_path, 'METADATA')
|