#!/usr/bin/python3
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent / 'python'))

import argparse
import atexit
import subprocess

from pygit2 import Keypair, Oid, RemoteCallbacks, Repository, enums
from slaby_scripts.git import run_git_command

argparser = argparse.ArgumentParser(description='Rebase work onto devel and push to origin')
argparser.add_argument('--continue', action='store_true', help='Continue rebase if in progress')
args = argparser.parse_args()
cont = vars(args)['continue']

repo = Repository('.')
child = None

cur_branch = repo.head.shorthand
if not cont and cur_branch == 'work':
    run_git_command('rebase', 'work', 'devel', capture_output=False)
elif cur_branch != 'devel':
    raise RuntimeError(f"not on {'work or ' if not cont else ''}devel branch: on {cur_branch if cur_branch else '<nothing>'}")

class MyRemoteCallbacks(RemoteCallbacks):
    def transfer_progress(self, stats):
        print(f"Received {stats.received_objects}/{stats.total_objects} objects ({stats.indexed_objects} indexed)")

    def update_tips(self, refname: str, old: Oid, new: Oid):
        old = repo[old].short_id
        new = repo[new].short_id
        print(f"Updated {refname} from {old} to {new}")

    def credentials(self, url, username_from_url, allowed_types):
        if allowed_types & enums.CredentialType.SSH_KEY:
            priv = Path.home() / '.ssh' / 'korg-jirislaby'
            pub = priv.with_suffix('.pub')
            return Keypair(username_from_url, pub, priv, None)

        raise RuntimeError(f"No suitable credentials for {url} (username: {username_from_url}, allowed types: {allowed_types:x})")

    def push_transfer_progress(self, current, total, bytes):
        print(f"Pushed {current}/{total} objects ({bytes} bytes)")

    def push_update_reference(self, refname, status):
        if status:
            print(f"Failed to update {refname}: {status}")
        else:
            print(f"Updated {refname}")

if not cont:
    child = subprocess.Popen(['ssh', 'git@gitolite.kernel.org', 'track', 'fetch',
                              'pub/scm/linux/kernel/git/jirislaby/linux', 'next_master'])
    atexit.register(child.wait)

    stat = repo.status('no')
    if stat:
        raise RuntimeError(f"directory not clean:\n{'\n'.join(stat)}")

    repo.remotes['next'].fetch(callbacks=MyRemoteCallbacks())
    repo.remotes['origin'].fetch(callbacks=MyRemoteCallbacks())

    try:
        run_git_command('rebase', '--onto=next/master', 'korg/next_master', 'devel',
                        capture_output=False, exit_on_error=False)
    except subprocess.CalledProcessError:
        raise RuntimeError("rebase failed")

walker = repo.walk(repo.head.target)
walker.hide(repo.lookup_reference('refs/remotes/next/master').target)
for commit in walker:
    headline = commit.message.splitlines()[0]
    if headline.startswith('BRANCH_MARKER: '):
        name = headline.split('BRANCH_MARKER: ')[1]
        repo.branches.local.create(name, commit, force=True)
        print(f"Created branch {name} at {commit.short_id}")

if child:
    print(f"Waiting for PID {child.pid} to finish")
    child.wait()

repo.remotes['korg'].push(['+next/master:refs/heads/next_master',
                           'origin/master:refs/heads/master', '+work:refs/heads/devel'],
                          callbacks=MyRemoteCallbacks())
repo.checkout('refs/heads/work')

subprocess.Popen(['make', 'O=../build/bu', 'tags'], start_new_session=True)
