move path_auditor from util to scmutil
authorAdrian Buehlmann <adrian@cadifra.com>
Wed, 20 Apr 2011 22:43:31 +0200
changeset 13972 d1f4e7fd970a
parent 13971 bfeaa88b875d
child 13973 366fa83f9820
move path_auditor from util to scmutil
mercurial/cmdutil.py
mercurial/commands.py
mercurial/localrepo.py
mercurial/merge.py
mercurial/scmutil.py
mercurial/subrepo.py
mercurial/util.py
--- a/mercurial/cmdutil.py	Wed Apr 20 21:41:41 2011 +0200
+++ b/mercurial/cmdutil.py	Wed Apr 20 22:43:31 2011 +0200
@@ -286,7 +286,7 @@
         similarity = float(opts.get('similarity') or 0)
     # we'd use status here, except handling of symlinks and ignore is tricky
     added, unknown, deleted, removed = [], [], [], []
-    audit_path = util.path_auditor(repo.root)
+    audit_path = scmutil.path_auditor(repo.root)
     m = match(repo, pats, opts)
     for abs in repo.walk(m):
         target = repo.wjoin(abs)
--- a/mercurial/commands.py	Wed Apr 20 21:41:41 2011 +0200
+++ b/mercurial/commands.py	Wed Apr 20 22:43:31 2011 +0200
@@ -3554,7 +3554,7 @@
                 fc = ctx[f]
                 repo.wwrite(f, fc.data(), fc.flags())
 
-            audit_path = util.path_auditor(repo.root)
+            audit_path = scmutil.path_auditor(repo.root)
             for f in remove[0]:
                 if repo.dirstate[f] == 'a':
                     repo.dirstate.forget(f)
--- a/mercurial/localrepo.py	Wed Apr 20 21:41:41 2011 +0200
+++ b/mercurial/localrepo.py	Wed Apr 20 22:43:31 2011 +0200
@@ -31,7 +31,7 @@
         self.root = os.path.realpath(util.expandpath(path))
         self.path = os.path.join(self.root, ".hg")
         self.origroot = path
-        self.auditor = util.path_auditor(self.root, self._checknested)
+        self.auditor = scmutil.path_auditor(self.root, self._checknested)
         self.opener = scmutil.opener(self.path)
         self.wopener = scmutil.opener(self.root)
         self.baseui = baseui
--- a/mercurial/merge.py	Wed Apr 20 21:41:41 2011 +0200
+++ b/mercurial/merge.py	Wed Apr 20 22:43:31 2011 +0200
@@ -7,7 +7,7 @@
 
 from node import nullid, nullrev, hex, bin
 from i18n import _
-import util, filemerge, copies, subrepo
+import scmutil, util, filemerge, copies, subrepo
 import errno, os, shutil
 
 class mergestate(object):
@@ -303,7 +303,7 @@
             repo.ui.debug("removing %s\n" % f)
             os.unlink(repo.wjoin(f))
 
-    audit_path = util.path_auditor(repo.root)
+    audit_path = scmutil.path_auditor(repo.root)
 
     numupdates = len(action)
     for i, a in enumerate(action):
--- a/mercurial/scmutil.py	Wed Apr 20 21:41:41 2011 +0200
+++ b/mercurial/scmutil.py	Wed Apr 20 22:43:31 2011 +0200
@@ -7,7 +7,7 @@
 
 from i18n import _
 import util, error
-import os, errno
+import os, errno, stat
 
 def checkportable(ui, f):
     '''Check if filename f is portable and warn or abort depending on config'''
@@ -26,6 +26,81 @@
         raise error.ConfigError(
             _("ui.portablefilenames value is invalid ('%s')") % val)
 
+class path_auditor(object):
+    '''ensure that a filesystem path contains no banned components.
+    the following properties of a path are checked:
+
+    - ends with a directory separator
+    - under top-level .hg
+    - starts at the root of a windows drive
+    - contains ".."
+    - traverses a symlink (e.g. a/symlink_here/b)
+    - inside a nested repository (a callback can be used to approve
+      some nested repositories, e.g., subrepositories)
+    '''
+
+    def __init__(self, root, callback=None):
+        self.audited = set()
+        self.auditeddir = set()
+        self.root = root
+        self.callback = callback
+
+    def __call__(self, path):
+        '''Check the relative path.
+        path may contain a pattern (e.g. foodir/**.txt)'''
+
+        if path in self.audited:
+            return
+        # AIX ignores "/" at end of path, others raise EISDIR.
+        if util.endswithsep(path):
+            raise util.Abort(_("path ends in directory separator: %s") % path)
+        normpath = os.path.normcase(path)
+        parts = util.splitpath(normpath)
+        if (os.path.splitdrive(path)[0]
+            or parts[0].lower() in ('.hg', '.hg.', '')
+            or os.pardir in parts):
+            raise util.Abort(_("path contains illegal component: %s") % path)
+        if '.hg' in path.lower():
+            lparts = [p.lower() for p in parts]
+            for p in '.hg', '.hg.':
+                if p in lparts[1:]:
+                    pos = lparts.index(p)
+                    base = os.path.join(*parts[:pos])
+                    raise util.Abort(_('path %r is inside nested repo %r')
+                                     % (path, base))
+
+        parts.pop()
+        prefixes = []
+        while parts:
+            prefix = os.sep.join(parts)
+            if prefix in self.auditeddir:
+                break
+            curpath = os.path.join(self.root, prefix)
+            try:
+                st = os.lstat(curpath)
+            except OSError, err:
+                # EINVAL can be raised as invalid path syntax under win32.
+                # They must be ignored for patterns can be checked too.
+                if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
+                    raise
+            else:
+                if stat.S_ISLNK(st.st_mode):
+                    raise util.Abort(
+                        _('path %r traverses symbolic link %r')
+                        % (path, prefix))
+                elif (stat.S_ISDIR(st.st_mode) and
+                      os.path.isdir(os.path.join(curpath, '.hg'))):
+                    if not self.callback or not self.callback(curpath):
+                        raise util.Abort(_('path %r is inside nested repo %r') %
+                                         (path, prefix))
+            prefixes.append(prefix)
+            parts.pop()
+
+        self.audited.add(path)
+        # only add prefixes to the cache after checking everything: we don't
+        # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
+        self.auditeddir.update(prefixes)
+
 class opener(object):
     '''Open files relative to a base directory
 
@@ -35,7 +110,7 @@
     def __init__(self, base, audit=True):
         self.base = base
         if audit:
-            self.auditor = util.path_auditor(base)
+            self.auditor = path_auditor(base)
         else:
             self.auditor = util.always
         self.createmode = None
@@ -132,7 +207,7 @@
         name = os.path.join(root, cwd, name)
     name = os.path.normpath(name)
     if auditor is None:
-        auditor = util.path_auditor(root)
+        auditor = path_auditor(root)
     if name != rootsep and name.startswith(rootsep):
         name = name[len(rootsep):]
         auditor(name)
--- a/mercurial/subrepo.py	Wed Apr 20 21:41:41 2011 +0200
+++ b/mercurial/subrepo.py	Wed Apr 20 22:43:31 2011 +0200
@@ -8,7 +8,7 @@
 import errno, os, re, xml.dom.minidom, shutil, posixpath
 import stat, subprocess, tarfile
 from i18n import _
-import config, util, node, error, cmdutil, url, bookmarks
+import config, scmutil, util, node, error, cmdutil, url, bookmarks
 hg = None
 
 nullstate = ('', '', 'empty')
@@ -234,7 +234,7 @@
     import hg as h
     hg = h
 
-    util.path_auditor(ctx._repo.root)(path)
+    scmutil.path_auditor(ctx._repo.root)(path)
     state = ctx.substate.get(path, nullstate)
     if state[2] not in types:
         raise util.Abort(_('unknown subrepo type %s') % state[2])
--- a/mercurial/util.py	Wed Apr 20 21:41:41 2011 +0200
+++ b/mercurial/util.py	Wed Apr 20 22:43:31 2011 +0200
@@ -16,7 +16,7 @@
 from i18n import _
 import error, osutil, encoding
 import errno, re, shutil, sys, tempfile, traceback
-import os, stat, time, calendar, textwrap, unicodedata, signal
+import os, time, calendar, textwrap, unicodedata, signal
 import imp, socket
 
 # Python compatibility
@@ -492,80 +492,6 @@
             return _("filename ends with '%s', which is not allowed "
                      "on Windows") % t
 
-class path_auditor(object):
-    '''ensure that a filesystem path contains no banned components.
-    the following properties of a path are checked:
-
-    - ends with a directory separator
-    - under top-level .hg
-    - starts at the root of a windows drive
-    - contains ".."
-    - traverses a symlink (e.g. a/symlink_here/b)
-    - inside a nested repository (a callback can be used to approve
-      some nested repositories, e.g., subrepositories)
-    '''
-
-    def __init__(self, root, callback=None):
-        self.audited = set()
-        self.auditeddir = set()
-        self.root = root
-        self.callback = callback
-
-    def __call__(self, path):
-        '''Check the relative path.
-        path may contain a pattern (e.g. foodir/**.txt)'''
-
-        if path in self.audited:
-            return
-        # AIX ignores "/" at end of path, others raise EISDIR.
-        if endswithsep(path):
-            raise Abort(_("path ends in directory separator: %s") % path)
-        normpath = os.path.normcase(path)
-        parts = splitpath(normpath)
-        if (os.path.splitdrive(path)[0]
-            or parts[0].lower() in ('.hg', '.hg.', '')
-            or os.pardir in parts):
-            raise Abort(_("path contains illegal component: %s") % path)
-        if '.hg' in path.lower():
-            lparts = [p.lower() for p in parts]
-            for p in '.hg', '.hg.':
-                if p in lparts[1:]:
-                    pos = lparts.index(p)
-                    base = os.path.join(*parts[:pos])
-                    raise Abort(_('path %r is inside nested repo %r')
-                                % (path, base))
-
-        parts.pop()
-        prefixes = []
-        while parts:
-            prefix = os.sep.join(parts)
-            if prefix in self.auditeddir:
-                break
-            curpath = os.path.join(self.root, prefix)
-            try:
-                st = os.lstat(curpath)
-            except OSError, err:
-                # EINVAL can be raised as invalid path syntax under win32.
-                # They must be ignored for patterns can be checked too.
-                if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
-                    raise
-            else:
-                if stat.S_ISLNK(st.st_mode):
-                    raise Abort(_('path %r traverses symbolic link %r') %
-                                (path, prefix))
-                elif (stat.S_ISDIR(st.st_mode) and
-                      os.path.isdir(os.path.join(curpath, '.hg'))):
-                    if not self.callback or not self.callback(curpath):
-                        raise Abort(_('path %r is inside nested repo %r') %
-                                    (path, prefix))
-            prefixes.append(prefix)
-            parts.pop()
-
-        self.audited.add(path)
-        # only add prefixes to the cache after checking everything: we don't
-        # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
-        self.auditeddir.update(prefixes)
-
 def lookup_reg(key, name=None, scope=None):
     return None