| # Copyright 2011 The Chromium Authors | |
| # 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 as e: | |
| # errno.EEXIST is "File exists". If we see another error, re-raise. | |
| if e.errno != errno.EEXIST: | |
| raise |