diff options
Diffstat (limited to 'tools/python/google/path_utils.py')
-rw-r--r-- | tools/python/google/path_utils.py | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/tools/python/google/path_utils.py b/tools/python/google/path_utils.py new file mode 100644 index 0000000..0585614 --- /dev/null +++ b/tools/python/google/path_utils.py @@ -0,0 +1,109 @@ +# Copyright 2008, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""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 |