Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Unified Diff: gmerge

Issue 6305004: Modify devserver and gmerge to be friendlier (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/dev-util.git@master
Patch Set: Numerous code review fixes. Added --USE flag as well Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « devserver.py ('k') | gmerge_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gmerge
diff --git a/gmerge b/gmerge
index e6426d0ffede672e7c2aeb257b35ed4e9efa08ad..363233f187c91e1cd538939322e8fb8624937be4 100755
--- a/gmerge
+++ b/gmerge
@@ -1,83 +1,134 @@
-#!/bin/bash
+#!/usr/bin/env python
-# Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved.
+# 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.
-# Prints the arguments and dies.
-print_and_die() {
- echo $*
- exit 1
-}
-
-# Set up PORTAGE variables to be rooted in /usr/local/portage.
-setup_portage_vars() {
- export PORTDIR=/usr/local/portage
- export PKGDIR=/usr/local/portage
- export DISTDIR=/usr/local/portage/distfiles
- export PORTAGE_BINHOST="${DEVKIT_URL}/static/pkgroot/${BOARD_NAME}/packages"
- export PORTAGE_TMPDIR=/tmp
- export CONFIG_PROTECT="-*"
- export FEATURES="-sandbox"
- # Accept keywords only for stable ebuilds by default.
- [ -z "$ACCEPT_KEYWORDS" ] && ACCEPT_KEYWORDS="arm x86 ~arm ~x86"
- export ACCEPT_KEYWORDS
- export ROOT=/
-}
-
-# Prompts the user to change the root to /usr/local.
-change_portage_root() {
- read -p "Do you wish to install this program into /usr/local? (Y/n) " input
- if [[ ${input} = [Nn]* ]]; then
- echo "Better safe than sorry."
- exit 1
- fi
- export ROOT=/usr/local
-}
-
-set -e
-
-# Get variables for the devserver from the lsb-release file.
-DEVKIT_URL=$(grep ^CHROMEOS_DEVSERVER /etc/lsb-release | cut -d = -f 2-)
-BOARD_NAME=$(grep ^CHROMEOS_RELEASE_BOARD /etc/lsb-release | cut -d = -f 2-)
-[ -z "${BOARD_NAME}" ] && print_and_die "No board in /etc/lsb-release"
-[ -z "${DEVKIT_URL}" ] && print_and_die "No dev server url in /etc/lsb-release"
-
-setup_portage_vars
-
-# Determine if we should send a build command to the devserver.
-BUILD=1
-if [ x$1 == x-n ]; then
- BUILD=0
- shift
-fi
-
-# Package name is the last argument.
-# TODO(sosa) - Support multiple packages.
-PACKAGE_NAME=${!#}
-
-# If no package name is provided skip to emerge options.
-[[ ${PACKAGE_NAME} == -* ]] && BUILD=0
-
-mount -o remount,rw / || change_portage_root
-
-# Re-mount /tmp as exec.
-mount -o remount,exec /tmp
-trap "mount -o remount,noexec /tmp" EXIT
-
-# Delete the local binary package cache.
-rm -rf "${PKGDIR}/packages"
-
-if [ ${BUILD} == 1 ]; then
- echo "Building ${PACKAGE_NAME}"
- ESCAPED_PACKAGE=$(python -c \
- "import urllib; print urllib.quote('''${PACKAGE_NAME}''')")
- ESCAPED_BOARD=$(python -c \
- "import urllib; print urllib.quote('''${BOARD_NAME}''')")
-
- wget $DEVKIT_URL/build \
- --post-data="pkg=${ESCAPED_PACKAGE}&board=${ESCAPED_BOARD}"
-fi
-
-echo "Emerging ${PACKAGE_NAME}"
-emerge --getbinpkgonly --usepkgonly "$@"
+"""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()
« no previous file with comments | « devserver.py ('k') | gmerge_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698