github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/make/tools/findleaves.py (about)

     1  #!/usr/bin/env python
     2  #
     3  # Copyright (C) 2009 The Android Open Source Project
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #      http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  #
    17  
    18  #
    19  # Finds files with the specified name under a particular directory, stopping
    20  # the search in a given subdirectory when the file is found.
    21  #
    22  
    23  import os
    24  import sys
    25  
    26  def perform_find(mindepth, prune, dirlist, filenames):
    27    result = []
    28    pruneleaves = set(map(lambda x: os.path.split(x)[1], prune))
    29    seen = set()
    30    for rootdir in dirlist:
    31      rootdepth = rootdir.count("/")
    32      for root, dirs, files in os.walk(rootdir, followlinks=True):
    33        # prune
    34        check_prune = False
    35        for d in dirs:
    36          if d in pruneleaves:
    37            check_prune = True
    38            break
    39        if check_prune:
    40          i = 0
    41          while i < len(dirs):
    42            if dirs[i] in prune:
    43              del dirs[i]
    44            else:
    45              i += 1
    46        # mindepth
    47        if mindepth > 0:
    48          depth = 1 + root.count("/") - rootdepth
    49          if depth < mindepth:
    50            continue
    51        # match
    52        for filename in filenames:
    53          if filename in files:
    54            result.append(os.path.join(root, filename))
    55            del dirs[:]
    56  
    57        # filter out inodes that have already been seen due to symlink loops
    58        i = 0
    59        while i < len(dirs):
    60          st = os.stat(os.path.join(root, dirs[i]))
    61          key = (st.st_dev, st.st_ino)
    62          if key in seen:
    63            del dirs[i]
    64          else:
    65            i += 1
    66            seen.add(key)
    67  
    68    return result
    69  
    70  def usage():
    71    sys.stderr.write("""Usage: %(progName)s [<options>] [--dir=<dir>] <filenames>
    72  Options:
    73     --mindepth=<mindepth>
    74         Both behave in the same way as their find(1) equivalents.
    75     --prune=<dirname>
    76         Avoids returning results from inside any directory called <dirname>
    77         (e.g., "*/out/*"). May be used multiple times.
    78     --dir=<dir>
    79         Add a directory to search.  May be repeated multiple times.  For backwards
    80         compatibility, if no --dir argument is provided then all but the last entry
    81         in <filenames> are treated as directories.
    82  """ % {
    83        "progName": os.path.split(sys.argv[0])[1],
    84      })
    85    sys.exit(1)
    86  
    87  def main(argv):
    88    mindepth = -1
    89    prune = []
    90    dirlist = []
    91    i=1
    92    while i<len(argv) and len(argv[i])>2 and argv[i][0:2] == "--":
    93      arg = argv[i]
    94      if arg.startswith("--mindepth="):
    95        try:
    96          mindepth = int(arg[len("--mindepth="):])
    97        except ValueError:
    98          usage()
    99      elif arg.startswith("--prune="):
   100        p = arg[len("--prune="):]
   101        if len(p) == 0:
   102          usage()
   103        prune.append(p)
   104      elif arg.startswith("--dir="):
   105        d = arg[len("--dir="):]
   106        if len(p) == 0:
   107          usage()
   108        dirlist.append(d)
   109      else:
   110        usage()
   111      i += 1
   112    if len(dirlist) == 0: # backwards compatibility
   113      if len(argv)-i < 2: # need both <dirlist> and <filename>
   114        usage()
   115      dirlist = argv[i:-1]
   116      filenames = [argv[-1]]
   117    else:
   118      if len(argv)-i < 1: # need <filename>
   119        usage()
   120      filenames = argv[i:]
   121    results = list(set(perform_find(mindepth, prune, dirlist, filenames)))
   122    results.sort()
   123    for r in results:
   124      print r
   125  
   126  if __name__ == "__main__":
   127    main(sys.argv)