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

Side by Side Diff: devserver.py

Issue 6305004: Modify devserver and gmerge to be friendlier (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/dev-util.git@master
Patch Set: Actually implement --use 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | gmerge » ('j') | gmerge » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 # Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved. 3 # Copyright (c) 2009-2010 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.
6 6
7 """A CherryPy-based webserver to host images and build packages.""" 7 """A CherryPy-based webserver to host images and build packages."""
8 8
9 import cherrypy 9 import cherrypy
10 import optparse 10 import optparse
11 import os 11 import os
12 import subprocess
12 import sys 13 import sys
13 14
14 import autoupdate 15 import autoupdate
15 16
16 CACHED_ENTRIES=12 17 CACHED_ENTRIES=12
17 18
18 # Sets up global to share between classes. 19 # Sets up global to share between classes.
19 global updater 20 global updater
20 updater = None 21 updater = None
21 22
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 if image_dir != os.readlink('static/archive'): 63 if image_dir != os.readlink('static/archive'):
63 cherrypy.log('removing stale symlink to %s' % image_dir, 'DEVSERVER') 64 cherrypy.log('removing stale symlink to %s' % image_dir, 'DEVSERVER')
64 os.unlink('static/archive') 65 os.unlink('static/archive')
65 os.symlink(image_dir, 'static/archive') 66 os.symlink(image_dir, 'static/archive')
66 else: 67 else:
67 os.symlink(image_dir, 'static/archive') 68 os.symlink(image_dir, 'static/archive')
68 cherrypy.log('archive dir: %s ready to be used to serve images.' % image_dir, 69 cherrypy.log('archive dir: %s ready to be used to serve images.' % image_dir,
69 'DEVSERVER') 70 'DEVSERVER')
70 71
71 72
72 class DevServerRoot: 73 def _OutputOf(command):
74 """Runs command, a list of arguments beginning with an executable.
75
76 If the executable begins with "scripts/", the path is adjusted to
77 the scripts directory of this chroot.
78
79 Args:
80 A list of arguments, beginning with the executable
81 Returns:
82 A list of lines returned by the command
83 """
84
sosa 2011/01/14 23:03:54 Don't need this extra line
rochberg 2011/01/15 06:16:48 Done.
85 scripts = 'scripts/'
86 if command[0].find(scripts) == 0:
87 command[0] = command[0].replace(scripts, '../../' + scripts)
88 cherrypy.log('Executing: ' + ' '.join(command), 'BUILD')
89 output_blob = subprocess.Popen(command,
90 stdout=subprocess.PIPE).communicate()[0]
91 return [line.rstrip() for line in output_blob.split('\n')]
92
sosa 2011/01/14 23:03:54 2 lines between top level defs
93 def _IsIn(needle, haystack_list):
sosa 2011/01/14 23:03:54 Isn't this equivalent to needle in haystick_list?
rochberg 2011/01/15 06:16:48 The way the code is structured now, the relevant t
94 for line in haystack_list:
95 if needle in line:
96 return True
97 return False
98
sosa 2011/01/14 23:03:54 2 lines between top level defs
rochberg 2011/01/15 06:16:48 Done.
99 class Builder(object):
sosa 2011/01/14 23:03:54 Should probably move this into its own module.
rochberg 2011/01/15 06:16:48 Done.
100 def _ShouldBeWorkedOn(self, board, pkg):
101 """Is pkg a package that could be worked on, but is not?"""
102 if _IsIn(pkg, _OutputOf([
103 'scripts/cros_workon', '--board=' + board, 'list'])):
104 return False
105
106 # If it's in the list of possible workon targets, we should be working on it
107 return _IsIn(pkg, _OutputOf([
108 'scripts/cros_workon', '--board=' + board, 'list', '--all']))
109
110 def SetError(self, text):
111 cherrypy.response.status = 500
112 cherrypy.log(text, 'BUILD')
113 return text
114
115 def Build(self, board, pkg, additional_args):
116 cherrypy.log('Additional build request arguments: '+ str(additional_args),
117 'BUILD')
118
119 original_use = os.environ.get('USE', '')
120 if 'use' in additional_args:
121 os.environ['USE'] = original_use + ' ' + additional_args['use']
122 cherrypy.log("USE flags modified to " + os.environ['USE'], 'BUILD')
123
124 try:
125 if (self._ShouldBeWorkedOn(board, pkg) and
126 not additional_args.get('accept_stable')):
127 return self.SetError(
128 'Package is not cros_workon\'d on the devserver machine.\n'
129 'Either start working on the package or pass --accept_stable '
130 'to gmerge')
131
132 rc = subprocess.call(['emerge-%s' % board, pkg])
133 if rc != 0:
134 return self.SetError('Could not emerge ' + pkg)
135
136 cherrypy.log('ecleaning %s' % pkg, 'BUILD')
137 rc = subprocess.call(['eclean-' + board, '-d', 'packages'])
138 if rc != 0:
139 return self.SetError('eclean failed')
140
141 cherrypy.log('eclean complete %s' % pkg, 'BUILD')
142 return 'Success\n'
143
144 except OSError, e:
145 return self.SetError('Could not execute build command: ' + str(e))
146
147 finally:
148 os.environ['USE'] = original_use
149
150
151 class DevServerRoot(object):
73 """The Root Class for the Dev Server. 152 """The Root Class for the Dev Server.
74 153
75 CherryPy works as follows: 154 CherryPy works as follows:
76 For each method in this class, cherrpy interprets root/path 155 For each method in this class, cherrpy interprets root/path
77 as a call to an instance of DevServerRoot->method_name. For example, 156 as a call to an instance of DevServerRoot->method_name. For example,
78 a call to http://myhost/build will call build. CherryPy automatically 157 a call to http://myhost/build will call build. CherryPy automatically
79 parses http args and places them as keyword arguments in each method. 158 parses http args and places them as keyword arguments in each method.
80 For paths http://myhost/update/dir1/dir2, you can use *args so that 159 For paths http://myhost/update/dir1/dir2, you can use *args so that
81 cherrypy uses the update method and puts the extra paths in args. 160 cherrypy uses the update method and puts the extra paths in args.
82 """ 161 """
83 162
84 def build(self, board, pkg): 163 def __init__(self):
164 self._builder = Builder()
165
166 def build(self, board, pkg, **kwargs):
85 """Builds the package specified.""" 167 """Builds the package specified."""
86 cherrypy.log('emerging %s' % pkg, 'BUILD') 168 return self._builder.Build(board, pkg, kwargs)
87 emerge_command = 'emerge-%s %s' % (board, pkg)
88 err = os.system(emerge_command)
89 if err != 0:
90 raise Exception('failed to execute %s' % emerge_command)
91 eclean_command = 'eclean-%s -d packages' % board
92 err = os.system(eclean_command)
93 if err != 0:
94 raise Exception('failed to execute %s' % emerge_command)
95 169
96 def index(self): 170 def index(self):
97 return 'Welcome to the Dev Server!' 171 return 'Welcome to the Dev Server!'
98 172
99 def update(self, *args): 173 def update(self, *args):
100 label = '/'.join(args) 174 label = '/'.join(args)
101 body_length = int(cherrypy.request.headers['Content-Length']) 175 body_length = int(cherrypy.request.headers['Content-Length'])
102 data = cherrypy.request.rfile.read(body_length) 176 data = cherrypy.request.rfile.read(body_length)
103 return updater.HandleUpdatePing(data, label) 177 return updater.HandleUpdatePing(data, label)
104 178
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 # We don't run the dev server with this option. 282 # We don't run the dev server with this option.
209 if options.validate_factory_config: 283 if options.validate_factory_config:
210 sys.exit(0) 284 sys.exit(0)
211 elif options.pregenerate_update: 285 elif options.pregenerate_update:
212 if not updater.PreGenerateUpdate(): 286 if not updater.PreGenerateUpdate():
213 sys.exit(1) 287 sys.exit(1)
214 288
215 # If the command line requested after setup, it's time to do it. 289 # If the command line requested after setup, it's time to do it.
216 if not options.exit: 290 if not options.exit:
217 cherrypy.quickstart(DevServerRoot(), config=_GetConfig(options)) 291 cherrypy.quickstart(DevServerRoot(), config=_GetConfig(options))
OLDNEW
« no previous file with comments | « no previous file | gmerge » ('j') | gmerge » ('J')

Powered by Google App Engine
This is Rietveld 408576698