#!/usr/bin/python
# Copyright Cloud Linux Zug GmbH

__author__ = 'iseletsk'

import errno
import getopt
import shutil
import os
from os.path import join
import sys

BASE_DIR = '/usr/share/kcare-eportal/patches/'
LATEST_DIR = join(BASE_DIR, "release", "release-latest")


def link_file(name, dir, dest_dir):
    full_name = join(dest_dir, name)
    if os.path.exists(full_name) and not os.path.islink(full_name):
        os.unlink(full_name)
    if not os.path.exists(full_name):
        try:
            link_name = join(LATEST_DIR, dir, name)
            os.symlink(link_name, full_name)
        except OSError, e:
            if e.errno == errno.EEXIST:
                pass
            else:
                raise e


def link_dir(dir):
    print "Processing %s" % dir
    dest_dir = join(BASE_DIR, dir)
    src_dir = join(SOURCE_DIR, dir)

    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)

    for latest in ('latest.v2', 'latest.v1'):
        path = join(src_dir, latest)
        if os.path.exists(path):
            with open(path) as f:
                release = f.read()
            break
    else:
        raise IOError('Unable to find release number. File %s not found.'
                      % join(src_dir, 'latest.vX'))

    try:
        release_level = int(release)
    except (ValueError, TypeError) as e:
        raise Exception("Unable to parse release number: %s" % e)

    release_dir = join(dest_dir, release)
    if os.path.lexists(release_dir):
        try:
            os.unlink(release_dir)
        except OSError, e:
            if e.errno == errno.EISDIR:
                shutil.rmtree(release_dir)
            else:
                raise e

    os.symlink(join(src_dir, release), release_dir)

    # process fixups
    prev_release_level = release_level - 1
    prev_release_dir = join(dest_dir, str(prev_release_level))
    prev_src_dir = join(src_dir, str(prev_release_level))
    if prev_release_level > 0 and os.path.exists(prev_src_dir):
        kpatch_fixups_file = os.path.join(prev_src_dir, 'kpatch.fixups')
        if os.path.exists(kpatch_fixups_file):
            kpatch_fixups_dest = join(prev_release_dir, 'kpatch.fixups')
            shutil.copy(kpatch_fixups_file, kpatch_fixups_dest)

            with open(kpatch_fixups_file) as f:
                for fixup_basename in f:
                    fixup_basename = fixup_basename.strip()
                    if not fixup_basename:
                        continue

                    fixup_src_name = join(prev_src_dir, fixup_basename)
                    fixup_dest_name = join(prev_release_dir, fixup_basename)
                    shutil.copy(fixup_src_name, fixup_dest_name)

    link_file('kcare.ko', dir, dest_dir)
    link_file('kcare.ko.sig', dir, dest_dir)
    link_file('version', dir, dest_dir)
    link_file(latest, dir, dest_dir)

    # do release-latest
    rl_dir = join(LATEST_DIR, dir)
    if os.path.exists(rl_dir) and os.path.islink(rl_dir):
        os.unlink(rl_dir)
    os.symlink(src_dir, rl_dir)


def link_json():
    lpatches = join(LATEST_DIR, 'patches.json')
    if os.path.exists(lpatches):
        os.unlink(lpatches)
    os.symlink(join(SOURCE_DIR, 'patches.json'), lpatches)
    base_patches_json = join(BASE_DIR, 'patches.json')
    if not os.path.exists(base_patches_json):
        os.symlink(lpatches, base_patches_json)


def process_latest():
    for dir in os.listdir(SOURCE_DIR):
        dirname = join(SOURCE_DIR, dir)
        if os.path.isdir(dirname):
            link_dir(dir)
        link_json()
    print "All Done"


def usage():
    print 'Usage: %s [OPTIONS] release_tag' % (sys.argv[0])
    print
    print 'deploys release RELEASE_TAG as latest release'
    print 'patches for the RELEASE_TAG should be located in ' \
          '/usr/share/kcare-eportal/patches/release/RELEASE_TAG'
    print '-p | --production         : deploy to production, otherwise test assumed'
    print '-h | --help               : show this help'
    print '--24h                     : deploy to 24h folder'
    print '--48h                     : deploy to 48h folder'


def main():
    global BASE_DIR, SOURCE_DIR, LATEST_DIR
    try:
        opts, args = getopt.getopt(
            sys.argv[1:],
            'h:p', ['production', 'help', '24h', '48h'])
    except getopt.GetoptError, e:
        print "ERROR: %s" %(str(e),)
        usage()
        sys.exit(1)

    prefix = 'test/'
    for o, a in opts:
        if o in ['-h', '--help']:
            usage()
            sys.exit(0)
        elif o in ['-p', '--production']:
            prefix = ''
        elif o in ['--24h']:
            prefix = '24h/'
        elif o in ['--48h']:
            prefix = '48h/'
    if len(args) != 1:
        print "RELEASE TAG required"
        usage()
        sys.exit(1)

    BASE_DIR = join(BASE_DIR, prefix)
    SOURCE_DIR = join(BASE_DIR, 'release', args[0])
    LATEST_DIR = join(BASE_DIR, 'release', 'release-latest')
    if not os.path.exists(SOURCE_DIR):
        print "%s doesn't exist" % SOURCE_DIR
        sys.exit(1)
    if not os.path.exists(LATEST_DIR):
        try:
            os.makedirs(LATEST_DIR)
        except OSError as e:
            print "Unable to create %s: %s" % (LATEST_DIR, e)
            sys.exit(1)
    if not prefix:
        deploy_type = "PRODUCTION"
    else:
        deploy_type = prefix[:-1].upper()

    print "Deploying to %s, release %s" % (deploy_type, args[0])
    process_latest()


if __name__ == '__main__':
    main()
