#!/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,
                 'features': os.environ.get('FEATURES', None),
                 'use': os.environ.get('USE', None),
                 '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')

  (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())
    if FLAGS.call_devserver:
      merger.RequestPackageBuild(package_name)
    else:
      print 'Not requesting fresh build on server---installing whatever we find'

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


if __name__ == '__main__':
  main()
