#!/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."""
    binhost_prefix = '%s/static/pkgroot/%s' % (self.devkit_url, self.board_name)
    binhost = '%s/packages' % binhost_prefix
    if not FLAGS.include_masked_files:
      binhost += ' %s/gmerge-packages' % binhost_prefix
    environ.update({
        'PORTDIR': '/usr/local/portage',
        'PKGDIR': '/usr/local/portage',
        'DISTDIR': '/usr/local/portage/distfiles',
        'PORTAGE_BINHOST': binhost,
        'PORTAGE_TMPDIR': '/tmp',
        'CONFIG_PROTECT': '-*',
        'FEATURES': '-sandbox',
        'ACCEPT_KEYWORDS': 'arm x86 ~arm ~x86',
        'ROOT': os.environ.get('ROOT', '/'),
        'PORTAGE_CONFIGROOT': '/usr/local'
        })

  def GeneratePackageRequest(self, package_name):
    """Build the POST string that conveys our options to the devserver."""
    post_data = {'board': self.board_name,
                 'deep': FLAGS.deep or '',
                 'pkg': package_name,
                 'features': os.environ.get('FEATURES'),
                 'use': os.environ.get('USE'),
                 'accept_stable': FLAGS.accept_stable or '',
                 'usepkg': FLAGS.usepkg or '',
                }
    post_data = dict([(key, value) for (key, value) in post_data.iteritems()
                      if value is not None])
    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())
    except urllib2.URLError, e:
      sys.exit('Could not reach devserver. Reason: %s' % e.reason)


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('--include_masked_files',
                    action='store_true', dest='include_masked_files',
                    default=False, help=('Include masked files in package '
                                         '(e.g. debug symbols)'))
  parser.add_option('-n', '--usepkg',
                    action='store_true', dest='usepkg', default=False,
                    help='Use currently built binary packages on server.')
  parser.add_option('-D', '--deep',
                    action='store_true', dest='deep', default=False,
                    help='Update package and all dependencies '
                         '(requires --usepkg).')
  parser.add_option('-x', '--extra', dest='extra', default='',
                    help='Extra arguments to pass to emerge command.')

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

  # TODO(davidjames): Should we allow --deep without --usepkg? Not sure what
  # the desired behavior should be in this case, so disabling the combo for
  # now.
  if FLAGS.deep and not FLAGS.usepkg:
    sys.exit('If using --deep, --usepkg must also be enabled.')

  package_name = remaining_arguments[0]

  try:
    subprocess.check_call(['mount', '-o', 'remount,exec', '/tmp'])
    merger = GMerger(open('/etc/lsb-release').readlines())
    merger.RequestPackageBuild(package_name)

    print 'Emerging ', package_name
    merger.SetupPortageEnvironment(os.environ)
    merger.RemountOrChangeRoot(os.environ)
    subprocess.check_call(['rm', '-rf', '/usr/local/portage',
                           '/var/cache/edb/binhost'])
    emerge_args = 'emerge --getbinpkgonly --usepkgonly --verbose'
    if FLAGS.deep:
      emerge_args += ' --update --deep'
    if FLAGS.extra:
      emerge_args += ' ' + FLAGS.extra
    emerge_args += ' ' + package_name
    subprocess.check_call(emerge_args, shell=True)
  finally:
    subprocess.call(['mount', '-o', 'remount,noexec', '/tmp'])


if __name__ == '__main__':
  main()
