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 |