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