1# -*- coding: utf-8 -*-
2
3#-------------------------------------------------------------------------
4# drawElements Quality Program utilities
5# --------------------------------------
6#
7# Copyright 2015-2017 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
23import os
24import sys
25import hashlib
26
27from . import registry
28
29scriptPath = os.path.join(os.path.dirname(__file__), "..")
30sys.path.insert(0, scriptPath)
31
32from ctsbuild.common import *
33
34BASE_URL = ""
35
36class RegistrySource:
37	def __init__(self, repository, filename, revision, checksum):
38		self.repository	= repository
39		self.filename	= filename
40		self.revision	= revision
41		self.checksum	= checksum
42
43	def __hash__(self):
44		return hash((self.repository, self.filename, self.revision, self.checksum))
45
46	def __eq__(self, other):
47		return (self.repository, self.filename, self.revision, self.checksum) == (other.repository, other.filename, other.revision, other.checksum)
48
49	def getFilename (self):
50		return os.path.basename(self.filename)
51
52	def getCacheFilename (self):
53		return "r%s-%s" % (self.revision, self.getFilename())
54
55	def getChecksum (self):
56		return self.checksum
57
58	def getRevision (self):
59		return self.revision
60
61	def getRepo (self):
62		return self.repository
63
64	def getRevision (self):
65		return self.revision
66
67	def getFilename (self):
68		return self.filename
69
70def computeChecksum (data):
71	dataFiltered = data.replace('\r','')
72	hash = hashlib.sha256(dataFiltered.encode("utf-8")).hexdigest()
73	return hash
74
75def makeSourceUrl (repository, revision, filename):
76	return "%s/%s/%s" % (repository, revision, filename)
77
78def checkoutGit (repository, revision, fullDstPath):
79	if not os.path.exists(fullDstPath):
80		execute(["git", "clone", "--no-checkout", repository, fullDstPath])
81
82	pushWorkingDir(fullDstPath)
83	try:
84		execute(["git", "fetch", repository, "+refs/heads/*:refs/remotes/origin/*"])
85		execute(["git", "checkout", revision])
86	finally:
87		popWorkingDir()
88
89def checkoutFile (repository, revision, filename, cacheDir):
90	if sys.version_info < (3, 0):
91		from urllib2 import urlopen
92	else:
93		from urllib.request import urlopen
94
95	try:
96		req		= urlopen(makeSourceUrl(repository, revision, filename))
97		data	= req.read()
98		if sys.version_info >= (3, 0):
99			data	= data.decode("utf-8")
100	except IOError:
101		fullDstPath = os.path.join(cacheDir, "git")
102
103		checkoutGit(repository, revision, fullDstPath)
104		f		= open(os.path.join(fullDstPath, filename), "rt")
105		data	= f.read()
106		f.close()
107	except:
108		print("Unexpected error:", sys.exc_info()[0])
109
110	return data
111
112def fetchFile (dstPath, repository, revision, filename, checksum, cacheDir):
113	def writeFile (filename, data):
114		f = open(filename, 'wt')
115		f.write(data)
116		f.close()
117
118	if not os.path.exists(os.path.dirname(dstPath)):
119		os.makedirs(os.path.dirname(dstPath))
120
121	print("Fetching %s/%s@%s" % (repository, filename, revision))
122	data		= checkoutFile(repository, revision, filename, cacheDir)
123	gotChecksum	= computeChecksum(data)
124
125	if checksum != gotChecksum:
126		raise Exception("Checksum mismatch, expected %s, got %s" % (checksum, gotChecksum))
127
128	writeFile(dstPath, data)
129
130def checkFile (filename, checksum):
131	def readFile (filename):
132		f = open(filename, 'rt')
133		data = f.read()
134		f.close()
135		return data
136
137	if os.path.exists(filename):
138		return computeChecksum(readFile(filename)) == checksum
139	else:
140		return False
141
142g_registryCache = {}
143
144def getRegistry (source):
145	global g_registryCache
146
147	if source in g_registryCache:
148		return g_registryCache[source]
149
150	cacheDir	= os.path.join(os.path.dirname(__file__), "cache")
151	cachePath	= os.path.join(cacheDir, source.getCacheFilename())
152
153	if not checkFile(cachePath, source.checksum):
154		fetchFile(cachePath, source.getRepo(), source.getRevision(), source.getFilename(), source.getChecksum(), cacheDir)
155
156	parsedReg	= registry.parse(cachePath)
157
158	g_registryCache[source] = parsedReg
159
160	return parsedReg
161