#!/usr/bin/python3

import sys
from collections.abc import Mapping
from pathlib import Path
from pprint import pprint

gitdir = Path('.git')

if not gitdir.is_dir():
    sys.exit(0)

import sh
from sh import git, Command
try:
    import tomllib
except ModuleNotFoundError:
    import tomli as tomllib
from pristine_lfs import do_checkout, do_commit

package = 'matrix-synapse'

def read_dependencies(branch):
    Cargo_toml = git('cat-file', 'blob', f'{branch}:rust/Cargo.toml')
    parsed = tomllib.loads(Cargo_toml)
    deps = parsed['dependencies']
    if 'build-dependencies' in parsed:
        deps.update(parsed['build-dependencies'])
    return {p: (v['version'] if isinstance(v, Mapping) else v) for p, v in deps.items()}

v = "upstream/latest"
new_deps = read_dependencies(f'{v}')
old_deps = read_dependencies(f'{v}^')
# pprint(new_deps)
# pprint(old_deps)

dep_diff = {
    p: (old_deps.get(p), v)
    for p, v in new_deps.items()
    if old_deps.get(p) != v
}

def is_interesting(v1, v2):
    if v1 is None:
        return True
    if v1.startswith("0."):
        if v1.split('.')[:2] == v2.split('.')[:2]:
            return False
    else:
        if v1.split('.')[:1] == v2.split('.')[:1]:
            return False
    return True

dep_diff = {
    p: vv
    for p, vv in dep_diff.items()
    if is_interesting(*vv)
}

def setup_logging():
    import logging
    logging.basicConfig(format='{levelname[0]}: {message!s}', style='{',
                        level=(logging.WARNING - 10))
    logging.getLogger(sh.__name__).setLevel(logging.WARNING)

def version_for_commit(commit):
    pyproject_toml = git('cat-file', 'blob', f'{commit}:pyproject.toml')
    pyproject = tomllib.loads(pyproject_toml)
    return pyproject['tool']['poetry']['version']

def reuse_vendor():
    print("No significant changes detected, reusing vendored dependencies")
    git('checkout', 'HEAD^', '--', 'vendor/')
    git('commit', '--amend', '--no-edit')
    version = version_for_commit('HEAD^')
    new_version = version_for_commit('HEAD')
    setup_logging()
    p = Path(f"../{package}_{new_version}.orig-vendor.tar.xz")
    if new_version != version:
        do_checkout(branch="pristine-lfs", version=version, outdir='..')
        p.unlink(missing_ok=True)
        p.symlink_to(f"{package}_{version}.orig-vendor.tar.xz")
    with p.open(mode="rb") as tarball:
        do_commit(tarball=tarball, branch="pristine-lfs")

def revendor():
    print("Significant changes detected, revendoring")
    rules = Command('debian/rules')
    rules('vendor')
    git('add', '-f', 'vendor/')
    git('commit', '--amend', '--no-edit')
    new_version = version_for_commit('HEAD')
    setup_logging()
    p = Path(f"../{package}_{new_version}.orig-vendor.tar.xz")
    with p.open(mode="rb") as tarball:
        do_commit(tarball=tarball, branch="pristine-lfs")

if not dep_diff:
    reuse_vendor()
else:
    pprint(dep_diff)
    revendor()
