1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 from __future__
import absolute_import
8 from datetime
import datetime
, timedelta
12 import mozversioncontrol
15 from cStringIO
import StringIO
as BytesIO
17 from io
import BytesIO
19 HEADERS
= {"User-Agent": "wpt manifest download"}
22 def get(logger
, url
, **kwargs
):
24 if "headers" not in kwargs
:
25 kwargs
["headers"] = HEADERS
26 return requests
.get(url
, **kwargs
)
30 return os
.path
.abspath(os
.path
.expanduser(path
))
33 def get_commits(logger
, repo_root
):
35 repo
= mozversioncontrol
.get_repository_object(repo_root
)
36 except mozversioncontrol
.InvalidRepoPath
:
37 logger
.warning("No VCS found for path %s" % repo_root
)
40 # The base_ref doesn't actually return a ref, sadly
41 base_rev
= repo
.base_ref
42 if repo
.name
== "git":
43 logger
.debug("Found git repo")
44 logger
.debug("Base rev is %s" % base_rev
)
45 if not repo
.has_git_cinnabar
:
46 logger
.error("git cinnabar not found")
49 repo
._run
("cinnabar", "git2hg", rev
).strip()
55 "testing/web-platform/tests",
56 "testing/web-platform/mozilla/tests",
60 logger
.debug("Found hg repo")
61 logger
.debug("Base rev is %s" % base_rev
)
62 changeset_iter
= repo
._run
(
65 "--template={node}\n",
68 "testing/web-platform/tests",
69 "testing/web-platform/mozilla/tests",
74 def should_download(logger
, manifest_paths
, rebuild_time
=timedelta(days
=5)):
75 # TODO: Improve logic for when to download. Maybe if x revisions behind?
76 for manifest_path
in manifest_paths
:
77 if not os
.path
.exists(manifest_path
):
79 mtime
= datetime
.fromtimestamp(os
.path
.getmtime(manifest_path
))
80 if mtime
< datetime
.now() - rebuild_time
:
82 if os
.path
.getsize(manifest_path
) == 0:
85 logger
.info("Skipping manifest download because existing file is recent")
89 def taskcluster_url(logger
, commits
):
90 artifact_path
= "/artifacts/public/manifests.tar.gz"
93 "mozilla-central": "mozilla-central",
94 "integration/autoland": "autoland",
95 "releases/mozilla-esr102": "mozilla-esr102",
98 "https://hg.mozilla.org/{repo}/json-pushes?"
99 "changeset={changeset}&version=2&tipsonly=1"
103 "https://firefox-ci-tc.services.mozilla.com/api/index/v1/"
104 "task/gecko.v2.{name}."
105 "revision.{changeset}.source.manifest-upload"
109 "https://firefox-ci-tc.services.mozilla.com/api/index/v1/"
110 "task/gecko.v2.mozilla-central.latest.source.manifest-upload" + artifact_path
113 for revision
in commits
:
116 if revision
== 40 * "0":
119 for repo_path
, index_name
in six
.iteritems(repos
):
121 req_headers
= HEADERS
.copy()
122 req_headers
.update({"Accept": "application/json"})
125 cset_url
.format(changeset
=revision
, repo
=repo_path
),
128 req
.raise_for_status()
129 except requests
.exceptions
.RequestException
:
130 if req
is not None and req
.status_code
== 404:
131 # The API returns a 404 if it can't find a changeset for the revision.
132 logger
.debug("%s not found in %s" % (revision
, repo_path
))
139 pushes
= result
["pushes"]
141 logger
.debug("Error reading response; 'pushes' key not found")
143 [cset
] = next(iter(pushes
.values()))["changesets"]
145 tc_index_url
= tc_url
.format(changeset
=cset
, name
=index_name
)
147 req
= get(logger
, tc_index_url
)
148 except requests
.exceptions
.RequestException
:
151 if req
.status_code
== 200:
152 return tc_index_url
+ artifact_path
155 "Can't find a commit-specific manifest so just using the most " "recent one"
161 def download_manifest(logger
, test_paths
, commits_func
, url_func
, force
=False):
162 manifest_paths
= [item
["manifest_path"] for item
in six
.itervalues(test_paths
)]
164 if not force
and not should_download(logger
, manifest_paths
):
167 commits
= commits_func()
169 url
= url_func(logger
, commits
)
171 logger
.warning("No generated manifest found")
174 logger
.info("Downloading manifest from %s" % url
)
176 req
= get(logger
, url
)
178 logger
.warning("Downloading pregenerated manifest failed")
181 if req
.status_code
!= 200:
183 "Downloading pregenerated manifest failed; got "
184 "HTTP status %d" % req
.status_code
188 tar
= tarfile
.open(mode
="r:gz", fileobj
=BytesIO(req
.content
))
189 for paths
in six
.itervalues(test_paths
):
191 member
= tar
.getmember(paths
["manifest_rel_path"].replace(os
.path
.sep
, "/"))
194 "Failed to find downloaded manifest %s" % paths
["manifest_rel_path"]
199 "Unpacking %s to %s" % (member
.name
, paths
["manifest_path"])
201 src
= tar
.extractfile(member
)
202 with
open(paths
["manifest_path"], "wb") as dest
:
203 dest
.write(src
.read())
209 "Failed to decompress %s:\n%s"
210 % (paths
["manifest_rel_path"], traceback
.format_exc())
214 os
.utime(paths
["manifest_path"], None)
219 def download_from_taskcluster(logger
, repo_root
, test_paths
, force
=False):
220 return download_manifest(
223 lambda: get_commits(logger
, repo_root
),