1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2013 The Chromium Authors 2*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 3*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 4*8975f5c5SAndroid Build Coastguard Worker 5*8975f5c5SAndroid Build Coastguard Worker"""Generic utilities for all python scripts.""" 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Workerimport atexit 8*8975f5c5SAndroid Build Coastguard Workerimport httplib 9*8975f5c5SAndroid Build Coastguard Workerimport os 10*8975f5c5SAndroid Build Coastguard Workerimport signal 11*8975f5c5SAndroid Build Coastguard Workerimport stat 12*8975f5c5SAndroid Build Coastguard Workerimport subprocess 13*8975f5c5SAndroid Build Coastguard Workerimport sys 14*8975f5c5SAndroid Build Coastguard Workerimport tempfile 15*8975f5c5SAndroid Build Coastguard Workerimport urlparse 16*8975f5c5SAndroid Build Coastguard Worker 17*8975f5c5SAndroid Build Coastguard Worker 18*8975f5c5SAndroid Build Coastguard Workerdef GetPlatformName(): 19*8975f5c5SAndroid Build Coastguard Worker """Return a string to be used in paths for the platform.""" 20*8975f5c5SAndroid Build Coastguard Worker if IsWindows(): 21*8975f5c5SAndroid Build Coastguard Worker return 'win' 22*8975f5c5SAndroid Build Coastguard Worker if IsMac(): 23*8975f5c5SAndroid Build Coastguard Worker return 'mac' 24*8975f5c5SAndroid Build Coastguard Worker if IsLinux(): 25*8975f5c5SAndroid Build Coastguard Worker return 'linux' 26*8975f5c5SAndroid Build Coastguard Worker raise NotImplementedError('Unknown platform "%s".' % sys.platform) 27*8975f5c5SAndroid Build Coastguard Worker 28*8975f5c5SAndroid Build Coastguard Worker 29*8975f5c5SAndroid Build Coastguard Workerdef IsWindows(): 30*8975f5c5SAndroid Build Coastguard Worker return sys.platform == 'cygwin' or sys.platform.startswith('win') 31*8975f5c5SAndroid Build Coastguard Worker 32*8975f5c5SAndroid Build Coastguard Worker 33*8975f5c5SAndroid Build Coastguard Workerdef IsLinux(): 34*8975f5c5SAndroid Build Coastguard Worker return sys.platform.startswith('linux') 35*8975f5c5SAndroid Build Coastguard Worker 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Workerdef IsMac(): 38*8975f5c5SAndroid Build Coastguard Worker return sys.platform.startswith('darwin') 39*8975f5c5SAndroid Build Coastguard Worker 40*8975f5c5SAndroid Build Coastguard Worker 41*8975f5c5SAndroid Build Coastguard Workerdef _DeleteDir(path): 42*8975f5c5SAndroid Build Coastguard Worker """Deletes a directory recursively, which must exist.""" 43*8975f5c5SAndroid Build Coastguard Worker # Don't use shutil.rmtree because it can't delete read-only files on Win. 44*8975f5c5SAndroid Build Coastguard Worker for root, dirs, files in os.walk(path, topdown=False): 45*8975f5c5SAndroid Build Coastguard Worker for name in files: 46*8975f5c5SAndroid Build Coastguard Worker filename = os.path.join(root, name) 47*8975f5c5SAndroid Build Coastguard Worker os.chmod(filename, stat.S_IWRITE) 48*8975f5c5SAndroid Build Coastguard Worker os.remove(filename) 49*8975f5c5SAndroid Build Coastguard Worker for name in dirs: 50*8975f5c5SAndroid Build Coastguard Worker os.rmdir(os.path.join(root, name)) 51*8975f5c5SAndroid Build Coastguard Worker os.rmdir(path) 52*8975f5c5SAndroid Build Coastguard Worker 53*8975f5c5SAndroid Build Coastguard Worker 54*8975f5c5SAndroid Build Coastguard Workerdef Delete(path): 55*8975f5c5SAndroid Build Coastguard Worker """Deletes the given file or directory (recursively), which must exist.""" 56*8975f5c5SAndroid Build Coastguard Worker if os.path.isdir(path): 57*8975f5c5SAndroid Build Coastguard Worker _DeleteDir(path) 58*8975f5c5SAndroid Build Coastguard Worker else: 59*8975f5c5SAndroid Build Coastguard Worker os.remove(path) 60*8975f5c5SAndroid Build Coastguard Worker 61*8975f5c5SAndroid Build Coastguard Worker 62*8975f5c5SAndroid Build Coastguard Workerdef MaybeDelete(path): 63*8975f5c5SAndroid Build Coastguard Worker """Deletes the given file or directory (recurisvely), if it exists.""" 64*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(path): 65*8975f5c5SAndroid Build Coastguard Worker Delete(path) 66*8975f5c5SAndroid Build Coastguard Worker 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Workerdef MakeTempDir(parent_dir=None): 69*8975f5c5SAndroid Build Coastguard Worker """Creates a temporary directory and returns an absolute path to it. 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker The temporary directory is automatically deleted when the python interpreter 72*8975f5c5SAndroid Build Coastguard Worker exits normally. 73*8975f5c5SAndroid Build Coastguard Worker 74*8975f5c5SAndroid Build Coastguard Worker Args: 75*8975f5c5SAndroid Build Coastguard Worker parent_dir: the directory to create the temp dir in. If None, the system 76*8975f5c5SAndroid Build Coastguard Worker temp dir is used. 77*8975f5c5SAndroid Build Coastguard Worker 78*8975f5c5SAndroid Build Coastguard Worker Returns: 79*8975f5c5SAndroid Build Coastguard Worker The absolute path to the temporary directory. 80*8975f5c5SAndroid Build Coastguard Worker """ 81*8975f5c5SAndroid Build Coastguard Worker path = tempfile.mkdtemp(dir=parent_dir) 82*8975f5c5SAndroid Build Coastguard Worker atexit.register(MaybeDelete, path) 83*8975f5c5SAndroid Build Coastguard Worker return path 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Worker 86*8975f5c5SAndroid Build Coastguard Workerdef Unzip(zip_path, output_dir): 87*8975f5c5SAndroid Build Coastguard Worker """Unzips the given zip file using a system installed unzip tool. 88*8975f5c5SAndroid Build Coastguard Worker 89*8975f5c5SAndroid Build Coastguard Worker Args: 90*8975f5c5SAndroid Build Coastguard Worker zip_path: zip file to unzip. 91*8975f5c5SAndroid Build Coastguard Worker output_dir: directory to unzip the contents of the zip file. The directory 92*8975f5c5SAndroid Build Coastguard Worker must exist. 93*8975f5c5SAndroid Build Coastguard Worker 94*8975f5c5SAndroid Build Coastguard Worker Raises: 95*8975f5c5SAndroid Build Coastguard Worker RuntimeError if the unzip operation fails. 96*8975f5c5SAndroid Build Coastguard Worker """ 97*8975f5c5SAndroid Build Coastguard Worker if IsWindows(): 98*8975f5c5SAndroid Build Coastguard Worker unzip_cmd = ['C:\\Program Files\\7-Zip\\7z.exe', 'x', '-y'] 99*8975f5c5SAndroid Build Coastguard Worker else: 100*8975f5c5SAndroid Build Coastguard Worker unzip_cmd = ['unzip', '-o'] 101*8975f5c5SAndroid Build Coastguard Worker unzip_cmd += [zip_path] 102*8975f5c5SAndroid Build Coastguard Worker if RunCommand(unzip_cmd, output_dir) != 0: 103*8975f5c5SAndroid Build Coastguard Worker raise RuntimeError('Unable to unzip %s to %s' % (zip_path, output_dir)) 104*8975f5c5SAndroid Build Coastguard Worker 105*8975f5c5SAndroid Build Coastguard Worker 106*8975f5c5SAndroid Build Coastguard Workerdef Kill(pid): 107*8975f5c5SAndroid Build Coastguard Worker """Terminate the given pid.""" 108*8975f5c5SAndroid Build Coastguard Worker if IsWindows(): 109*8975f5c5SAndroid Build Coastguard Worker subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)]) 110*8975f5c5SAndroid Build Coastguard Worker else: 111*8975f5c5SAndroid Build Coastguard Worker os.kill(pid, signal.SIGTERM) 112*8975f5c5SAndroid Build Coastguard Worker 113*8975f5c5SAndroid Build Coastguard Worker 114*8975f5c5SAndroid Build Coastguard Workerdef RunCommand(cmd, cwd=None): 115*8975f5c5SAndroid Build Coastguard Worker """Runs the given command and returns the exit code. 116*8975f5c5SAndroid Build Coastguard Worker 117*8975f5c5SAndroid Build Coastguard Worker Args: 118*8975f5c5SAndroid Build Coastguard Worker cmd: list of command arguments. 119*8975f5c5SAndroid Build Coastguard Worker cwd: working directory to execute the command, or None if the current 120*8975f5c5SAndroid Build Coastguard Worker working directory should be used. 121*8975f5c5SAndroid Build Coastguard Worker 122*8975f5c5SAndroid Build Coastguard Worker Returns: 123*8975f5c5SAndroid Build Coastguard Worker The exit code of the command. 124*8975f5c5SAndroid Build Coastguard Worker """ 125*8975f5c5SAndroid Build Coastguard Worker process = subprocess.Popen(cmd, cwd=cwd) 126*8975f5c5SAndroid Build Coastguard Worker process.wait() 127*8975f5c5SAndroid Build Coastguard Worker return process.returncode 128*8975f5c5SAndroid Build Coastguard Worker 129*8975f5c5SAndroid Build Coastguard Worker 130*8975f5c5SAndroid Build Coastguard Workerdef DoesUrlExist(url): 131*8975f5c5SAndroid Build Coastguard Worker """Determines whether a resource exists at the given URL. 132*8975f5c5SAndroid Build Coastguard Worker 133*8975f5c5SAndroid Build Coastguard Worker Args: 134*8975f5c5SAndroid Build Coastguard Worker url: URL to be verified. 135*8975f5c5SAndroid Build Coastguard Worker 136*8975f5c5SAndroid Build Coastguard Worker Returns: 137*8975f5c5SAndroid Build Coastguard Worker True if url exists, otherwise False. 138*8975f5c5SAndroid Build Coastguard Worker """ 139*8975f5c5SAndroid Build Coastguard Worker parsed = urlparse.urlparse(url) 140*8975f5c5SAndroid Build Coastguard Worker try: 141*8975f5c5SAndroid Build Coastguard Worker conn = httplib.HTTPConnection(parsed.netloc) 142*8975f5c5SAndroid Build Coastguard Worker conn.request('HEAD', parsed.path) 143*8975f5c5SAndroid Build Coastguard Worker response = conn.getresponse() 144*8975f5c5SAndroid Build Coastguard Worker except (socket.gaierror, socket.error): 145*8975f5c5SAndroid Build Coastguard Worker return False 146*8975f5c5SAndroid Build Coastguard Worker finally: 147*8975f5c5SAndroid Build Coastguard Worker conn.close() 148*8975f5c5SAndroid Build Coastguard Worker # Follow both permanent (301) and temporary (302) redirects. 149*8975f5c5SAndroid Build Coastguard Worker if response.status == 302 or response.status == 301: 150*8975f5c5SAndroid Build Coastguard Worker return DoesUrlExist(response.getheader('location')) 151*8975f5c5SAndroid Build Coastguard Worker return response.status == 200 152