ClickHouse/tests/ci/cherry_pick_utils/local.py

110 lines
3.4 KiB
Python
Raw Normal View History

2021-11-08 14:30:27 +00:00
# -*- coding: utf-8 -*-
import functools
import logging
import os
import re
import git
2021-11-08 14:30:27 +00:00
class RepositoryBase:
def __init__(self, repo_path):
self._repo = git.Repo(repo_path, search_parent_directories=(not repo_path))
# comparator of commits
def cmp(x, y):
if str(x) == str(y):
return 0
if self._repo.is_ancestor(x, y):
return -1
else:
return 1
2021-11-08 14:30:27 +00:00
self.comparator = functools.cmp_to_key(cmp)
def iterate(self, begin, end):
rev_range = f"{begin}...{end}"
2021-11-08 14:30:27 +00:00
for commit in self._repo.iter_commits(rev_range, first_parent=True):
yield commit
class Repository(RepositoryBase):
def __init__(self, repo_path, remote_name, default_branch_name):
super().__init__(repo_path)
2021-11-08 14:30:27 +00:00
self._remote = self._repo.remotes[remote_name]
self._remote.fetch()
self._default = self._remote.refs[default_branch_name]
def get_head_commit(self):
return self._repo.commit(self._default)
2021-11-08 14:30:27 +00:00
def get_release_branches(self):
"""
2021-11-08 14:30:27 +00:00
Returns sorted list of tuples:
* remote branch (git.refs.remote.RemoteReference),
* base commit (git.Commit),
* head (git.Commit)).
List is sorted by commits in ascending order.
"""
2021-11-08 14:30:27 +00:00
release_branches = []
RE_RELEASE_BRANCH_REF = re.compile(r"^refs/remotes/.+/\d+\.\d+$")
2021-11-08 14:30:27 +00:00
for branch in [
r for r in self._remote.refs if RE_RELEASE_BRANCH_REF.match(r.path)
]:
2021-11-08 14:30:27 +00:00
base = self._repo.merge_base(self._default, self._repo.commit(branch))
if not base:
logging.info(
"Branch %s is not based on branch %s. Ignoring.",
branch.path,
self._default,
)
2021-11-08 14:30:27 +00:00
elif len(base) > 1:
logging.info(
"Branch %s has more than one base commit. Ignoring.", branch.path
)
2021-11-08 14:30:27 +00:00
else:
release_branches.append((os.path.basename(branch.name), base[0]))
return sorted(release_branches, key=lambda x: self.comparator(x[1]))
2021-11-08 14:30:27 +00:00
class BareRepository(RepositoryBase):
def __init__(self, repo_path, default_branch_name):
super().__init__(repo_path)
2021-11-08 14:30:27 +00:00
self._default = self._repo.branches[default_branch_name]
def get_release_branches(self):
"""
2021-11-08 14:30:27 +00:00
Returns sorted list of tuples:
* branch (git.refs.head?),
* base commit (git.Commit),
* head (git.Commit)).
List is sorted by commits in ascending order.
"""
2021-11-08 14:30:27 +00:00
release_branches = []
RE_RELEASE_BRANCH_REF = re.compile(r"^refs/heads/\d+\.\d+$")
2021-11-08 14:30:27 +00:00
for branch in [
r for r in self._repo.branches if RE_RELEASE_BRANCH_REF.match(r.path)
]:
2021-11-08 14:30:27 +00:00
base = self._repo.merge_base(self._default, self._repo.commit(branch))
if not base:
logging.info(
"Branch %s is not based on branch %s. Ignoring.",
branch.path,
self._default,
)
2021-11-08 14:30:27 +00:00
elif len(base) > 1:
logging.info(
"Branch %s has more than one base commit. Ignoring.", branch.path
)
2021-11-08 14:30:27 +00:00
else:
release_branches.append((os.path.basename(branch.name), base[0]))
return sorted(release_branches, key=lambda x: self.comparator(x[1]))