forked from coreos/dev-util
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgmerge
executable file
·136 lines (115 loc) · 5.1 KB
/
gmerge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/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 subprocess
import sys
import urllib
import urllib2
class GMerger(object):
"""emerges a package from the devserver."""
def __init__(self, conf_lines):
self.update_conf = self.ParseUpdateConf(conf_lines)
try:
self.devkit_url = self.update_conf['DEVSERVER']
self.board_name = self.update_conf['COREOS_RELEASE_BOARD']
except KeyError as e:
sys.exit('Could not find /etc/coreos/update.conf value: ' + e.message)
def ParseUpdateConf(self, conf_lines):
"""Convert a list of KEY=VALUE lines to a dictionary."""
partitioned_lines = [line.rstrip().partition('=')
for line in conf_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({
'PKGDIR': '/var/tmp/portage',
'DISTDIR': '/var/tmp/portage/distfiles',
'PORTAGE_BINHOST': binhost,
'PORTAGE_TMPDIR': '/var/tmp',
'CONFIG_PROTECT': '-*',
'ACCEPT_KEYWORDS': '**',
})
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))
sys.stdout.write(result.read() + '\n')
result.close()
except urllib2.HTTPError as e:
# The exception includes the content, which is the error mesage
sys.exit(e.read())
except urllib2.URLError as 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]
with open('/usr/share/coreos/release') as conf:
conf_data = conf.readlines()
with open('/etc/coreos/update.conf') as conf:
conf_data += conf.readlines()
merger = GMerger(conf_data)
merger.RequestPackageBuild(package_name)
sys.stdout.write("Emerging %s\n" % package_name)
merger.SetupPortageEnvironment(os.environ)
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)
if __name__ == '__main__':
main()