From a25c4e4fefd10980e2a4701607e494513a6c60b5 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Fri, 21 Mar 2014 17:30:12 +0000 Subject: rebaseline_server: fix --editable mode complete revert of https://skia.googlesource.com/skia/+/736be3527214ddbd3dd7e42a89a374c62d98f370 partial revert of https://skia.googlesource.com/skia/+/579942387bed9259b03419c593503022e1399931 and glue made necessary by the above. (SkipBuildbotRuns) BUG=skia:2319 NOTREECHECKS=True NOTRY=True R=senorblanco@google.com, senorblanco@chromium.org Author: epoger@google.com Review URL: https://codereview.chromium.org/208473004 git-svn-id: http://skia.googlecode.com/svn/trunk@13893 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/rebaseline_server/server.py | 128 ++++++++++++++++++--------------- gm/rebaseline_server/static/index.html | 4 +- 2 files changed, 73 insertions(+), 59 deletions(-) (limited to 'gm') diff --git a/gm/rebaseline_server/server.py b/gm/rebaseline_server/server.py index d88d3992d7..bf9b125e1f 100755 --- a/gm/rebaseline_server/server.py +++ b/gm/rebaseline_server/server.py @@ -28,20 +28,16 @@ import urlparse # Imports from within Skia # -# We need to add the 'tools' directory for svn.py, and the 'gm' directory for -# gm_json.py . -# Make sure that these dirs are in the PYTHONPATH, but add them at the *end* +# We need to add the 'tools' directory, so that we can import svn.py within +# that directory. +# Make sure that the 'tools' dir is in the PYTHONPATH, but add it at the *end* # so any dirs that are already in the PYTHONPATH will be preferred. PARENT_DIRECTORY = os.path.dirname(os.path.realpath(__file__)) -GM_DIRECTORY = os.path.dirname(PARENT_DIRECTORY) -TRUNK_DIRECTORY = os.path.dirname(GM_DIRECTORY) +TRUNK_DIRECTORY = os.path.dirname(os.path.dirname(PARENT_DIRECTORY)) TOOLS_DIRECTORY = os.path.join(TRUNK_DIRECTORY, 'tools') if TOOLS_DIRECTORY not in sys.path: sys.path.append(TOOLS_DIRECTORY) import svn -if GM_DIRECTORY not in sys.path: - sys.path.append(GM_DIRECTORY) -import gm_json # Imports from local dir # @@ -76,9 +72,8 @@ DEFAULT_ACTUALS_REPO_URL = 'http://skia-autogen.googlecode.com/svn/gm-actual' DEFAULT_PORT = 8888 # Directory within which the server will serve out static files. -STATIC_CONTENTS_DIR = os.path.realpath(os.path.join(PARENT_DIRECTORY, 'static')) -GENERATED_IMAGES_DIR = os.path.join(STATIC_CONTENTS_DIR, 'generated-images') -GENERATED_JSON_DIR = os.path.join(STATIC_CONTENTS_DIR, 'generated-json') +STATIC_CONTENTS_SUBDIR = 'static' # within PARENT_DIR +GENERATED_IMAGES_SUBDIR = 'generated-images' # within STATIC_CONTENTS_SUBDIR # How often (in seconds) clients should reload while waiting for initial # results to load. @@ -87,11 +82,6 @@ RELOAD_INTERVAL_UNTIL_READY = 10 _HTTP_HEADER_CONTENT_LENGTH = 'Content-Length' _HTTP_HEADER_CONTENT_TYPE = 'Content-Type' -SUMMARY_TYPES = [ - results_mod.KEY__HEADER__RESULTS_ALL, - results_mod.KEY__HEADER__RESULTS_FAILURES, -] - _SERVER = None # This gets filled in by main() @@ -177,25 +167,6 @@ class Server(object): self._actuals_repo = _create_svn_checkout( dir_path=actuals_dir, repo_url=actuals_repo_url) - # Since we don't have any results ready yet, prepare a dummy results file - # telling any clients that we're still working on the results. - response_dict = { - results_mod.KEY__HEADER: { - results_mod.KEY__HEADER__SCHEMA_VERSION: ( - results_mod.REBASELINE_SERVER_SCHEMA_VERSION_NUMBER), - results_mod.KEY__HEADER__IS_STILL_LOADING: True, - results_mod.KEY__HEADER__TIME_UPDATED: 0, - results_mod.KEY__HEADER__TIME_NEXT_UPDATE_AVAILABLE: ( - RELOAD_INTERVAL_UNTIL_READY), - }, - } - if not os.path.isdir(GENERATED_JSON_DIR): - os.makedirs(GENERATED_JSON_DIR) - for summary_type in SUMMARY_TYPES: - gm_json.WriteToFile( - response_dict, - os.path.join(GENERATED_JSON_DIR, '%s.json' % summary_type)) - # Reentrant lock that must be held whenever updating EITHER of: # 1. self._results # 2. the expected or actual results on local disk @@ -265,20 +236,13 @@ class Server(object): results_mod.DEFAULT_EXPECTATIONS_DIR) _run_command(['gclient', 'sync'], TRUNK_DIRECTORY) - new_results = results_mod.Results( + self._results = results_mod.Results( actuals_root=self._actuals_dir, - generated_images_root=GENERATED_IMAGES_DIR, - diff_base_url=os.path.relpath( - GENERATED_IMAGES_DIR, GENERATED_JSON_DIR)) - - if not os.path.isdir(GENERATED_JSON_DIR): - os.makedirs(GENERATED_JSON_DIR) - for summary_type in SUMMARY_TYPES: - gm_json.WriteToFile( - new_results.get_packaged_results_of_type(results_type=summary_type), - os.path.join(GENERATED_JSON_DIR, '%s.json' % summary_type)) - - self._results = new_results + generated_images_root=os.path.join( + PARENT_DIRECTORY, STATIC_CONTENTS_SUBDIR, + GENERATED_IMAGES_SUBDIR), + diff_base_url=posixpath.join( + os.pardir, STATIC_CONTENTS_SUBDIR, GENERATED_IMAGES_SUBDIR)) def _result_loader(self, reload_seconds=0): """ Call self.update_results(), either once or periodically. @@ -329,10 +293,10 @@ class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): try: logging.debug('do_GET: path="%s"' % self.path) if self.path == '' or self.path == '/' or self.path == '/index.html' : - self.redirect_to('/static/index.html') + self.redirect_to('/%s/index.html' % STATIC_CONTENTS_SUBDIR) return if self.path == '/favicon.ico' : - self.redirect_to('/static/favicon.ico') + self.redirect_to('/%s/favicon.ico' % STATIC_CONTENTS_SUBDIR) return # All requests must be of this form: @@ -342,7 +306,8 @@ class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): normpath = posixpath.normpath(self.path) (dispatcher_name, remainder) = PATHSPLIT_RE.match(normpath).groups() dispatchers = { - 'static': self.do_GET_static, + 'results': self.do_GET_results, + STATIC_CONTENTS_SUBDIR: self.do_GET_static, } dispatcher = dispatchers[dispatcher_name] dispatcher(remainder) @@ -350,25 +315,62 @@ class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): self.send_error(404) raise + def do_GET_results(self, results_type): + """ Handle a GET request for GM results. + + Args: + results_type: string indicating which set of results to return; + must be one of the results_mod.RESULTS_* constants + """ + logging.debug('do_GET_results: sending results of type "%s"' % results_type) + # Since we must make multiple calls to the Results object, grab a + # reference to it in case it is updated to point at a new Results + # object within another thread. + # + # TODO(epoger): Rather than using a global variable for the handler + # to refer to the Server object, make Server a subclass of + # HTTPServer, and then it could be available to the handler via + # the handler's .server instance variable. + results_obj = _SERVER.results + if results_obj: + response_dict = results_obj.get_packaged_results_of_type( + results_type=results_type, reload_seconds=_SERVER.reload_seconds, + is_editable=_SERVER.is_editable, is_exported=_SERVER.is_exported) + else: + now = int(time.time()) + response_dict = { + results_mod.KEY__HEADER: { + results_mod.KEY__HEADER__SCHEMA_VERSION: ( + results_mod.REBASELINE_SERVER_SCHEMA_VERSION_NUMBER), + results_mod.KEY__HEADER__IS_STILL_LOADING: True, + results_mod.KEY__HEADER__TIME_UPDATED: now, + results_mod.KEY__HEADER__TIME_NEXT_UPDATE_AVAILABLE: ( + now + RELOAD_INTERVAL_UNTIL_READY), + }, + } + self.send_json_dict(response_dict) + def do_GET_static(self, path): - """ Handle a GET request for a file under the 'static' directory. - Only allow serving of files within the 'static' directory that is a + """ Handle a GET request for a file under STATIC_CONTENTS_SUBDIR . + Only allow serving of files within STATIC_CONTENTS_SUBDIR that is a filesystem sibling of this script. Args: - path: path to file (under static directory) to retrieve + path: path to file (within STATIC_CONTENTS_SUBDIR) to retrieve """ # Strip arguments ('?resultsToLoad=all') from the path path = urlparse.urlparse(path).path logging.debug('do_GET_static: sending file "%s"' % path) - full_path = os.path.realpath(os.path.join(STATIC_CONTENTS_DIR, path)) - if full_path.startswith(STATIC_CONTENTS_DIR): + static_dir = os.path.realpath(os.path.join( + PARENT_DIRECTORY, STATIC_CONTENTS_SUBDIR)) + full_path = os.path.realpath(os.path.join(static_dir, path)) + if full_path.startswith(static_dir): self.send_file(full_path) else: logging.error( 'Attempted do_GET_static() of path [%s] outside of static dir [%s]' - % (full_path, STATIC_CONTENTS_DIR)) + % (full_path, static_dir)) self.send_error(404) def do_POST(self): @@ -480,6 +482,18 @@ class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): else: self.send_error(404) + def send_json_dict(self, json_dict): + """ Send the contents of this dictionary in JSON format, with a JSON + mimetype. + + Args: + json_dict: dictionary to send + """ + self.send_response(200) + self.send_header('Content-type', 'application/json') + self.end_headers() + json.dump(json_dict, self.wfile) + def main(): logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', diff --git a/gm/rebaseline_server/static/index.html b/gm/rebaseline_server/static/index.html index 419b7b59d8..9cfd41c569 100644 --- a/gm/rebaseline_server/static/index.html +++ b/gm/rebaseline_server/static/index.html @@ -9,13 +9,13 @@ Here are links to the result pages: