findleaves.py: prevent recursion into symlink loops

Keep a set of all visited inodes, and prevent recursing into a symlink
to an already visited inode.

Test: m -j
Test: compare `build/tools/findleaves.py --prune=.repo --prune=.git --mindepth=2 --dir=. Android.mk` before and after
Change-Id: Ied14c40d3066ef9f8e8a2b1535f56f7bbbbd0ab6
diff --git a/tools/findleaves.py b/tools/findleaves.py
index 72cc024..f152a87 100755
--- a/tools/findleaves.py
+++ b/tools/findleaves.py
@@ -26,6 +26,7 @@
 def perform_find(mindepth, prune, dirlist, filenames):
   result = []
   pruneleaves = set(map(lambda x: os.path.split(x)[1], prune))
+  seen = set()
   for rootdir in dirlist:
     rootdepth = rootdir.count("/")
     for root, dirs, files in os.walk(rootdir, followlinks=True):
@@ -52,6 +53,18 @@
         if filename in files:
           result.append(os.path.join(root, filename))
           del dirs[:]
+
+      # filter out inodes that have already been seen due to symlink loops
+      i = 0
+      while i < len(dirs):
+        st = os.stat(os.path.join(root, dirs[i]))
+        key = (st.st_dev, st.st_ino)
+        if key in seen:
+          del dirs[i]
+        else:
+          i += 1
+          seen.add(key)
+
   return result
 
 def usage():