#!/usr/bin/python
# based on:
# fedpkg - a script to interact with the Fedora Packaging system
#
# Copyright (C) 2011 Red Hat Inc.
# Author(s): clime <clime@redhat.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
# the full text of the license.

import ConfigParser
import argparse
import fedpkg
import logging
import os
import posixpath
import pyrpkg
import re
import sys
import urlparse

from pyrpkg.utils import cached_property
from pyrpkg.lookaside import CGILookasideCache

from fedpkg.lookaside import FedoraLookasideCache


class CoprCommands(fedpkg.Commands):

    @cached_property
    def lookasidecache(self):
        """A helper to interact with the lookaside cache

        We override this because we need a different download path.
        """
        try:
            if self.push_url:
                parsed_url = urlparse.urlparse(self.push_url)
                parts = posixpath.normpath(parsed_url.path).split("/")
                username, projectname = parts[-3], parts[-2]
        except pyrpkg.rpkgError:
            self.log.info('Failed to get module name from Git url or pushurl')

        return FedoraLookasideCache(
            self.lookasidehash, os.path.join(self.lookaside, username, projectname), self.lookaside_cgi,
            client_cert=self.cert_file, ca_cert=self.ca_cert)

    # this method can be removed once
    # https://pagure.io/fedpkg/pull-request/25
    # is merged
    def load_rpmdefines(self):
        """Populate rpmdefines based on branch data"""
        try:
            return super(CoprCommands, self).load_rpmdefines()
        except pyrpkg.rpkgError:
            pass
        if re.match(r'custom\d$', self.branch_merge):
            self._distval = self.branch_merge[6]
            self._distvar = 'custom'
            self.dist = 'custom%s' % self._distval
            self.mockconfig = 'custom-%s-%s' % (self._distval, self.localarch)
            self.override = '%s-override' % self.branch_merge
            self._distunset = 'rhel'
        elif re.match(r'mga\d$', self.branch_merge):
            self._distval = self.branch_merge[3]
            self._distvar = 'mageia'
            self.dist = 'mga%s' % self._distval
            self.mockconfig = 'mageia-%s-%s' % (self._distval, self.localarch)
            self.override = '%s-override' % self.branch_merge
            self._distunset = 'rhel'
        elif re.match(r'cauldron$', self.branch_merge):
            self._distval = '6'
            self._distvar = 'mageia'
            self.dist = 'cauldron'
            self.mockconfig = 'mageia-cauldron-%s' % self.localarch
            self.override = '%s-override' % self.branch_merge
            self._distunset = 'rhel'
        else:
            raise pyrpkg.rpkgError('Could not find the dist from branch name '
                                   '%s' % self.branch_merge)

        self._rpmdefines = ["--define '_sourcedir %s'" % self.path,
                            "--define '_specdir %s'" % self.path,
                            "--define '_builddir %s'" % self.path,
                            "--define '_srcrpmdir %s'" % self.path,
                            "--define '_rpmdir %s'" % self.path,
                            "--define 'dist .%s'" % self.dist,
                            "--define '%s %s'" % (self._distvar,
                                                  self._distval),
                            "--eval '%%undefine %s'" % self._distunset,
                            "--define '%mklibname(ds) %{_lib}%{1}%{?2:%{2}}%{?3:_%{3}}%{-s:-static}%{-d:-devel}'",
                            "--define '%mkrel(c:) %{-c: 0.%{-c*}.}%{1}%{?subrel:.%subrel}%{?dist:%dist}'",
                            "--define '%s 1'" % self.dist]
        if self._runtime_disttag:
            if self.dist != self._runtime_disttag:
                # This means that the runtime is known, and is different from
                # the target, so we need to unset the _runtime_disttag
                self._rpmdefines.append("--eval '%%undefine %s'" %
                                        self._runtime_disttag)


class fedpkgCoprClient(fedpkg.cli.fedpkgClient):
    def load_cmd(self):
        """This sets up the cmd object"""

        # Set target if we got it as an option
        target = None
        if hasattr(self.args, 'target') and self.args.target:
            target = self.args.target

        # load items from the config file
        items = dict(self.config.items(self.name, raw=True))

        # Create the cmd object
        self._cmd = CoprCommands(self.args.path,
                                       items['lookaside'],
                                       items['lookasidehash'],
                                       items['lookaside_cgi'],
                                       items['gitbaseurl'],
                                       items['anongiturl'],
                                       items['branchre'],
                                       items['kojiconfig'],
                                       items['build_client'],
                                       user=self.args.user,
                                       dist=self.args.dist,
                                       target=target,
                                       quiet=self.args.q,
                                       )

        self._cmd.module_name = self.args.module_name
        self._cmd.password = self.args.password
        self._cmd.runas = self.args.runas


def main():
    # Setup an argparser and parse the known commands to get the config file
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument('-C', '--config', help='Specify a config file to use',
                        default='/etc/rpkg/fedpkg-copr.conf')

    (args, other) = parser.parse_known_args()

    # Make sure we have a sane config file
    if not os.path.exists(args.config) and not other[-1] in ['--help', '-h', 'help']:
        sys.stderr.write('Invalid config file %s\n' % args.config)
        sys.exit(1)

    # Setup a configuration object and read config file data
    config = ConfigParser.SafeConfigParser()
    config.read(args.config)

    client = fedpkgCoprClient(config)
    client.do_imports(site='fedpkg')
    client.parse_cmdline()

    if not client.args.path:
        try:
            client.args.path = os.getcwd()
        except:
            print('Could not get current path, have you deleted it?')
            sys.exit(1)

    # setup the logger -- This logger will take things of INFO or DEBUG and
    # log it to stdout.  Anything above that (WARN, ERROR, CRITICAL) will go
    # to stderr.  Normal operation will show anything INFO and above.
    # Quiet hides INFO, while Verbose exposes DEBUG.  In all cases WARN or
    # higher are exposed (via stderr).
    log = pyrpkg.log
    client.setupLogging(log)

    if client.args.v:
        log.setLevel(logging.DEBUG)
    elif client.args.q:
        log.setLevel(logging.WARNING)
    else:
        log.setLevel(logging.INFO)

    # Run the necessary command
    try:
        sys.exit(client.args.command())
    except KeyboardInterrupt:
        pass
    except Exception, e:
        log.error('Could not execute %s: %s' % (client.args.command.__name__, e))
        if client.args.v:
            raise
        sys.exit(1)

if __name__ == "__main__":
    main()
