servo/tests/wpt/harness/wptrunner/update/update.py
2016-02-02 09:54:39 +00:00

158 lines
4.9 KiB
Python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os
import sys
from metadata import MetadataUpdateRunner
from sync import SyncFromUpstreamRunner
from tree import GitTree, HgTree, NoVCSTree
from .. import environment as env
from base import Step, StepRunner, exit_clean, exit_unclean
from state import State
def setup_paths(sync_path):
sys.path.insert(0, os.path.abspath(sync_path))
from tools import localpaths
class LoadConfig(Step):
"""Step for loading configuration from the ini file and kwargs."""
provides = ["sync", "paths", "metadata_path", "tests_path"]
def create(self, state):
state.sync = {"remote_url": state.kwargs["remote_url"],
"branch": state.kwargs["branch"],
"path": state.kwargs["sync_path"]}
state.paths = state.kwargs["test_paths"]
state.tests_path = state.paths["/"]["tests_path"]
state.metadata_path = state.paths["/"]["metadata_path"]
assert state.tests_path.startswith("/")
class LoadTrees(Step):
"""Step for creating a Tree for the local copy and a GitTree for the
upstream sync."""
provides = ["local_tree", "sync_tree"]
def create(self, state):
if os.path.exists(state.sync["path"]):
sync_tree = GitTree(root=state.sync["path"])
else:
sync_tree = None
if GitTree.is_type():
local_tree = GitTree()
elif HgTree.is_type():
local_tree = HgTree()
else:
local_tree = NoVCSTree()
state.update({"local_tree": local_tree,
"sync_tree": sync_tree})
class SyncFromUpstream(Step):
"""Step that synchronises a local copy of the code with upstream."""
def create(self, state):
if not state.kwargs["sync"]:
return
if not state.sync_tree:
os.mkdir(state.sync["path"])
state.sync_tree = GitTree(root=state.sync["path"])
kwargs = state.kwargs
with state.push(["sync", "paths", "metadata_path", "tests_path", "local_tree",
"sync_tree"]):
state.target_rev = kwargs["rev"]
state.no_patch = kwargs["no_patch"]
state.suite_name = kwargs["suite_name"]
runner = SyncFromUpstreamRunner(self.logger, state)
runner.run()
class UpdateMetadata(Step):
"""Update the expectation metadata from a set of run logs"""
def create(self, state):
if not state.kwargs["run_log"]:
return
kwargs = state.kwargs
with state.push(["local_tree", "sync_tree", "paths", "serve_root"]):
state.run_log = kwargs["run_log"]
state.ignore_existing = kwargs["ignore_existing"]
state.no_patch = kwargs["no_patch"]
state.suite_name = kwargs["suite_name"]
state.product = kwargs["product"]
state.config = kwargs["config"]
runner = MetadataUpdateRunner(self.logger, state)
runner.run()
class UpdateRunner(StepRunner):
"""Runner for doing an overall update."""
steps = [LoadConfig,
LoadTrees,
SyncFromUpstream,
UpdateMetadata]
class WPTUpdate(object):
def __init__(self, logger, runner_cls=UpdateRunner, **kwargs):
"""Object that controls the running of a whole wptupdate.
:param runner_cls: Runner subclass holding the overall list of
steps to run.
:param kwargs: Command line arguments
"""
self.runner_cls = runner_cls
self.serve_root = kwargs["test_paths"]["/"]["tests_path"]
if not kwargs["sync"]:
setup_paths(self.serve_root)
else:
if os.path.exists(kwargs["sync_path"]):
# If the sync path doesn't exist we defer this until it does
setup_paths(kwargs["sync_path"])
self.state = State(logger)
self.kwargs = kwargs
self.logger = logger
def run(self, **kwargs):
if self.kwargs["abort"]:
self.abort()
return exit_clean
if not self.kwargs["continue"] and not self.state.is_empty():
self.logger.error("Found existing state. Run with --continue to resume or --abort to clear state")
return exit_unclean
if self.kwargs["continue"]:
if self.state.is_empty():
self.logger.error("No sync in progress?")
return exit_clean
self.kwargs = self.state.kwargs
else:
self.state.kwargs = self.kwargs
self.state.serve_root = self.serve_root
update_runner = self.runner_cls(self.logger, self.state)
rv = update_runner.run()
if rv in (exit_clean, None):
self.state.clear()
return rv
def abort(self):
self.state.clear()