Index: build/util/lib/common/util.py |
diff --git a/build/util/lib/common/util.py b/build/util/lib/common/util.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a415b1f534b4ef46e7b7b50dddc65ccdcb9d78b9 |
--- /dev/null |
+++ b/build/util/lib/common/util.py |
@@ -0,0 +1,151 @@ |
+# Copyright 2013 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Generic utilities for all python scripts.""" |
+ |
+import atexit |
+import httplib |
+import os |
+import signal |
+import stat |
+import subprocess |
+import sys |
+import tempfile |
+import urlparse |
+ |
+ |
+def GetPlatformName(): |
+ """Return a string to be used in paths for the platform.""" |
+ if IsWindows(): |
+ return 'win' |
+ if IsMac(): |
+ return 'mac' |
+ if IsLinux(): |
+ return 'linux' |
+ raise NotImplementedError('Unknown platform "%s".' % sys.platform) |
+ |
+ |
+def IsWindows(): |
+ return sys.platform == 'cygwin' or sys.platform.startswith('win') |
+ |
+ |
+def IsLinux(): |
+ return sys.platform.startswith('linux') |
+ |
+ |
+def IsMac(): |
+ return sys.platform.startswith('darwin') |
+ |
+ |
+def _DeleteDir(path): |
+ """Deletes a directory recursively, which must exist.""" |
+ # Don't use shutil.rmtree because it can't delete read-only files on Win. |
+ for root, dirs, files in os.walk(path, topdown=False): |
+ for name in files: |
+ filename = os.path.join(root, name) |
+ os.chmod(filename, stat.S_IWRITE) |
+ os.remove(filename) |
+ for name in dirs: |
+ os.rmdir(os.path.join(root, name)) |
+ os.rmdir(path) |
+ |
+ |
+def Delete(path): |
+ """Deletes the given file or directory (recursively), which must exist.""" |
+ if os.path.isdir(path): |
+ _DeleteDir(path) |
+ else: |
+ os.remove(path) |
+ |
+ |
+def MaybeDelete(path): |
+ """Deletes the given file or directory (recurisvely), if it exists.""" |
+ if os.path.exists(path): |
+ Delete(path) |
+ |
+ |
+def MakeTempDir(parent_dir=None): |
+ """Creates a temporary directory and returns an absolute path to it. |
+ |
+ The temporary directory is automatically deleted when the python interpreter |
+ exits normally. |
+ |
+ Args: |
+ parent_dir: the directory to create the temp dir in. If None, the system |
+ temp dir is used. |
+ |
+ Returns: |
+ The absolute path to the temporary directory. |
+ """ |
+ path = tempfile.mkdtemp(dir=parent_dir) |
+ atexit.register(MaybeDelete, path) |
+ return path |
+ |
+ |
+def Unzip(zip_path, output_dir): |
+ """Unzips the given zip file using a system installed unzip tool. |
+ |
+ Args: |
+ zip_path: zip file to unzip. |
+ output_dir: directory to unzip the contents of the zip file. The directory |
+ must exist. |
+ |
+ Raises: |
+ RuntimeError if the unzip operation fails. |
+ """ |
+ if IsWindows(): |
+ unzip_cmd = ['C:\\Program Files\\7-Zip\\7z.exe', 'x', '-y'] |
+ else: |
+ unzip_cmd = ['unzip', '-o'] |
+ unzip_cmd += [zip_path] |
+ if RunCommand(unzip_cmd, output_dir) != 0: |
+ raise RuntimeError('Unable to unzip %s to %s' % (zip_path, output_dir)) |
+ |
+ |
+def Kill(pid): |
+ """Terminate the given pid.""" |
+ if IsWindows(): |
+ subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)]) |
+ else: |
+ os.kill(pid, signal.SIGTERM) |
+ |
+ |
+def RunCommand(cmd, cwd=None): |
+ """Runs the given command and returns the exit code. |
+ |
+ Args: |
+ cmd: list of command arguments. |
+ cwd: working directory to execute the command, or None if the current |
+ working directory should be used. |
+ |
+ Returns: |
+ The exit code of the command. |
+ """ |
+ process = subprocess.Popen(cmd, cwd=cwd) |
+ process.wait() |
+ return process.returncode |
+ |
+ |
+def DoesUrlExist(url): |
+ """Determines whether a resource exists at the given URL. |
+ |
+ Args: |
+ url: URL to be verified. |
+ |
+ Returns: |
+ True if url exists, otherwise False. |
+ """ |
+ parsed = urlparse.urlparse(url) |
+ try: |
+ conn = httplib.HTTPConnection(parsed.netloc) |
+ conn.request('HEAD', parsed.path) |
+ response = conn.getresponse() |
+ except (socket.gaierror, socket.error): |
+ return False |
+ finally: |
+ conn.close() |
+ # Follow both permanent (301) and temporary (302) redirects. |
+ if response.status == 302 or response.status == 301: |
+ return DoesUrlExist(response.getheader('location')) |
+ return response.status == 200 |