1
0
Fork 0

create branch for every diff

This should be compatible with the current pipelines.
This commit is contained in:
Christian Kühnel 2020-03-23 10:39:49 +01:00
parent a638dd5342
commit fe92469ae0

View file

@ -23,7 +23,11 @@ import time
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from phabricator import Phabricator from phabricator import Phabricator
from git import Repo, GitCommandError from git import Repo, BadName
# FIXME: maybe move to config file
LLVM_GITHUB_URL = 'ssh://git@github.com/llvm/llvm-project'
class ApplyPatch: class ApplyPatch:
@ -42,8 +46,10 @@ class ApplyPatch:
https://github.com/llvm/llvm-project https://github.com/llvm/llvm-project
""" """
def __init__(self, diff_id: int, comment_file_path: str, token: str, url: str, git_hash: str): def __init__(self, diff_id: int, comment_file_path: str, token: str, url: str, git_hash: str,
push_branch: bool = False):
self.comment_file_path = comment_file_path self.comment_file_path = comment_file_path
self.push_branch = push_branch # type: bool
self.conduit_token = token # type: Optional[str] self.conduit_token = token # type: Optional[str]
self.host = url # type: Optional[str] self.host = url # type: Optional[str]
self._load_arcrc() self._load_arcrc()
@ -55,6 +61,11 @@ class ApplyPatch:
self.msg = [] # type: List[str] self.msg = [] # type: List[str]
self.repo = Repo(os.getcwd()) # type: Repo self.repo = Repo(os.getcwd()) # type: Repo
@property
def branch_name(self):
"""Name used for the git branch."""
return 'phab-diff-{}'.format(self.diff_id)
def _load_arcrc(self): def _load_arcrc(self):
"""Load arc configuration from file if not set.""" """Load arc configuration from file if not set."""
if self.conduit_token is not None or self.host is not None: if self.conduit_token is not None or self.host is not None:
@ -73,20 +84,10 @@ class ApplyPatch:
""" """
try: try:
self._refresh_master()
revision_id, dependencies, base_revision = self._get_dependencies(self.diff_id) revision_id, dependencies, base_revision = self._get_dependencies(self.diff_id)
dependencies.reverse() # Arrange deps in chronological order. dependencies.reverse() # Arrange deps in chronological order.
if self.base_revision is not None: self._create_branch(base_revision)
print('Using base revision provided by command line\n{} instead of resolved\n{}'.format(
self.base_revision, base_revision))
base_revision = self.base_revision
print('Checking out {}...'.format(base_revision))
try:
self.repo.git.checkout(base_revision)
except GitCommandError:
print('ERROR checking out revision {}. It`s not in the '
'repository. Using master instead.'.format(base_revision))
self.repo.git.checkout('master')
print('Revision is {}'.format(self.repo.head.commit.hexsha))
print('git reset, git cleanup...') print('git reset, git cleanup...')
self.repo.git.reset('--hard') self.repo.git.reset('--hard')
self.repo.git.clean('-fdx') self.repo.git.clean('-fdx')
@ -99,16 +100,70 @@ class ApplyPatch:
if missing: if missing:
for revision in missing: for revision in missing:
self._apply_revision(revision) self._apply_revision(revision)
# FIXME: submit every Revision individually to get nicer history, use original user name
self.repo.config_writer().set_value("user", "name", "myusername").release() self.repo.config_writer().set_value("user", "name", "myusername").release()
self.repo.config_writer().set_value("user", "email", "myemail@example.com").release() self.repo.config_writer().set_value("user", "email", "myemail@example.com").release()
self.repo.git.commit('-a', '-m', 'dependencies') self.repo.git.commit('-a', '-m', 'dependencies')
print('All depended diffs are applied') print('All depended diffs are applied')
self._apply_diff(self.diff_id, revision_id) self._apply_diff(self.diff_id, revision_id)
self.repo.git.add('-u', '.') if self.push_branch:
self._commit_and_push()
else:
self.repo.git.add('-u', '.')
print('done.') print('done.')
finally: finally:
self._write_error_message() self._write_error_message()
def _refresh_master(self):
"""Update local git repo and origin.
As origin is disjoint from upstream, it needs to be updated by this script.
"""
if not self.push_branch:
return
print('Syncing local, origin and upstream...')
self.repo.git.fetch('--all')
self.repo.git.checkout('master')
self.repo.git.reset('--hard')
self.repo.git.clean('-fdx')
if 'upstream' not in self.repo.remotes:
self.repo.create_remote('upstream', url=LLVM_GITHUB_URL)
self.repo.remotes.upstream.fetch()
self.repo.git.pull('upstream', 'master')
self.repo.git.push('origin', 'master')
print('refresh of master branch completed')
def _create_branch(self, base_revision: Optional[str]):
self.repo.git.fetch('--all')
if self.branch_name in self.repo.heads:
self.repo.delete_head('--force', self.branch_name)
if self.base_revision is not None:
print('Using base revision provided by command line\n{} instead of resolved\n{}'.format(
self.base_revision, base_revision))
base_revision = self.base_revision
try:
commit = self.repo.commit()
except BadName:
print('Revision {} not found in upstream repository, using master instead.'.format(base_revision))
commit = self.repo.heads['master']
new_branch = self.repo.create_head(self.branch_name, commit.hexsha)
self.repo.head.reference = new_branch
self.repo.head.reset(index=True, working_tree=True)
print('Base revision is {}'.format(self.repo.head.commit.hexsha))
def _commit_and_push(self):
"""Commit the patch and push it to origin."""
if not self.push_branch:
return
self.repo.git.add('-A')
self.repo.index.commit(message='applying Diff {}'.format(
self.diff_id))
self.repo.git.push('--force', 'origin', self.branch_name)
print('Branch {} pushed to origin'.format(self.branch_name))
pass
def _create_phab(self): def _create_phab(self):
phab = Phabricator(token=self.conduit_token, host=self.host) phab = Phabricator(token=self.conduit_token, host=self.host)
try_call(lambda: phab.update_interfaces()) try_call(lambda: phab.update_interfaces())
@ -245,6 +300,8 @@ if __name__ == "__main__":
parser.add_argument('--url', type=str, default=None, help='Phabricator URL') parser.add_argument('--url', type=str, default=None, help='Phabricator URL')
parser.add_argument('--commit', dest='commit', type=str, default=None, parser.add_argument('--commit', dest='commit', type=str, default=None,
help='Use this commit as a base. By default tool tries to pick the base commit itself') help='Use this commit as a base. By default tool tries to pick the base commit itself')
parser.add_argument('--push-branch', action='store_true', dest='push_branch',
help='choose if branch shall be pushed to origin')
args = parser.parse_args() args = parser.parse_args()
patcher = ApplyPatch(args.diff_id, args.comment_file_path, args.token, args.url, args.commit) patcher = ApplyPatch(args.diff_id, args.comment_file_path, args.token, args.url, args.commit, args.push_branch)
patcher.run() patcher.run()