#!/usr/bin/env python

# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Build packages on a host machine, then install them on the local target.

Contacts a devserver (trunk/src/platform/dev/devserver.py) and
requests that it build a package, then performs a binary install of
that package on the local machine.
"""

import optparse
import os
import shutil
import subprocess
import sys
import urllib
import urllib2


class GMerger(object):
  """emerges a package from the devserver.

  NB:  Must be instantiated using with, e.g.:
    with GMerger(open('/etc/lsb-release').readlines()) as merger:
  in order to remount /tmp as executable.
  """

  def __init__(self, lsb_release_lines):
    self.lsb_release = self.ParseLsbRelease(lsb_release_lines)
    try:
      self.devkit_url = self.lsb_release['CHROMEOS_DEVSERVER']
      self.board_name = self.lsb_release['CHROMEOS_RELEASE_BOARD']
    except KeyError, e:
      sys.exit('Could not find /etc/lsb_release value: ' + e)

  def RemountOrChangeRoot(self, environ):
    """Remount the root filesystem rw; install into /usr/local if this fails."""
    rc = subprocess.call(['mount', '-o', 'remount,rw', '/'])
    if rc == 0:
      return
    answer = raw_input(
        'Could not mount / as writable.  Install into /usr/local? (Y/n)')
    if answer[0] not in 'Yy':
      sys.exit('Better safe than sorry.')
    environ['ROOT'] = '/usr/local'

  def ParseLsbRelease(self, lsb_release_lines):
    """Convert a list of KEY=VALUE lines to a dictionary."""
    partitioned_lines = [line.rstrip().partition('=')
                         for line in lsb_release_lines]
    return dict([(fields[0], fields[2]) for fields in partitioned_lines])

  def SetupPortageEnvironment(self, environ):
    """Setup portage to use stateful partition and fetch from dev server."""
    environ.update({
        'PORTDIR': '/usr/local/portage',
        'PKGDIR': '/usr/local/portage',
        'DISTDIR': '/usr/local/portage/distfiles',
        'PORTAGE_BINHOST': '%s/static/pkgroot/%s/packages' % (
            self.devkit_url, self.board_name),
        'PORTAGE_TMPDIR': '/tmp',
        'CONFIG_PROTECT': '-*',
        'FEATURES': '-sandbox',
        'ACCEPT_KEYWORDS': 'arm x86 ~arm ~x86',
        'ROOT': '/',
        })

  def GeneratePackageRequest(self, package_name):
    """Build the POST string that conveys our options to the devserver."""
    post_data = {'board': self.board_name,
                 'pkg': package_name,
                 'use': FLAGS.use,
                 'accept_stable': FLAGS.accept_stable,
                }
    post_data = dict([(key, value) for (key, value) in post_data.iteritems()
                      if value])
    return urllib.urlencode(post_data)

  def RequestPackageBuild(self, package_name):
    """Contacts devserver to request a build."""
    try:
      result = urllib2.urlopen(self.devkit_url + '/build',
                               data=self.GeneratePackageRequest(package_name))
      print result.read()
      result.close()

    except urllib2.HTTPError, e:
      # The exception includes the content, which is the error mesage
      sys.exit(e.read())


def main():
  global FLAGS
  parser = optparse.OptionParser(usage='usage: %prog [options] package_name')
  parser.add_option('--accept_stable',
                    action='store_true', dest='accept_stable', default=False,
                    help=('Build even if a cros_workon package is not '
                          'using the live package'))
  parser.add_option('-n', '--no_devserver',
                    action='store_false', dest='call_devserver', default=True,
                    help='Do not actually ask the server to build')
  parser.add_option('--use', '--USE',
                    dest='use', default=None,
                    help='USE flags to pass to emerge on the server')

  (FLAGS, remaining_arguments) = parser.parse_args()
  if len(remaining_arguments) != 1:
    parser.print_help()
    sys.exit('Need exactly one package name')

  package_name = remaining_arguments[0]

  try:
    subprocess.check_call(['mount', '-o', 'remount,exec', '/tmp'])
    merger = GMerger(open('/etc/lsb-release').readlines())
    merger.SetupPortageEnvironment(os.environ)
    merger.RemountOrChangeRoot(os.environ)
    if FLAGS.call_devserver:
      merger.RequestPackageBuild(package_name)
    else:
      print 'Not requesting fresh build on server---installing whatever we find'

    print 'Emerging ', package_name
    subprocess.check_call([
        'emerge', '--getbinpkgonly', '--usepkgonly', package_name])
  finally:
    subprocess.call(['mount', '-o', 'remount,noexec', '/tmp'])


if __name__ == '__main__':
  main()
