diff mercurial/scmutil.py @ 13975:938fbeacac84

move walkrepos from util to scmutil
author Adrian Buehlmann <adrian@cadifra.com>
date Thu, 21 Apr 2011 16:06:19 +0200
parents 23f2736abce3
children af60153b5e3b
line wrap: on
line diff
--- a/mercurial/scmutil.py	Thu Apr 21 13:18:52 2011 +0200
+++ b/mercurial/scmutil.py	Thu Apr 21 16:06:19 2011 +0200
@@ -248,3 +248,50 @@
             name = dirname
 
         raise util.Abort('%s not under root' % myname)
+
+def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
+    '''yield every hg repository under path, recursively.'''
+    def errhandler(err):
+        if err.filename == path:
+            raise err
+    if followsym and hasattr(os.path, 'samestat'):
+        def _add_dir_if_not_there(dirlst, dirname):
+            match = False
+            samestat = os.path.samestat
+            dirstat = os.stat(dirname)
+            for lstdirstat in dirlst:
+                if samestat(dirstat, lstdirstat):
+                    match = True
+                    break
+            if not match:
+                dirlst.append(dirstat)
+            return not match
+    else:
+        followsym = False
+
+    if (seen_dirs is None) and followsym:
+        seen_dirs = []
+        _add_dir_if_not_there(seen_dirs, path)
+    for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
+        dirs.sort()
+        if '.hg' in dirs:
+            yield root # found a repository
+            qroot = os.path.join(root, '.hg', 'patches')
+            if os.path.isdir(os.path.join(qroot, '.hg')):
+                yield qroot # we have a patch queue repo here
+            if recurse:
+                # avoid recursing inside the .hg directory
+                dirs.remove('.hg')
+            else:
+                dirs[:] = [] # don't descend further
+        elif followsym:
+            newdirs = []
+            for d in dirs:
+                fname = os.path.join(root, d)
+                if _add_dir_if_not_there(seen_dirs, fname):
+                    if os.path.islink(fname):
+                        for hgname in walkrepos(fname, True, seen_dirs):
+                            yield hgname
+                    else:
+                        newdirs.append(d)
+            dirs[:] = newdirs