Fix protocol auto-detection for ssh
[platform/upstream/VK-GL-CTS.git] / external / fetch_sources.py
1 # -*- coding: utf-8 -*-
2
3 #-------------------------------------------------------------------------
4 # drawElements Quality Program utilities
5 # --------------------------------------
6 #
7 # Copyright 2015 The Android Open Source Project
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 #      http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 #
21 #-------------------------------------------------------------------------
22
23 import os
24 import sys
25 import shutil
26 import tarfile
27 import urllib2
28 import hashlib
29 import argparse
30 import subprocess
31
32 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "scripts"))
33
34 from build.common import *
35
36 EXTERNAL_DIR    = os.path.realpath(os.path.normpath(os.path.dirname(__file__)))
37
38 def computeChecksum (data):
39         return hashlib.sha256(data).hexdigest()
40
41 class Source:
42         def __init__(self, baseDir, extractDir):
43                 self.baseDir            = baseDir
44                 self.extractDir         = extractDir
45
46         def clean (self):
47                 fullDstPath = os.path.join(EXTERNAL_DIR, self.baseDir, self.extractDir)
48                 if os.path.exists(fullDstPath):
49                         shutil.rmtree(fullDstPath, ignore_errors=False)
50
51 class SourcePackage (Source):
52         def __init__(self, url, filename, checksum, baseDir, extractDir = "src", postExtract=None):
53                 Source.__init__(self, baseDir, extractDir)
54                 self.url                        = url
55                 self.filename           = filename
56                 self.checksum           = checksum
57                 self.archiveDir         = "packages"
58                 self.postExtract        = postExtract
59
60         def clean (self):
61                 Source.clean(self)
62                 self.removeArchives()
63
64         def update (self, cmdProtocol = None):
65                 if not self.isArchiveUpToDate():
66                         self.fetchAndVerifyArchive()
67
68                 if self.getExtractedChecksum() != self.checksum:
69                         Source.clean(self)
70                         self.extract()
71                         self.storeExtractedChecksum(self.checksum)
72
73         def removeArchives (self):
74                 archiveDir = os.path.join(EXTERNAL_DIR, pkg.baseDir, pkg.archiveDir)
75                 if os.path.exists(archiveDir):
76                         shutil.rmtree(archiveDir, ignore_errors=False)
77
78         def isArchiveUpToDate (self):
79                 archiveFile = os.path.join(EXTERNAL_DIR, pkg.baseDir, pkg.archiveDir, pkg.filename)
80                 if os.path.exists(archiveFile):
81                         return computeChecksum(readFile(archiveFile)) == self.checksum
82                 else:
83                         return False
84
85         def getExtractedChecksumFilePath (self):
86                 return os.path.join(EXTERNAL_DIR, pkg.baseDir, pkg.archiveDir, "extracted")
87
88         def getExtractedChecksum (self):
89                 extractedChecksumFile = self.getExtractedChecksumFilePath()
90
91                 if os.path.exists(extractedChecksumFile):
92                         return readFile(extractedChecksumFile)
93                 else:
94                         return None
95
96         def storeExtractedChecksum (self, checksum):
97                 writeFile(self.getExtractedChecksumFilePath(), checksum)
98
99         def fetchAndVerifyArchive (self):
100                 print "Fetching %s" % self.url
101
102                 req                     = urllib2.urlopen(self.url)
103                 data            = req.read()
104                 checksum        = computeChecksum(data)
105                 dstPath         = os.path.join(EXTERNAL_DIR, self.baseDir, self.archiveDir, self.filename)
106
107                 if checksum != self.checksum:
108                         raise Exception("Checksum mismatch for %s, exepected %s, got %s" % (self.filename, self.checksum, checksum))
109
110                 if not os.path.exists(os.path.dirname(dstPath)):
111                         os.mkdir(os.path.dirname(dstPath))
112
113                 writeFile(dstPath, data)
114
115         def extract (self):
116                 print "Extracting %s to %s/%s" % (self.filename, self.baseDir, self.extractDir)
117
118                 srcPath = os.path.join(EXTERNAL_DIR, self.baseDir, self.archiveDir, self.filename)
119                 tmpPath = os.path.join(EXTERNAL_DIR, ".extract-tmp-%s" % self.baseDir)
120                 dstPath = os.path.join(EXTERNAL_DIR, self.baseDir, self.extractDir)
121                 archive = tarfile.open(srcPath)
122
123                 if os.path.exists(tmpPath):
124                         shutil.rmtree(tmpPath, ignore_errors=False)
125
126                 os.mkdir(tmpPath)
127
128                 archive.extractall(tmpPath)
129                 archive.close()
130
131                 extractedEntries = os.listdir(tmpPath)
132                 if len(extractedEntries) != 1 or not os.path.isdir(os.path.join(tmpPath, extractedEntries[0])):
133                         raise Exception("%s doesn't contain single top-level directory" % self.filename)
134
135                 topLevelPath = os.path.join(tmpPath, extractedEntries[0])
136
137                 if not os.path.exists(dstPath):
138                         os.mkdir(dstPath)
139
140                 for entry in os.listdir(topLevelPath):
141                         if os.path.exists(os.path.join(dstPath, entry)):
142                                 raise Exception("%s exists already" % entry)
143
144                         shutil.move(os.path.join(topLevelPath, entry), dstPath)
145
146                 shutil.rmtree(tmpPath, ignore_errors=True)
147
148                 if self.postExtract != None:
149                         self.postExtract(dstPath)
150
151 class GitRepo (Source):
152         def __init__(self, httpsUrl, sshUrl, revision, baseDir, extractDir = "src"):
153                 Source.__init__(self, baseDir, extractDir)
154                 self.httpsUrl   = httpsUrl
155                 self.sshUrl             = sshUrl
156                 self.revision   = revision
157
158         def selectUrl(self, cmdProtocol = None):
159                 if cmdProtocol == None:
160                         # reuse parent repo protocol
161                         proc = subprocess.Popen(['git', 'ls-remote', '--get-url', 'origin'], stdout=subprocess.PIPE)
162                         (stdout, stderr) = proc.communicate()
163
164                         if proc.returncode != 0:
165                                 raise Exception("Failed to execute 'git ls-remote origin', got %d" % proc.returncode)
166                         if (stdout[:3] == 'ssh') or (stdout[:3] == 'git'):
167                                 protocol = 'ssh'
168                         else:
169                                 assert stdout[:5] == 'https'
170                                 protocol = 'https'
171                 else:
172                         protocol = cmdProtocol
173
174                 if protocol == 'ssh':
175                         if self.sshUrl != None:
176                                 url = self.sshUrl
177                         else:
178                                 assert self.httpsUrl != None
179                                 url = self.httpsUrl
180                 else:
181                         assert protocol == 'https'
182                         url = self.httpsUrl
183
184                 assert url != None
185                 return url
186
187         def update (self, cmdProtocol = None):
188                 fullDstPath = os.path.join(EXTERNAL_DIR, self.baseDir, self.extractDir)
189
190                 url = self.selectUrl(cmdProtocol)
191                 if not os.path.exists(fullDstPath):
192                         execute(["git", "clone", "--no-checkout", url, fullDstPath])
193
194                 pushWorkingDir(fullDstPath)
195                 try:
196                         execute(["git", "fetch", url, "+refs/heads/*:refs/remotes/origin/*"])
197                         execute(["git", "checkout", self.revision])
198                 finally:
199                         popWorkingDir()
200
201 def postExtractLibpng (path):
202         shutil.copy(os.path.join(path, "scripts", "pnglibconf.h.prebuilt"),
203                                 os.path.join(path, "pnglibconf.h"))
204
205 PACKAGES = [
206         SourcePackage(
207                 "http://zlib.net/zlib-1.2.8.tar.gz",
208                 "zlib-1.2.8.tar.gz",
209                 "36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d",
210                 "zlib"),
211         SourcePackage(
212                 "http://prdownloads.sourceforge.net/libpng/libpng-1.6.26.tar.gz",
213                 "libpng-1.6.26.tar.gz",
214                 "81bfc8f16ed125622c0c5ad44eeffda19e7a7c7e32f47e43c8932bf32deae7cc",
215                 "libpng",
216                 postExtract = postExtractLibpng),
217         GitRepo(
218                 "https://github.com/KhronosGroup/SPIRV-Tools.git",
219                 None,
220                 "5c19de25107d496a15c7869b3e1dab0a0f85913d",
221                 "spirv-tools"),
222         GitRepo(
223                 "https://github.com/KhronosGroup/glslang.git",
224                 None,
225                 "e3aa654c4b0c761b28d7864192ca8ceea6faf70a",
226                 "glslang"),
227         GitRepo(
228                 "https://github.com/KhronosGroup/SPIRV-Headers.git",
229                 None,
230                 "bd47a9abaefac00be692eae677daed1b977e625c",
231                 "spirv-headers"),
232 ]
233
234 def parseArgs ():
235         parser = argparse.ArgumentParser(description = "Fetch external sources")
236         parser.add_argument('--clean', dest='clean', action='store_true', default=False,
237                                                 help='Remove sources instead of fetching')
238         parser.add_argument('--protocol', dest='protocol', default=None, choices=['ssh', 'https'],
239                                                 help="Select protocol to checkout git repositories.")
240         return parser.parse_args()
241
242 if __name__ == "__main__":
243         args = parseArgs()
244
245         for pkg in PACKAGES:
246                 if args.clean:
247                         pkg.clean()
248                 else:
249                         pkg.update(args.protocol)