Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/bin/bash | 1 #!/usr/bin/env python |
|
sosa
2011/01/14 23:03:54
Never seen this style before ...
rochberg
2011/01/15 06:16:48
This is so we can run even if python is in /usr/lo
| |
| 2 | 2 |
| 3 # Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
|
sosa
2011/01/14 23:03:54
Maybe add a module docstring.
rochberg
2011/01/15 06:16:48
Done.
| |
| 6 | 6 |
| 7 # Prints the arguments and dies. | 7 import optparse |
| 8 print_and_die() { | 8 import os |
| 9 echo $* | 9 import shutil |
| 10 exit 1 | 10 import subprocess |
| 11 } | 11 import sys |
| 12 import urllib | |
| 13 import urllib2 | |
| 12 | 14 |
| 13 # Set up PORTAGE variables to be rooted in /usr/local/portage. | |
| 14 setup_portage_vars() { | |
| 15 export PORTDIR=/usr/local/portage | |
| 16 export PKGDIR=/usr/local/portage | |
| 17 export DISTDIR=/usr/local/portage/distfiles | |
| 18 export PORTAGE_BINHOST="${DEVKIT_URL}/static/pkgroot/${BOARD_NAME}/packages" | |
| 19 export PORTAGE_TMPDIR=/tmp | |
| 20 export CONFIG_PROTECT="-*" | |
| 21 export FEATURES="-sandbox" | |
| 22 # Accept keywords only for stable ebuilds by default. | |
| 23 [ -z "$ACCEPT_KEYWORDS" ] && ACCEPT_KEYWORDS="arm x86 ~arm ~x86" | |
| 24 export ACCEPT_KEYWORDS | |
| 25 export ROOT=/ | |
| 26 } | |
| 27 | 15 |
| 28 # Prompts the user to change the root to /usr/local. | 16 PARSER = optparse.OptionParser() |
|
sosa
2011/01/14 23:03:54
Why did you choose to make this global rather than
sosa
2011/01/14 23:03:54
usage?
rochberg
2011/01/15 06:16:48
Done.
rochberg
2011/01/15 06:16:48
Done.
| |
| 29 change_portage_root() { | 17 PARSER.add_option('--accept_stable', |
| 30 read -p "Do you wish to install this program into /usr/local? (Y/n) " input | 18 action='store_true', dest='accept_stable', default=False, |
| 31 if [[ ${input} = [Nn]* ]]; then | 19 help=('Build even if a cros_workon package is not ' |
| 32 echo "Better safe than sorry." | 20 'using the live package')) |
| 33 exit 1 | 21 PARSER.add_option('-n', '--no_devserver', |
| 34 fi | 22 action='store_false', dest='call_devserver', default=True, |
| 35 export ROOT=/usr/local | 23 help='Do not actually ask the server to build') |
| 36 } | 24 PARSER.add_option('--use', |
| 25 dest='use', default=None, | |
| 26 help='USE flags to pass to emerge on the server') | |
| 37 | 27 |
| 38 set -e | |
| 39 | 28 |
| 40 # Get variables for the devserver from the lsb-release file. | 29 class GMerger(object): |
| 41 DEVKIT_URL=$(grep ^CHROMEOS_DEVSERVER /etc/lsb-release | cut -d = -f 2-) | 30 """emerges a package from the devserver. |
| 42 BOARD_NAME=$(grep ^CHROMEOS_RELEASE_BOARD /etc/lsb-release | cut -d = -f 2-) | |
| 43 [ -z "${BOARD_NAME}" ] && print_and_die "No board in /etc/lsb-release" | |
| 44 [ -z "${DEVKIT_URL}" ] && print_and_die "No dev server url in /etc/lsb-release" | |
| 45 | 31 |
| 46 setup_portage_vars | 32 NB: Must be instantiated using with, e.g.: |
| 33 with GMerger(open('/etc/lsb-release').readlines()) as merger: | |
| 34 in order to remount /tmp as executable. | |
| 35 """ | |
| 47 | 36 |
| 48 # Determine if we should send a build command to the devserver. | 37 def __init__(self, lsb_release_lines): |
| 49 BUILD=1 | 38 self.lsb_release = self.ParseLsbRelease(lsb_release_lines) |
| 50 if [ x$1 == x-n ]; then | 39 try: |
| 51 BUILD=0 | 40 self.devkit_url = self.lsb_release['CHROMEOS_DEVSERVER'] |
| 52 shift | 41 self.board_name = self.lsb_release['CHROMEOS_RELEASE_BOARD'] |
| 53 fi | 42 except KeyError, e: |
| 43 sys.exit('Could not find /etc/lsb_release value: ' + e) | |
| 54 | 44 |
| 55 # Package name is the last argument. | 45 def RemountOrChangeRoot(self, environ): |
|
sosa
2011/01/14 23:03:54
Please add at least one line doc strings to each m
rochberg
2011/01/15 06:16:48
Done.
| |
| 56 # TODO(sosa) - Support multiple packages. | 46 rc = subprocess.call(['mount', '-o', 'remount,rw', '/']) |
| 57 PACKAGE_NAME=${!#} | 47 if rc == 0: |
| 48 return | |
| 49 answer = raw_input( | |
| 50 'Could not mount / as writable. Install into /usr/local? (Y/n)') | |
| 51 if answer[0] not in 'Yy': | |
| 52 sys.exit('Better safe than sorry.') | |
| 53 environ['ROOT'] = '/usr/local' | |
| 58 | 54 |
| 59 # If no package name is provided skip to emerge options. | 55 def CleanPortageCache(self): |
| 60 [[ ${PACKAGE_NAME} == -* ]] && BUILD=0 | 56 shutil.rmtree(os.path.join(os.environ['PKGDIR'], 'packages'), |
| 57 ignore_errors=True) | |
|
sosa
2011/01/14 23:03:54
This is somewhat functionally different than the o
rochberg
2011/01/15 06:16:48
First of all, the ignore_errors bit was due to som
| |
| 61 | 58 |
| 62 mount -o remount,rw / || change_portage_root | 59 def ParseLsbRelease(self, lsb_release_lines): |
| 60 """Convert a list of KEY=VALUE lines to a dictionary.""" | |
| 61 partitioned_lines = [line.rstrip().partition('=') | |
| 62 for line in lsb_release_lines] | |
| 63 return dict([(fields[0], fields[2]) for fields in partitioned_lines]) | |
| 63 | 64 |
| 64 # Re-mount /tmp as exec. | 65 def SetupPortageEnvironment(self, environ): |
| 65 mount -o remount,exec /tmp | 66 environ.update({ |
| 66 trap "mount -o remount,noexec /tmp" EXIT | 67 'PORTDIR': '/usr/local/portage', |
| 68 'PKGDIR': '/usr/local/portage', | |
| 69 'DISTDIR': '/usr/local/portage/distfiles', | |
| 70 'PORTAGE_BINHOST': '%s/static/pkgroot/%s/packages' % ( | |
| 71 self.devkit_url, self.board_name), | |
| 72 'PORTAGE_TMPDIR': '/tmp', | |
| 73 'CONFIG_PROTECT': '-*', | |
| 74 'FEATURES': '-sandbox', | |
| 75 'ACCEPT_KEYWORDS': 'arm x86 ~arm ~x86', | |
| 76 'ROOT': '/', | |
| 77 }) | |
| 67 | 78 |
| 68 # Delete the local binary package cache. | 79 def GeneratePackageRequest(self, package_name): |
| 69 rm -rf "${PKGDIR}/packages" | 80 post_data = {'board': self.board_name, |
| 81 'pkg': package_name, | |
| 82 'use': FLAGS.use, | |
| 83 'accept_stable': FLAGS.accept_stable, | |
| 84 } | |
| 85 post_data = dict([(key, value) for (key, value) in post_data.iteritems() | |
| 86 if value]) | |
| 87 return urllib.urlencode(post_data) | |
| 70 | 88 |
| 71 if [ ${BUILD} == 1 ]; then | 89 def RequestPackageBuild(self, package_name): |
| 72 echo "Building ${PACKAGE_NAME}" | 90 try: |
| 73 ESCAPED_PACKAGE=$(python -c \ | 91 result = urllib2.urlopen(self.devkit_url + '/build', |
| 74 "import urllib; print urllib.quote('''${PACKAGE_NAME}''')") | 92 data=self. GeneratePackageRequest(package_name)) |
| 75 ESCAPED_BOARD=$(python -c \ | 93 print result.read() |
|
sosa
2011/01/14 23:03:54
result.close()?
rochberg
2011/01/15 06:16:48
Done.
| |
| 76 "import urllib; print urllib.quote('''${BOARD_NAME}''')") | |
| 77 | 94 |
| 78 wget $DEVKIT_URL/build \ | 95 except urllib2.HTTPError, e: |
| 79 --post-data="pkg=${ESCAPED_PACKAGE}&board=${ESCAPED_BOARD}" | 96 # The exception includes the content, which is the error mesage |
| 80 fi | 97 print e.read() |
| 98 sys.exit(1) | |
|
sosa
2011/01/14 23:03:54
sys.exit(e.read())?
rochberg
2011/01/15 06:16:48
Done.
| |
| 81 | 99 |
| 82 echo "Emerging ${PACKAGE_NAME}" | 100 |
| 83 emerge --getbinpkgonly --usepkgonly "$@" | 101 def main(): |
| 102 global FLAGS | |
| 103 (FLAGS, remaining_arguments) = PARSER.parse_args() | |
| 104 if len(remaining_arguments) != 1: | |
|
sosa
2011/01/14 23:03:54
So this removes the ability to to do gmerge -n -h?
rochberg
2011/01/15 06:16:48
gmerge --help works, but gmerge -n -h as help for
| |
| 105 sys.exit('Usage: gmerge package_name') | |
|
sosa
2011/01/14 23:03:54
It makes it a little easier to read to have a line
rochberg
2011/01/15 06:16:48
Done.
| |
| 106 package_name = remaining_arguments[0] | |
| 107 | |
| 108 try: | |
| 109 subprocess.check_call(['mount', '-o', 'remount,exec', '/tmp']) | |
| 110 merger = GMerger(open('/etc/lsb-release').readlines()) | |
|
sosa
2011/01/14 23:03:54
Why not just pass the path?
rochberg
2011/01/15 06:16:48
Easier to test.
| |
| 111 merger.SetupPortageEnvironment(os.environ) | |
| 112 merger.RemountOrChangeRoot(os.environ) | |
| 113 merger.CleanPortageCache() | |
| 114 if FLAGS.call_devserver: | |
| 115 merger.RequestPackageBuild(package_name) | |
| 116 else: | |
| 117 print 'Not requesting fresh build on server---installing whatever we find' | |
| 118 | |
| 119 print 'Emerging ', package_name | |
| 120 subprocess.call(['emerge', '--getbinpkgonly', '--usepkgonly', package_name]) | |
|
sosa
2011/01/14 23:03:54
check_call?
rochberg
2011/01/15 06:16:48
Done.
| |
| 121 finally: | |
| 122 subprocess.call(['mount', '-o', 'remount,noexec', '/tmp']) | |
| 123 | |
| 124 | |
| 125 if __name__ == '__main__': | |
| 126 main() | |
| OLD | NEW |