1d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# Copyright (C) 2011 Google Inc. All rights reserved. 2d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# 3d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# Redistribution and use in source and binary forms, with or without 4d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# modification, are permitted provided that the following conditions are 5d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# met: 6d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# 7d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# 1. Redistributions of source code must retain the above copyright 8d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# notice, this list of conditions and the following disclaimer. 9d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# 2. Redistributions in binary form must reproduce the above copyright 10d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# notice, this list of conditions and the following disclaimer in the 11d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# documentation and/or other materials provided with the distribution. 12d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# 13d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 149b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 194d353eb8af7324c0ee3736c736668f6c9b162ee0Anna Zaks# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose 25a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramerimport BaseHTTPServer 261140186abc9c6bd39f50d9866892e0b050e5f938Ted Kremenekimport SocketServer 27d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenekimport logging 289ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekimport json 290e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenekimport os 300e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenekimport re 31ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenekimport sys 32802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenekimport urllib 330e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek 340e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenekfrom webkitpy.common.memoized import memoized 35ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenekfrom webkitpy.tool.servers.reflectionhandler import ReflectionHandler 360e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenekfrom webkitpy.layout_tests.port import builders 370e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek 380e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek 390e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek_log = logging.getLogger(__name__) 400e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek 418af2975d50270813ae6366d007e9e1f5b65ddc68Ted Kremenek 425f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerclass GardeningHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): 435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner def __init__(self, httpd_port, config): 44d8e494faa9f4bc13cd0a136b4d1ee1cfd52860eaBenjamin Kramer server_name = '' 45d8e494faa9f4bc13cd0a136b4d1ee1cfd52860eaBenjamin Kramer self.tool = config['tool'] 46d8e494faa9f4bc13cd0a136b4d1ee1cfd52860eaBenjamin Kramer self.options = config['options'] 478af2975d50270813ae6366d007e9e1f5b65ddc68Ted Kremenek BaseHTTPServer.HTTPServer.__init__(self, (server_name, httpd_port), GardeningHTTPRequestHandler) 488af2975d50270813ae6366d007e9e1f5b65ddc68Ted Kremenek 495f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner def url(self, args=None): 50e3ce2656790523fd8c70653ee1ec41e5898f82ebTed Kremenek # We can't use urllib.encode() here because that encodes spaces as plus signs and the buildbots don't decode those properly. 51d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks arg_string = ('?' + '&'.join("%s=%s" % (key, urllib.quote(value)) for (key, value) in args.items())) if args else '' 52d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks return 'http://localhost:8127/garden-o-matic.html' + arg_string 534850451c8e93789c099d907dd469898ea9561ecbTed Kremenek 541f9bd0fbf5894b41bba5f2fdb0c6546a7a6ef3d8Ted Kremenek 55d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaksclass GardeningHTTPRequestHandler(ReflectionHandler): 56082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek REVISION_LIMIT = 100 574e06387c2d6d00c7a30167d4c2206756992dde38Ted Kremenek BLINK_SVN_URL = 'http://src.chromium.org/blink/trunk' 581fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek CHROMIUM_SVN_DEPS_URL = 'http://src.chromium.org/chrome/trunk/src/DEPS' 592042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek # "webkit_revision": "149598", 601fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek BLINK_REVISION_REGEXP = re.compile(r'^ "webkit_revision": "(?P<revision>\d+)",$', re.MULTILINE); 61802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek 6207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek STATIC_FILE_NAMES = frozenset() 6307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 64802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek STATIC_FILE_EXTENSIONS = ('.js', '.css', '.html', '.gif', '.png', '.ico') 65b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 66b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose STATIC_FILE_DIRECTORY = os.path.join( 67b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose os.path.dirname(__file__), 68ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek '..', 69ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek '..', 70b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose '..', 71b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose '..', 72b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 'GardeningServer') 73b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 74b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose allow_cross_origin_requests = True 75b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose debug_output = '' 76b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 77b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose def ping(self): 78b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose self._serve_text('pong') 79b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 80b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose def _run_webkit_patch(self, command, input_string): 81b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose PIPE = self.server.tool.executive.PIPE 82b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose process = self.server.tool.executive.popen([self.server.tool.path()] + command, cwd=self.server.tool.scm().checkout_root, stdin=PIPE, stdout=PIPE, stderr=PIPE) 83b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose process.stdin.write(input_string) 84b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose output, error = process.communicate() 85b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose return (process.returncode, output, error) 86b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 87b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose def svnlog(self): 88b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose self._serve_xml(self.server.tool.executive.run_command(['svn', 'log', '--xml', '--limit', self.REVISION_LIMIT, self.BLINK_SVN_URL])) 89b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 90b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose def lastroll(self): 91b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose deps_contents = self.server.tool.executive.run_command(['svn', 'cat', self.CHROMIUM_SVN_DEPS_URL]) 92b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose match = re.search(self.BLINK_REVISION_REGEXP, deps_contents) 93b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose if not match: 94b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose _log.error("Unable to produce last Blink roll revision") 95b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose self._serve_text("0") 96b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose return 97b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 98b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose revision_line = match.group() 99b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose revision = match.group("revision") 100b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose self._serve_text(revision) 101b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 102b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose def rebaselineall(self): 103b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose command = ['rebaseline-json'] 104b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose if self.server.options.results_directory: 105b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose command.extend(['--results-directory', self.server.options.results_directory]) 106b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose if not self.server.options.optimize: 107eb2303c76971f3cc89bbb367ce77564ccb7042c1Ted Kremenek command.append('--no-optimize') 108eb2303c76971f3cc89bbb367ce77564ccb7042c1Ted Kremenek if self.server.options.verbose: 10907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek command.append('--verbose') 1103a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose json_input = self.read_entity_body() 11197bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks 11297bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks _log.debug("calling %s, input='%s'", command, json_input) 11397bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks return_code, output, error = self._run_webkit_patch(command, json_input) 11407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek print >> sys.stderr, error 11507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if return_code: 1163a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose _log.error("rebaseline-json failed: %d, output='%s'" % (return_code, output)) 1173a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose else: 1182042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek _log.debug("rebaseline-json succeeded") 11997bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks 12097bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks # FIXME: propagate error and/or log messages back to the UI. 1212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek self._serve_text('success') 122a127ccaa38a23dbd9bd3884a2627c091075a7227Ted Kremenek 123d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks def localresult(self): 124d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks path = self.query['path'][0] 125d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks filesystem = self.server.tool.filesystem 12661dfd6f160f7501e140704990db9c449d29f8649Anna Zaks 12761dfd6f160f7501e140704990db9c449d29f8649Anna Zaks # Ensure that we're only serving files from inside the results directory. 12861dfd6f160f7501e140704990db9c449d29f8649Anna Zaks if not filesystem.isabs(path) and self.server.options.results_directory: 12961dfd6f160f7501e140704990db9c449d29f8649Anna Zaks fullpath = filesystem.abspath(filesystem.join(self.server.options.results_directory, path)) 13061dfd6f160f7501e140704990db9c449d29f8649Anna Zaks if fullpath.startswith(filesystem.abspath(self.server.options.results_directory)): 13161dfd6f160f7501e140704990db9c449d29f8649Anna Zaks self._serve_file(fullpath, headers_only=(self.command == 'HEAD')) 13261dfd6f160f7501e140704990db9c449d29f8649Anna Zaks return 133d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 134d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks self.send_response(403) 135d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks