Unreviewed. Update W3C WebDriver imported tests.
[WebKit-https.git] / WebDriverTests / imported / w3c / tools / wptrunner / wptrunner / update / sync.py
1 import fnmatch
2 import os
3 import re
4 import shutil
5 import sys
6 import uuid
7
8 from .. import testloader
9
10 from base import Step, StepRunner
11 from tree import Commit
12
13 here = os.path.abspath(os.path.split(__file__)[0])
14
15 bsd_license = """W3C 3-clause BSD License
16
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions are
19 met:
20
21 * Redistributions of works must retain the original copyright notice, this
22   list of conditions and the following disclaimer.
23
24 * Redistributions in binary form must reproduce the original copyright
25   notice, this list of conditions and the following disclaimer in the
26   documentation and/or other materials provided with the distribution.
27
28 * Neither the name of the W3C nor the names of its contributors may be
29   used to endorse or promote products derived from this work without
30   specific prior written permission.
31
32
33 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
34 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
37 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 POSSIBILITY OF SUCH DAMAGE.
44 """
45
46
47 def copy_wpt_tree(tree, dest, excludes=None, includes=None):
48     """Copy the working copy of a Tree to a destination directory.
49
50     :param tree: The Tree to copy.
51     :param dest: The destination directory"""
52     if os.path.exists(dest):
53         assert os.path.isdir(dest)
54
55     shutil.rmtree(dest)
56
57     os.mkdir(dest)
58
59     if excludes is None:
60         excludes = []
61
62     excludes = [re.compile(fnmatch.translate(item)) for item in excludes]
63
64     if includes is None:
65         includes = []
66
67     includes = [re.compile(fnmatch.translate(item)) for item in includes]
68
69     for tree_path in tree.paths():
70         if (any(item.match(tree_path) for item in excludes) and
71             not any(item.match(tree_path) for item in includes)):
72             continue
73
74         source_path = os.path.join(tree.root, tree_path)
75         dest_path = os.path.join(dest, tree_path)
76
77         dest_dir = os.path.split(dest_path)[0]
78         if not os.path.isdir(source_path):
79             if not os.path.exists(dest_dir):
80                 os.makedirs(dest_dir)
81             shutil.copy2(source_path, dest_path)
82
83     for source, destination in [("testharness_runner.html", ""),
84                                 ("testharnessreport.js", "resources/"),
85                                 ("testdriver-vendor.js", "resources/")]:
86         source_path = os.path.join(here, os.pardir, source)
87         dest_path = os.path.join(dest, destination, os.path.split(source)[1])
88         shutil.copy2(source_path, dest_path)
89
90     add_license(dest)
91
92
93 def add_license(dest):
94     """Write the bsd license string to a LICENSE file.
95
96     :param dest: Directory in which to place the LICENSE file."""
97     with open(os.path.join(dest, "LICENSE"), "w") as f:
98         f.write(bsd_license)
99
100
101 class UpdateCheckout(Step):
102     """Pull changes from upstream into the local sync tree."""
103
104     provides = ["local_branch"]
105
106     def create(self, state):
107         sync_tree = state.sync_tree
108         state.local_branch = uuid.uuid4().hex
109         sync_tree.update(state.sync["remote_url"],
110                          state.sync["branch"],
111                          state.local_branch)
112         sync_path = os.path.abspath(sync_tree.root)
113         if not sync_path in sys.path:
114             from update import setup_paths
115             setup_paths(sync_path)
116
117     def restore(self, state):
118         assert os.path.abspath(state.sync_tree.root) in sys.path
119         Step.restore(self, state)
120
121
122 class GetSyncTargetCommit(Step):
123     """Find the commit that we will sync to."""
124
125     provides = ["sync_commit"]
126
127     def create(self, state):
128         if state.target_rev is None:
129             #Use upstream branch HEAD as the base commit
130             state.sync_commit = state.sync_tree.get_remote_sha1(state.sync["remote_url"],
131                                                                 state.sync["branch"])
132         else:
133             state.sync_commit = Commit(state.sync_tree, state.rev)
134
135         state.sync_tree.checkout(state.sync_commit.sha1, state.local_branch, force=True)
136         self.logger.debug("New base commit is %s" % state.sync_commit.sha1)
137
138
139 class LoadManifest(Step):
140     """Load the test manifest"""
141
142     provides = ["manifest_path", "test_manifest"]
143
144     def create(self, state):
145         from manifest import manifest
146         state.manifest_path = os.path.join(state.metadata_path, "MANIFEST.json")
147         state.test_manifest = manifest.Manifest("/")
148
149
150 class UpdateManifest(Step):
151     """Update the manifest to match the tests in the sync tree checkout"""
152
153     def create(self, state):
154         from manifest import manifest, update
155         update.update(state.sync["path"], state.test_manifest)
156         manifest.write(state.test_manifest, state.manifest_path)
157
158
159 class CopyWorkTree(Step):
160     """Copy the sync tree over to the destination in the local tree"""
161
162     def create(self, state):
163         copy_wpt_tree(state.sync_tree,
164                       state.tests_path,
165                       excludes=state.path_excludes,
166                       includes=state.path_includes)
167
168
169 class CreateSyncPatch(Step):
170     """Add the updated test files to a commit/patch in the local tree."""
171
172     def create(self, state):
173         if not state.patch:
174             return
175
176         local_tree = state.local_tree
177         sync_tree = state.sync_tree
178
179         local_tree.create_patch("web-platform-tests_update_%s" % sync_tree.rev,
180                                 "Update %s to revision %s" % (state.suite_name, sync_tree.rev))
181         local_tree.add_new(os.path.relpath(state.tests_path,
182                                            local_tree.root))
183         updated = local_tree.update_patch(include=[state.tests_path,
184                                                    state.metadata_path])
185         local_tree.commit_patch()
186
187         if not updated:
188             self.logger.info("Nothing to sync")
189
190
191 class SyncFromUpstreamRunner(StepRunner):
192     """(Sub)Runner for doing an upstream sync"""
193     steps = [UpdateCheckout,
194              GetSyncTargetCommit,
195              LoadManifest,
196              UpdateManifest,
197              CopyWorkTree,
198              CreateSyncPatch]