| # Copyright (c) 2011 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. |
| |
| """Some utility methods for getting and manipulating paths.""" |
| |
| # TODO(pamg): Have the buildbot use these, too. |
| |
| |
| import errno |
| import os |
| import sys |
| |
| class PathNotFound(Exception): pass |
| |
| def ScriptDir(): |
| """Get the full path to the directory containing the current script.""" |
| script_filename = os.path.abspath(sys.argv[0]) |
| return os.path.dirname(script_filename) |
| |
| def FindAncestor(start_dir, ancestor): |
| """Finds an ancestor dir in a path. |
| |
| For example, FindAncestor('c:\foo\bar\baz', 'bar') would return |
| 'c:\foo\bar'. Unlike FindUpward*, this only looks at direct path ancestors. |
| """ |
| start_dir = os.path.abspath(start_dir) |
| path = start_dir |
| while True: |
| (parent, tail) = os.path.split(path) |
| if tail == ancestor: |
| return path |
| if not tail: |
| break |
| path = parent |
| raise PathNotFound("Unable to find ancestor %s in %s" % (ancestor, start_dir)) |
| |
| def FindUpwardParent(start_dir, *desired_list): |
| """Finds the desired object's parent, searching upward from the start_dir. |
| |
| Searches start_dir and all its parents looking for the desired directory |
| or file, which may be given in one or more path components. Returns the |
| first directory in which the top desired path component was found, or raises |
| PathNotFound if it wasn't. |
| """ |
| desired_path = os.path.join(*desired_list) |
| last_dir = '' |
| cur_dir = start_dir |
| found_path = os.path.join(cur_dir, desired_path) |
| while not os.path.exists(found_path): |
| last_dir = cur_dir |
| cur_dir = os.path.dirname(cur_dir) |
| if last_dir == cur_dir: |
| raise PathNotFound('Unable to find %s above %s' % |
| (desired_path, start_dir)) |
| found_path = os.path.join(cur_dir, desired_path) |
| # Strip the entire original desired path from the end of the one found |
| # and remove a trailing path separator, if present. |
| found_path = found_path[:len(found_path) - len(desired_path)] |
| if found_path.endswith(os.sep): |
| found_path = found_path[:len(found_path) - 1] |
| return found_path |
| |
| |
| def FindUpward(start_dir, *desired_list): |
| """Returns a path to the desired directory or file, searching upward. |
| |
| Searches start_dir and all its parents looking for the desired directory |
| or file, which may be given in one or more path components. Returns the full |
| path to the desired object, or raises PathNotFound if it wasn't found. |
| """ |
| parent = FindUpwardParent(start_dir, *desired_list) |
| return os.path.join(parent, *desired_list) |
| |
| |
| def MaybeMakeDirectory(*path): |
| """Creates an entire path, if it doesn't already exist.""" |
| file_path = os.path.join(*path) |
| try: |
| os.makedirs(file_path) |
| except OSError, e: |
| # errno.EEXIST is "File exists". If we see another error, re-raise. |
| if e.errno != errno.EEXIST: |
| raise |