コード例 #1
0
ファイル: scmutil.py プロジェクト: gobizen/hg-stable
    def __call__(self, path):
        '''Check the relative path.
        path may contain a pattern (e.g. foodir/**.txt)'''

        path = util.localpath(path)
        normpath = self.normcase(path)
        if normpath 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)
        parts = util.splitpath(path)
        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 '%s' is inside nested repo %r") % (path, base))

        normparts = util.splitpath(normpath)
        assert len(parts) == len(normparts)

        parts.pop()
        normparts.pop()
        prefixes = []
        while parts:
            prefix = os.sep.join(parts)
            normprefix = os.sep.join(normparts)
            if normprefix 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 '%s' is inside nested "
                              "repo %r") % (path, prefix))
            prefixes.append(normprefix)
            parts.pop()
            normparts.pop()
コード例 #2
0
ファイル: pathutil.py プロジェクト: leetaizhu/Odoo_ENV_MAC_OS
    def __call__(self, path):
        '''Check the relative path.
        path may contain a pattern (e.g. foodir/**.txt)'''

        path = util.localpath(path)
        normpath = self.normcase(path)
        if normpath 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)
        parts = util.splitpath(path)
        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 '%s' is inside nested repo %r")
                                     % (path, base))

        normparts = util.splitpath(normpath)
        assert len(parts) == len(normparts)

        parts.pop()
        normparts.pop()
        prefixes = []
        while parts:
            prefix = os.sep.join(parts)
            normprefix = os.sep.join(normparts)
            if normprefix 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 '%s' is inside nested "
                                           "repo %r")
                                         % (path, prefix))
            prefixes.append(normprefix)
            parts.pop()
            normparts.pop()
コード例 #3
0
def canonpath(root, cwd, myname, auditor=None):
    '''return the canonical path of myname, given cwd and root'''
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep):]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ''
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows). The list
        # `rel' holds the reversed list of components making up the relative
        # file name we want.
        rel = []
        while True:
            try:
                s = util.samefile(name, root)
            except OSError:
                s = False
            if s:
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ''
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = util.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        # A common mistake is to use -R, but specify a file relative to the repo
        # instead of cwd.  Detect that case, and provide a hint to the user.
        hint = None
        try:
            if cwd != root:
                canonpath(root, root, myname, auditor)
                hint = (_("consider using '--cwd %s'")
                        % os.path.relpath(root, cwd))
        except util.Abort:
            pass

        raise util.Abort(_("%s not under root '%s'") % (myname, root),
                         hint=hint)
コード例 #4
0
ファイル: pathutil.py プロジェクト: nixiValor/Waterfox
    def __call__(self, path):
        """Check the relative path.
        path may contain a pattern (e.g. foodir/**.txt)"""

        path = util.localpath(path)
        normpath = self.normcase(path)
        if normpath 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)
        parts = util.splitpath(path)
        if os.path.splitdrive(path)[0] or _lowerclean(parts[0]) in (".hg", ".hg.", "") or os.pardir in parts:
            raise util.Abort(_("path contains illegal component: %s") % path)
        # Windows shortname aliases
        for p in parts:
            if "~" in p:
                first, last = p.split("~", 1)
                if last.isdigit() and first.upper() in ["HG", "HG8B6C"]:
                    raise util.Abort(_("path contains illegal component: %s") % path)
        if ".hg" in _lowerclean(path):
            lparts = [_lowerclean(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 '%s' is inside nested repo %r") % (path, base))

        normparts = util.splitpath(normpath)
        assert len(parts) == len(normparts)

        parts.pop()
        normparts.pop()
        prefixes = []
        while parts:
            prefix = os.sep.join(parts)
            normprefix = os.sep.join(normparts)
            if normprefix 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 '%s' is inside nested " "repo %r") % (path, prefix))
            prefixes.append(normprefix)
            parts.pop()
            normparts.pop()
コード例 #5
0
 def getcwd(self):
     cwd = os.getcwd()
     if cwd == self._root: return ''
     # self._root ends with a path separator if self._root is '/' or 'C:\'
     rootsep = self._root
     if not util.endswithsep(rootsep):
         rootsep += os.sep
     if cwd.startswith(rootsep):
         return cwd[len(rootsep):]
     else:
         # we're outside the repo. return an absolute path.
         return cwd
コード例 #6
0
ファイル: dirstate.py プロジェクト: c0ns0le/cygwin
 def getcwd(self):
     cwd = os.getcwd()
     if cwd == self._root: return ''
     # self._root ends with a path separator if self._root is '/' or 'C:\'
     rootsep = self._root
     if not util.endswithsep(rootsep):
         rootsep += os.sep
     if cwd.startswith(rootsep):
         return cwd[len(rootsep):]
     else:
         # we're outside the repo. return an absolute path.
         return cwd
コード例 #7
0
ファイル: scmutil.py プロジェクト: sandeepprasanna/ODOO
def canonpath(root, cwd, myname, auditor=None):
    '''return the canonical path of myname, given cwd and root'''
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep):]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ''
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows).  For each
        # `name', compare dev/inode numbers.  If they match, the list `rel'
        # holds the reversed list of components making up the relative file
        # name we want.
        root_st = os.stat(root)
        rel = []
        while True:
            try:
                name_st = os.stat(name)
            except OSError:
                name_st = None
            if name_st and util.samestat(name_st, root_st):
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ''
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = os.path.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        raise util.Abort('%s not under root' % myname)
コード例 #8
0
def canonpath(root, cwd, myname, auditor=None):
    '''return the canonical path of myname, given cwd and root'''
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep):]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ''
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows).  For each
        # `name', compare dev/inode numbers.  If they match, the list `rel'
        # holds the reversed list of components making up the relative file
        # name we want.
        root_st = os.stat(root)
        rel = []
        while True:
            try:
                name_st = os.stat(name)
            except OSError:
                name_st = None
            if name_st and util.samestat(name_st, root_st):
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ''
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = os.path.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        raise util.Abort('%s not under root' % myname)
コード例 #9
0
ファイル: scmutil.py プロジェクト: jordigh/mercurial-crew
def canonpath(root, cwd, myname, auditor=None):
    """return the canonical path of myname, given cwd and root"""
    if util.endswithsep(root):
        rootsep = root
    else:
        rootsep = root + os.sep
    name = myname
    if not os.path.isabs(name):
        name = os.path.join(root, cwd, name)
    name = os.path.normpath(name)
    if auditor is None:
        auditor = pathauditor(root)
    if name != rootsep and name.startswith(rootsep):
        name = name[len(rootsep) :]
        auditor(name)
        return util.pconvert(name)
    elif name == root:
        return ""
    else:
        # Determine whether `name' is in the hierarchy at or beneath `root',
        # by iterating name=dirname(name) until that causes no change (can't
        # check name == '/', because that doesn't work on windows). The list
        # `rel' holds the reversed list of components making up the relative
        # file name we want.
        rel = []
        while True:
            try:
                s = util.samefile(name, root)
            except OSError:
                s = False
            if s:
                if not rel:
                    # name was actually the same as root (maybe a symlink)
                    return ""
                rel.reverse()
                name = os.path.join(*rel)
                auditor(name)
                return util.pconvert(name)
            dirname, basename = util.split(name)
            rel.append(basename)
            if dirname == name:
                break
            name = dirname

        raise util.Abort(_("%s not under root '%s'") % (myname, root))
コード例 #10
0
ファイル: dirstate.py プロジェクト: CSCI-362-02-2015/RedTeam
    def getcwd(self):
        '''Return the path from which a canonical path is calculated.

        This path should be used to resolve file patterns or to convert
        canonical paths back to file paths for display. It shouldn't be
        used to get real file paths. Use vfs functions instead.
        '''
        cwd = self._cwd
        if cwd == self._root:
            return ''
        # self._root ends with a path separator if self._root is '/' or 'C:\'
        rootsep = self._root
        if not util.endswithsep(rootsep):
            rootsep += os.sep
        if cwd.startswith(rootsep):
            return cwd[len(rootsep):]
        else:
            # we're outside the repo. return an absolute path.
            return cwd
コード例 #11
0
ファイル: dirstate.py プロジェクト: html-shell/mozilla-build
    def getcwd(self):
        '''Return the path from which a canonical path is calculated.

        This path should be used to resolve file patterns or to convert
        canonical paths back to file paths for display. It shouldn't be
        used to get real file paths. Use vfs functions instead.
        '''
        cwd = self._cwd
        if cwd == self._root:
            return ''
        # self._root ends with a path separator if self._root is '/' or 'C:\'
        rootsep = self._root
        if not util.endswithsep(rootsep):
            rootsep += os.sep
        if cwd.startswith(rootsep):
            return cwd[len(rootsep):]
        else:
            # we're outside the repo. return an absolute path.
            return cwd
コード例 #12
0
ファイル: cmdutil.py プロジェクト: saminigod/cygwin
                    res = lambda p: dest
        return res

    pats = util.expand_glob(pats)
    if not pats:
        raise util.Abort(_('no source or destination specified'))
    if len(pats) == 1:
        raise util.Abort(_('no destination specified'))
    dest = pats.pop()
    destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
    if not destdirexists:
        if len(pats) > 1 or util.patkind(pats[0], None)[0]:
            raise util.Abort(
                _('with multiple sources, destination must be an '
                  'existing directory'))
        if util.endswithsep(dest):
            raise util.Abort(_('destination %s is not a directory') % dest)

    tfn = targetpathfn
    if after:
        tfn = targetpathafterfn
    copylist = []
    for pat in pats:
        srcs = walkpat(pat)
        if not srcs:
            continue
        copylist.append((tfn(pat, dest, srcs), srcs))
    if not copylist:
        raise util.Abort(_('no files to copy'))

    errors = 0
コード例 #13
0
ファイル: cmdutil.py プロジェクト: MezzLabs/mercurial
                    res = lambda p: dest
        return res


    pats = expandpats(pats)
    if not pats:
        raise util.Abort(_('no source or destination specified'))
    if len(pats) == 1:
        raise util.Abort(_('no destination specified'))
    dest = pats.pop()
    destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
    if not destdirexists:
        if len(pats) > 1 or matchmod.patkind(pats[0]):
            raise util.Abort(_('with multiple sources, destination must be an '
                               'existing directory'))
        if util.endswithsep(dest):
            raise util.Abort(_('destination %s is not a directory') % dest)

    tfn = targetpathfn
    if after:
        tfn = targetpathafterfn
    copylist = []
    for pat in pats:
        srcs = walkpat(pat)
        if not srcs:
            continue
        copylist.append((tfn(pat, dest, srcs), srcs))
    if not copylist:
        raise util.Abort(_('no files to copy'))

    errors = 0
コード例 #14
0
    def statwalk(self,
                 files=None,
                 match=util.always,
                 unknown=True,
                 ignored=False,
                 badmatch=None,
                 directories=False):
        '''
        walk recursively through the directory tree, finding all files
        matched by the match function

        results are yielded in a tuple (src, filename, st), where src
        is one of:
        'f' the file was found in the directory tree
        'd' the file is a directory of the tree
        'm' the file was only in the dirstate and not in the tree
        'b' file was not found and matched badmatch

        and st is the stat result if the file was found in the directory.
        '''

        # walk all files by default
        if not files:
            files = ['.']
            dc = self._map.copy()
        else:
            files = util.unique(files)
            dc = self._filter(files)

        def imatch(file_):
            if file_ not in dc and self._ignore(file_):
                return False
            return match(file_)

        # TODO: don't walk unknown directories if unknown and ignored are False
        ignore = self._ignore
        dirignore = self._dirignore
        if ignored:
            imatch = match
            ignore = util.never
            dirignore = util.never

        # self._root may end with a path separator when self._root == '/'
        common_prefix_len = len(self._root)
        if not util.endswithsep(self._root):
            common_prefix_len += 1

        normpath = util.normpath
        listdir = osutil.listdir
        lstat = os.lstat
        bisect_left = bisect.bisect_left
        isdir = os.path.isdir
        pconvert = util.pconvert
        join = os.path.join
        s_isdir = stat.S_ISDIR
        supported = self._supported
        _join = self._join
        known = {'.hg': 1}

        # recursion free walker, faster than os.walk.
        def findfiles(s):
            work = [s]
            wadd = work.append
            found = []
            add = found.append
            if directories:
                add((normpath(s[common_prefix_len:]), 'd', lstat(s)))
            while work:
                top = work.pop()
                entries = listdir(top, stat=True)
                # nd is the top of the repository dir tree
                nd = normpath(top[common_prefix_len:])
                if nd == '.':
                    nd = ''
                else:
                    # do not recurse into a repo contained in this
                    # one. use bisect to find .hg directory so speed
                    # is good on big directory.
                    names = [e[0] for e in entries]
                    hg = bisect_left(names, '.hg')
                    if hg < len(names) and names[hg] == '.hg':
                        if isdir(join(top, '.hg')):
                            continue
                for f, kind, st in entries:
                    np = pconvert(join(nd, f))
                    if np in known:
                        continue
                    known[np] = 1
                    p = join(top, f)
                    # don't trip over symlinks
                    if kind == stat.S_IFDIR:
                        if not ignore(np):
                            wadd(p)
                            if directories:
                                add((np, 'd', st))
                        if np in dc and match(np):
                            add((np, 'm', st))
                    elif imatch(np):
                        if supported(np, st.st_mode):
                            add((np, 'f', st))
                        elif np in dc:
                            add((np, 'm', st))
            found.sort()
            return found

        # step one, find all files that match our criteria
        files.sort()
        for ff in files:
            nf = normpath(ff)
            f = _join(ff)
            try:
                st = lstat(f)
            except OSError, inst:
                found = False
                for fn in dc:
                    if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
                        found = True
                        break
                if not found:
                    if inst.errno != errno.ENOENT or not badmatch:
                        self._ui.warn('%s: %s\n' %
                                      (self.pathto(ff), inst.strerror))
                    elif badmatch and badmatch(ff) and imatch(nf):
                        yield 'b', ff, None
                continue
            if s_isdir(st.st_mode):
                if not dirignore(nf):
                    for f, src, st in findfiles(f):
                        yield src, f, st
            else:
                if nf in known:
                    continue
                known[nf] = 1
                if match(nf):
                    if supported(ff, st.st_mode, verbose=True):
                        yield 'f', nf, st
                    elif ff in dc:
                        yield 'm', nf, st
コード例 #15
0
ファイル: dirstate.py プロジェクト: c0ns0le/cygwin
    def statwalk(self, files=None, match=util.always, unknown=True,
                 ignored=False, badmatch=None, directories=False):
        '''
        walk recursively through the directory tree, finding all files
        matched by the match function

        results are yielded in a tuple (src, filename, st), where src
        is one of:
        'f' the file was found in the directory tree
        'd' the file is a directory of the tree
        'm' the file was only in the dirstate and not in the tree
        'b' file was not found and matched badmatch

        and st is the stat result if the file was found in the directory.
        '''

        # walk all files by default
        if not files:
            files = ['.']
            dc = self._map.copy()
        else:
            files = util.unique(files)
            dc = self._filter(files)

        def imatch(file_):
            if file_ not in dc and self._ignore(file_):
                return False
            return match(file_)

        # TODO: don't walk unknown directories if unknown and ignored are False
        ignore = self._ignore
        dirignore = self._dirignore
        if ignored:
            imatch = match
            ignore = util.never
            dirignore = util.never

        # self._root may end with a path separator when self._root == '/'
        common_prefix_len = len(self._root)
        if not util.endswithsep(self._root):
            common_prefix_len += 1

        normpath = util.normpath
        listdir = osutil.listdir
        lstat = os.lstat
        bisect_left = bisect.bisect_left
        isdir = os.path.isdir
        pconvert = util.pconvert
        join = os.path.join
        s_isdir = stat.S_ISDIR
        supported = self._supported
        _join = self._join
        known = {'.hg': 1}

        # recursion free walker, faster than os.walk.
        def findfiles(s):
            work = [s]
            wadd = work.append
            found = []
            add = found.append
            if directories:
                add((normpath(s[common_prefix_len:]), 'd', lstat(s)))
            while work:
                top = work.pop()
                entries = listdir(top, stat=True)
                # nd is the top of the repository dir tree
                nd = normpath(top[common_prefix_len:])
                if nd == '.':
                    nd = ''
                else:
                    # do not recurse into a repo contained in this
                    # one. use bisect to find .hg directory so speed
                    # is good on big directory.
                    names = [e[0] for e in entries]
                    hg = bisect_left(names, '.hg')
                    if hg < len(names) and names[hg] == '.hg':
                        if isdir(join(top, '.hg')):
                            continue
                for f, kind, st in entries:
                    np = pconvert(join(nd, f))
                    if np in known:
                        continue
                    known[np] = 1
                    p = join(top, f)
                    # don't trip over symlinks
                    if kind == stat.S_IFDIR:
                        if not ignore(np):
                            wadd(p)
                            if directories:
                                add((np, 'd', st))
                        if np in dc and match(np):
                            add((np, 'm', st))
                    elif imatch(np):
                        if supported(np, st.st_mode):
                            add((np, 'f', st))
                        elif np in dc:
                            add((np, 'm', st))
            found.sort()
            return found

        # step one, find all files that match our criteria
        files.sort()
        for ff in files:
            nf = normpath(ff)
            f = _join(ff)
            try:
                st = lstat(f)
            except OSError, inst:
                found = False
                for fn in dc:
                    if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
                        found = True
                        break
                if not found:
                    if inst.errno != errno.ENOENT or not badmatch:
                        self._ui.warn('%s: %s\n' %
                                      (self.pathto(ff), inst.strerror))
                    elif badmatch and badmatch(ff) and imatch(nf):
                        yield 'b', ff, None
                continue
            if s_isdir(st.st_mode):
                if not dirignore(nf):
                    for f, src, st in findfiles(f):
                        yield src, f, st
            else:
                if nf in known:
                    continue
                known[nf] = 1
                if match(nf):
                    if supported(ff, st.st_mode, verbose=True):
                        yield 'f', nf, st
                    elif ff in dc:
                        yield 'm', nf, st
コード例 #16
0
    def __call__(self, path):
        '''Check the relative path.
        path may contain a pattern (e.g. foodir/**.txt)'''

        path = util.localpath(path)
        normpath = self.normcase(path)
        if normpath 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)
        parts = util.splitpath(path)
        if (os.path.splitdrive(path)[0]
            or _lowerclean(parts[0]) in ('.hg', '.hg.', '')
            or os.pardir in parts):
            raise util.Abort(_("path contains illegal component: %s") % path)
        # Windows shortname aliases
        for p in parts:
            if "~" in p:
                first, last = p.split("~", 1)
                if last.isdigit() and first.upper() in ["HG", "HG8B6C"]:
                    raise util.Abort(_("path contains illegal component: %s")
                                     % path)
        if '.hg' in _lowerclean(path):
            lparts = [_lowerclean(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 '%s' is inside nested repo %r")
                                     % (path, base))

        normparts = util.splitpath(normpath)
        assert len(parts) == len(normparts)

        parts.pop()
        normparts.pop()
        prefixes = []
        while parts:
            prefix = os.sep.join(parts)
            normprefix = os.sep.join(normparts)
            if normprefix in self.auditeddir:
                break
            curpath = os.path.join(self.root, prefix)
            try:
                st = os.lstat(curpath)
            except OSError as 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 '%s' is inside nested "
                                           "repo %r")
                                         % (path, prefix))
            prefixes.append(normprefix)
            parts.pop()
            normparts.pop()

        self.audited.add(normpath)
        # 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)