1*35238bceSAndroid Build Coastguard Worker# -*- coding: utf-8 -*- 2*35238bceSAndroid Build Coastguard Worker 3*35238bceSAndroid Build Coastguard Worker#------------------------------------------------------------------------- 4*35238bceSAndroid Build Coastguard Worker# drawElements Quality Program utilities 5*35238bceSAndroid Build Coastguard Worker# -------------------------------------- 6*35238bceSAndroid Build Coastguard Worker# 7*35238bceSAndroid Build Coastguard Worker# Copyright 2015 The Android Open Source Project 8*35238bceSAndroid Build Coastguard Worker# 9*35238bceSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 10*35238bceSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 11*35238bceSAndroid Build Coastguard Worker# You may obtain a copy of the License at 12*35238bceSAndroid Build Coastguard Worker# 13*35238bceSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 14*35238bceSAndroid Build Coastguard Worker# 15*35238bceSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 16*35238bceSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 17*35238bceSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18*35238bceSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 19*35238bceSAndroid Build Coastguard Worker# limitations under the License. 20*35238bceSAndroid Build Coastguard Worker# 21*35238bceSAndroid Build Coastguard Worker#------------------------------------------------------------------------- 22*35238bceSAndroid Build Coastguard Worker 23*35238bceSAndroid Build Coastguard Workerimport os 24*35238bceSAndroid Build Coastguard Workerimport subprocess 25*35238bceSAndroid Build Coastguard Workerimport sys 26*35238bceSAndroid Build Coastguard Worker 27*35238bceSAndroid Build Coastguard WorkerTEXT_FILE_EXTENSION = [ 28*35238bceSAndroid Build Coastguard Worker ".bat", 29*35238bceSAndroid Build Coastguard Worker ".c", 30*35238bceSAndroid Build Coastguard Worker ".cfg", 31*35238bceSAndroid Build Coastguard Worker ".cmake", 32*35238bceSAndroid Build Coastguard Worker ".cpp", 33*35238bceSAndroid Build Coastguard Worker ".css", 34*35238bceSAndroid Build Coastguard Worker ".h", 35*35238bceSAndroid Build Coastguard Worker ".hh", 36*35238bceSAndroid Build Coastguard Worker ".hpp", 37*35238bceSAndroid Build Coastguard Worker ".html", 38*35238bceSAndroid Build Coastguard Worker ".inl", 39*35238bceSAndroid Build Coastguard Worker ".java", 40*35238bceSAndroid Build Coastguard Worker ".js", 41*35238bceSAndroid Build Coastguard Worker ".m", 42*35238bceSAndroid Build Coastguard Worker ".mk", 43*35238bceSAndroid Build Coastguard Worker ".mm", 44*35238bceSAndroid Build Coastguard Worker ".py", 45*35238bceSAndroid Build Coastguard Worker ".rule", 46*35238bceSAndroid Build Coastguard Worker ".sh", 47*35238bceSAndroid Build Coastguard Worker ".test", 48*35238bceSAndroid Build Coastguard Worker ".txt", 49*35238bceSAndroid Build Coastguard Worker ".xml", 50*35238bceSAndroid Build Coastguard Worker ".xsl", 51*35238bceSAndroid Build Coastguard Worker ] 52*35238bceSAndroid Build Coastguard Worker 53*35238bceSAndroid Build Coastguard WorkerBINARY_FILE_EXTENSION = [ 54*35238bceSAndroid Build Coastguard Worker ".bin", 55*35238bceSAndroid Build Coastguard Worker ".png", 56*35238bceSAndroid Build Coastguard Worker ".pkm", 57*35238bceSAndroid Build Coastguard Worker ".xcf", 58*35238bceSAndroid Build Coastguard Worker ".nspv", 59*35238bceSAndroid Build Coastguard Worker ".h264", 60*35238bceSAndroid Build Coastguard Worker ".h265", 61*35238bceSAndroid Build Coastguard Worker ".ivf", 62*35238bceSAndroid Build Coastguard Worker ".obu", 63*35238bceSAndroid Build Coastguard Worker ".mp4", 64*35238bceSAndroid Build Coastguard Worker ".yuv" 65*35238bceSAndroid Build Coastguard Worker] 66*35238bceSAndroid Build Coastguard Worker 67*35238bceSAndroid Build Coastguard Workerdef isTextFile (filePath): 68*35238bceSAndroid Build Coastguard Worker # Special case for a preprocessor test file that uses a non-ascii/utf8 encoding 69*35238bceSAndroid Build Coastguard Worker if filePath.endswith("preprocessor.test"): 70*35238bceSAndroid Build Coastguard Worker return False 71*35238bceSAndroid Build Coastguard Worker # Special case for clang-format which is a baked binary from clang 72*35238bceSAndroid Build Coastguard Worker if filePath.endswith("clang-format"): 73*35238bceSAndroid Build Coastguard Worker return False 74*35238bceSAndroid Build Coastguard Worker 75*35238bceSAndroid Build Coastguard Worker ext = os.path.splitext(filePath)[1] 76*35238bceSAndroid Build Coastguard Worker if ext in TEXT_FILE_EXTENSION: 77*35238bceSAndroid Build Coastguard Worker return True 78*35238bceSAndroid Build Coastguard Worker if ext in BINARY_FILE_EXTENSION: 79*35238bceSAndroid Build Coastguard Worker return False 80*35238bceSAndroid Build Coastguard Worker 81*35238bceSAndroid Build Coastguard Worker # Analyze file contents, zero byte is the marker for a binary file 82*35238bceSAndroid Build Coastguard Worker f = open(filePath, "rb") 83*35238bceSAndroid Build Coastguard Worker 84*35238bceSAndroid Build Coastguard Worker TEST_LIMIT = 1024 85*35238bceSAndroid Build Coastguard Worker nullFound = False 86*35238bceSAndroid Build Coastguard Worker numBytesTested = 0 87*35238bceSAndroid Build Coastguard Worker 88*35238bceSAndroid Build Coastguard Worker byte = f.read(1) 89*35238bceSAndroid Build Coastguard Worker while byte and numBytesTested < TEST_LIMIT: 90*35238bceSAndroid Build Coastguard Worker if byte == "\0": 91*35238bceSAndroid Build Coastguard Worker nullFound = True 92*35238bceSAndroid Build Coastguard Worker break 93*35238bceSAndroid Build Coastguard Worker 94*35238bceSAndroid Build Coastguard Worker byte = f.read(1) 95*35238bceSAndroid Build Coastguard Worker numBytesTested += 1 96*35238bceSAndroid Build Coastguard Worker 97*35238bceSAndroid Build Coastguard Worker f.close() 98*35238bceSAndroid Build Coastguard Worker return not nullFound 99*35238bceSAndroid Build Coastguard Worker 100*35238bceSAndroid Build Coastguard Workerdef getProjectPath (): 101*35238bceSAndroid Build Coastguard Worker # File system hierarchy is fixed 102*35238bceSAndroid Build Coastguard Worker scriptDir = os.path.dirname(os.path.abspath(__file__)) 103*35238bceSAndroid Build Coastguard Worker projectDir = os.path.normpath(os.path.join(scriptDir, "../..")) 104*35238bceSAndroid Build Coastguard Worker return projectDir 105*35238bceSAndroid Build Coastguard Worker 106*35238bceSAndroid Build Coastguard Workerdef git (*args): 107*35238bceSAndroid Build Coastguard Worker process = subprocess.Popen(['git'] + list(args), cwd=getProjectPath(), stdout=subprocess.PIPE) 108*35238bceSAndroid Build Coastguard Worker output = process.communicate()[0] 109*35238bceSAndroid Build Coastguard Worker if process.returncode != 0: 110*35238bceSAndroid Build Coastguard Worker raise Exception("Failed to execute '%s', got %d" % (str(args), process.returncode)) 111*35238bceSAndroid Build Coastguard Worker return output 112*35238bceSAndroid Build Coastguard Worker 113*35238bceSAndroid Build Coastguard Workerdef getAbsolutePathPathFromProjectRelativePath (projectRelativePath): 114*35238bceSAndroid Build Coastguard Worker return os.path.normpath(os.path.join(getProjectPath(), projectRelativePath)) 115*35238bceSAndroid Build Coastguard Worker 116*35238bceSAndroid Build Coastguard Workerdef getChangedFiles (): 117*35238bceSAndroid Build Coastguard Worker # Added, Copied, Moved, Renamed 118*35238bceSAndroid Build Coastguard Worker output = git('diff', '--cached', '--name-only', '-z', '--diff-filter=ACMR') 119*35238bceSAndroid Build Coastguard Worker if not output: 120*35238bceSAndroid Build Coastguard Worker return [] 121*35238bceSAndroid Build Coastguard Worker relativePaths = output.decode().split('\0')[:-1] # remove trailing '' 122*35238bceSAndroid Build Coastguard Worker return [getAbsolutePathPathFromProjectRelativePath(path) for path in relativePaths] 123*35238bceSAndroid Build Coastguard Worker 124*35238bceSAndroid Build Coastguard Workerdef getFilesChangedSince (commit): 125*35238bceSAndroid Build Coastguard Worker # Get all the files changed since a given commit 126*35238bceSAndroid Build Coastguard Worker output = git('diff', '--name-only', '-U0', '-z', '--no-color', '--no-relative', '--diff-filter=ACMR', commit) 127*35238bceSAndroid Build Coastguard Worker relativePaths = output.decode().split('\0')[:-1] # remove trailing '' 128*35238bceSAndroid Build Coastguard Worker return [getAbsolutePathPathFromProjectRelativePath(path) for path in relativePaths] 129*35238bceSAndroid Build Coastguard Worker 130*35238bceSAndroid Build Coastguard Workerdef getFilesCurrentlyDirty (): 131*35238bceSAndroid Build Coastguard Worker # Get all the files currently dirty and uncommitted 132*35238bceSAndroid Build Coastguard Worker return getFilesChangedSince('HEAD') 133*35238bceSAndroid Build Coastguard Worker 134*35238bceSAndroid Build Coastguard Workerdef getFilesModifiedSinceLastCommit (): 135*35238bceSAndroid Build Coastguard Worker # Try to get only the modified files. In a shallow clone with depth 1, 136*35238bceSAndroid Build Coastguard Worker # HEAD^ doesn't exist, so we have no choice but to return all the files. 137*35238bceSAndroid Build Coastguard Worker try: 138*35238bceSAndroid Build Coastguard Worker return getFilesChangedSince('HEAD^') 139*35238bceSAndroid Build Coastguard Worker except: 140*35238bceSAndroid Build Coastguard Worker return getAllProjectFiles() 141*35238bceSAndroid Build Coastguard Worker 142*35238bceSAndroid Build Coastguard Workerdef getAllProjectFiles (): 143*35238bceSAndroid Build Coastguard Worker output = git('ls-files', '--cached', '-z').decode() 144*35238bceSAndroid Build Coastguard Worker relativePaths = output.split('\0')[:-1] # remove trailing '' 145*35238bceSAndroid Build Coastguard Worker return [getAbsolutePathPathFromProjectRelativePath(path) for path in relativePaths] 146*35238bceSAndroid Build Coastguard Worker 147*35238bceSAndroid Build Coastguard Workerdef runCommand (command): 148*35238bceSAndroid Build Coastguard Worker process = runCommandAsync(command) 149*35238bceSAndroid Build Coastguard Worker waitAsyncCommand(process, command) 150*35238bceSAndroid Build Coastguard Worker 151*35238bceSAndroid Build Coastguard Workerdef runCommandAsync (command): 152*35238bceSAndroid Build Coastguard Worker try: 153*35238bceSAndroid Build Coastguard Worker return subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 154*35238bceSAndroid Build Coastguard Worker except OSError as e: 155*35238bceSAndroid Build Coastguard Worker raise RuntimeError('Failed to run command "%s": %s' % (' '.join(command), e.strerror)) 156*35238bceSAndroid Build Coastguard Worker 157*35238bceSAndroid Build Coastguard Workerdef waitAsyncCommand (process, command): 158*35238bceSAndroid Build Coastguard Worker (out, err) = process.communicate() 159*35238bceSAndroid Build Coastguard Worker if process.returncode == 0: 160*35238bceSAndroid Build Coastguard Worker return out 161*35238bceSAndroid Build Coastguard Worker else: 162*35238bceSAndroid Build Coastguard Worker print('Failed to run command "%s": %s' % (' '.join(command), err)) 163*35238bceSAndroid Build Coastguard Worker sys.exit(process.returncode) 164