#!/usr/bin/python
#
#    promulgate - makes a charm recipe branch the official one
#
#    Copyright (C) 2011  Canonical Ltd.
#    Author: Francis J. Lacoste <francis.lacoste@canonical.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 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

from launchpadlib.launchpad import Launchpad
from lazr.restfulclient.errors import BadRequest, NotFound

import os
import sys

from optparse import OptionParser

from bzrlib import bzrdir
from bzrlib.plugins.launchpad import lp_api

import yaml

import logging

DISTRIBUTION = 'charms'
REVIEW_TEAM_NAME = 'charmers'
OFFICIAL_BRANCH_POCKET = 'Release'
OFFICAL_BRANCH_STATUS = 'Mature'

def main(argv):
    parser = OptionParser(usage='usage: %prog [options] <charm_dir>')
    parser.add_option(
        '-b', '--branch', dest='branch', default=None,
        help='The location of the charm public branch. Will be determined '
        'from the bzr configuration if omitted.')
    parser.add_option(
        '-s', '--series', dest='series', default=None,
        help='The distribution series on which to set the official branch. '
        'Defaults to setting it in the current development series.')
    parser.add_option(
        '-t', '--lp-instance', dest='lp_instance', default='production',
        help="The Launchpad instance to use. Defaults to production, but "
        "staging' or 'qastaging' might be used for testing.")
    parser.add_option(
        '-v', '--verbose', dest='verbose', action='count', default=0,
        help='Increase verbosity level.')
    options, args = parser.parse_args()

    if options.verbose >= 2:
        level = logging.DEBUG
    elif options.verbose >= 1:
        level = logging.INFO
    else:
        level = logging.WARNING
    logging.basicConfig(level=level, format='%(levelname)s:%(message)s')

    if len(args):
        charm_dir = args[0]
    else:
        charm_dir = '.'

    charm_metadata = os.path.join(charm_dir, 'metadata.yaml')
    if not os.access(charm_metadata, os.R_OK):
        logging.error("can't read charm metadata: %s", charm_metadata)

    with open(charm_metadata, 'r') as metadata:
        charm = yaml.load(metadata)

    logging.debug('login with %s launchpad:', options.lp_instance)
    lp = Launchpad.login_with('promulgate', options.lp_instance)

    if options.branch is None:
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
            charm_dir)
        push_location = branch.get_push_location()
        if push_location is None:
            logging.error("Branch has not been pushed.")
            return 1
        charm_branch = lp.branches.getByUrl(url=push_location)
        if charm_branch is None:
            logging.error("can't determine Launchpad branch from bzr branch")
            return 1
    else:
        charm_branch = lp.branches.getByUrl(url=options.branch)
        if charm_branch is None:
            logging.error("can't find branch on Launchpad: %s", options.branch)
            return 1

    logging.info(
        "Setting status of %s to %s", charm_branch.bzr_identity,
        OFFICAL_BRANCH_STATUS)
    charm_branch.lifecycle_status = OFFICAL_BRANCH_STATUS
    logging.info(
        "Setting reviewer of %s to %s", charm_branch.bzr_identity,
        REVIEW_TEAM_NAME)
    charm_branch.reviewer = lp.people[REVIEW_TEAM_NAME]
    charm_branch.lp_save()

    charm_distro = lp.distributions[DISTRIBUTION]
    if options.series is None:
        charm_series = charm_distro.current_series
    else:
        try:
            charm_series = charm_distro.getSeries(
                name_or_version=options.series)
        except (BadRequest, NotFound), e:
            # XXX flacoste 2011-06-15 bug=797917
            # Should only be NotFound.
            if e.content.startswith('No such distribution series:'):
                logging.error("can't find series '%s'", options.series)
                return 1
            else:
                raise

    lp_charm = charm_series.getSourcePackage(name=charm['name'])
    logging.info(
        'Setting %s as the official branch for %s',
        charm_branch.bzr_identity, lp_charm.name)
    lp_charm.setBranch(branch=charm_branch, pocket=OFFICIAL_BRANCH_POCKET)

    return 0




if __name__ == '__main__':
    sys.exit(main(sys.argv))

