[PATCH 2 of 2 stable] scmutil: record all symlinks to a repository in walkrepos

Enrique A. Tobis enrique at tobis.com.ar
Thu Dec 11 09:47:48 CST 2014


# HG changeset patch
# User Enrique A. Tobis <enrique at tobis.com.ar>
# Date 1418275100 18000
#      Thu Dec 11 00:18:20 2014 -0500
# Branch stable
# Node ID a2351ea044f117402b17809050bdc5dc2de29ff4
# Parent  c67b563426866e1c717c6a25b0056bb51cb155e5
scmutil: record all symlinks to a repository in walkrepos

In walkrepos, list all paths that lead to a repository when symlinks are
followed, while still avoiding infinite loops.

diff -r c67b56342686 -r a2351ea044f1 mercurial/scmutil.py
--- a/mercurial/scmutil.py	Wed Dec 10 23:46:47 2014 -0500
+++ b/mercurial/scmutil.py	Thu Dec 11 00:18:20 2014 -0500
@@ -448,9 +448,6 @@
 def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
     '''yield every hg repository under path, always recursively.
     The recurse flag will only control recursion into repo working dirs'''
-    def errhandler(err):
-        if err.filename == path:
-            raise err
     samestat = getattr(os.path, 'samestat', None)
     if followsym and samestat is not None:
         def adddir(dirlst, dirname):
@@ -463,35 +460,33 @@
             if not match:
                 dirlst.append(dirstat)
             return not match
+        removedir = lambda dirlst: dirlst.pop()
+        if seen_dirs is None:
+            seen_dirs = []
     else:
         followsym = False
-
-    if (seen_dirs is None) and followsym:
-        seen_dirs = []
-        adddir(seen_dirs, path)
-    for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
+        adddir = lambda dirlst, dirname: not os.path.islink(dirname)
+        removedir = lambda dirlst: None
+    def _walkrepos(path, followsym, seen_dirs, recurse):
+        dirs = [dirname for dirname in os.listdir(path)
+                if os.path.isdir(os.path.join(path, dirname))]
         dirs.sort()
         if '.hg' in dirs:
-            yield root # found a repository
-            qroot = os.path.join(root, '.hg', 'patches')
+            yield path
+            qroot = os.path.join(path, '.hg', 'patches')
             if os.path.isdir(os.path.join(qroot, '.hg')):
-                yield qroot # we have a patch queue repo here
+                yield qroot
             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 adddir(seen_dirs, fname):
-                    if os.path.islink(fname):
-                        for hgname in walkrepos(fname, True, seen_dirs):
-                            yield hgname
-                    else:
-                        newdirs.append(d)
-            dirs[:] = newdirs
+                return # don't descend further
+        for dirname in (os.path.join(path, dirname) for dirname in dirs):
+            if adddir(seen_dirs, dirname):
+                for repo in _walkrepos(dirname, followsym, seen_dirs, recurse):
+                    yield repo
+                removedir(seen_dirs)
+    for repo in _walkrepos(path, followsym, seen_dirs, recurse):
+        yield repo
 
 def osrcpath():
     '''return default os-specific hgrc search path'''
diff -r c67b56342686 -r a2351ea044f1 tests/test-hgwebdirsym.t
--- a/tests/test-hgwebdirsym.t	Wed Dec 10 23:46:47 2014 -0500
+++ b/tests/test-hgwebdirsym.t	Thu Dec 11 00:18:20 2014 -0500
@@ -40,6 +40,9 @@
   /al/
   /b/
   /c/
+  /circle/al/
+  /circle/b/
+  /circle/c/
   
   $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'al/file/tip/a?style=raw'
   200 Script output follows
@@ -53,28 +56,38 @@
   200 Script output follows
   
   c
-
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/al/file/tip/a?style=raw'
+  200 Script output follows
+  
+  a
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/b/file/tip/b?style=raw'
+  200 Script output follows
+  
+  b
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/c/file/tip/c?style=raw'
+  200 Script output follows
+  
+  c
 should fail
 
-  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/al/file/tip/a?style=raw'
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/circle/al/file/tip/a?style=raw'
   404 Not Found
   
   
-  error: repository circle/al/file/tip/a not found
+  error: repository circle/circle/al/file/tip/a not found
   [1]
-  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/b/file/tip/a?style=raw'
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/circle/b/file/tip/b?style=raw'
   404 Not Found
   
   
-  error: repository circle/b/file/tip/a not found
+  error: repository circle/circle/b/file/tip/b not found
   [1]
-  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/c/file/tip/a?style=raw'
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'circle/circle/c/file/tip/c?style=raw'
   404 Not Found
   
   
-  error: repository circle/c/file/tip/a not found
+  error: repository circle/circle/c/file/tip/c not found
   [1]
-
 collections errors
 
   $ cat error-collections.log
diff -r c67b56342686 -r a2351ea044f1 tests/test-walkrepo.py
--- a/tests/test-walkrepo.py	Wed Dec 10 23:46:47 2014 -0500
+++ b/tests/test-walkrepo.py	Thu Dec 11 00:18:20 2014 -0500
@@ -22,22 +22,22 @@
 
 def runtest():
     reposet = frozenset(walkrepos('.', followsym=True))
-    if sym and (len(reposet) != 3):
+    if sym and (len(reposet) != 7):
         print "reposet = %r" % (reposet,)
-        print ("Found %d repositories when I should have found 3"
+        print ("Found %d repositories when I should have found 7"
                % (len(reposet),))
     if (not sym) and (len(reposet) != 2):
         print "reposet = %r" % (reposet,)
         print ("Found %d repositories when I should have found 2"
                % (len(reposet),))
     sub1set = frozenset((pjoin('.', 'sub1'),
-                         pjoin('.', 'circle', 'subdir', 'sub1')))
+                         pjoin('.', 'circle', 'circle', 'subdir', 'sub1')))
     if len(sub1set & reposet) != 1:
         print "sub1set = %r" % (sub1set,)
         print "reposet = %r" % (reposet,)
         print "sub1set and reposet should have exactly one path in common."
-    sub2set = frozenset((pjoin('.', 'subsub1'),
-                         pjoin('.', 'subsubdir', 'subsub1')))
+    sub2set = frozenset((pjoin('.', 'sub1'),
+                         pjoin('.', 'circle', 'subdir', 'circle', 'top1')))
     if len(sub2set & reposet) != 1:
         print "sub2set = %r" % (sub2set,)
         print "reposet = %r" % (reposet,)


More information about the Mercurial-devel mailing list