# HG changeset patch # User Martin Geisler # Date 2010-09-03 10:58:51 # Node ID af8c4929931c58930b42235373f13bfe71d6c278 # Parent dfb11f9922c152bd74f5d827d89ec39f8749c1ad localrepo: add auditor attribute which knows about subrepos diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -28,6 +28,7 @@ class localrepository(repo.repository): 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.opener = util.opener(self.path) self.wopener = util.opener(self.root) self.baseui = baseui @@ -111,6 +112,44 @@ class localrepository(repo.repository): self._datafilters = {} self._transref = self._lockref = self._wlockref = None + def _checknested(self, path): + """Determine if path is a legal nested repository.""" + if not path.startswith(self.root): + return False + subpath = path[len(self.root) + 1:] + + # XXX: Checking against the current working copy is wrong in + # the sense that it can reject things like + # + # $ hg cat -r 10 sub/x.txt + # + # if sub/ is no longer a subrepository in the working copy + # parent revision. + # + # However, it can of course also allow things that would have + # been rejected before, such as the above cat command if sub/ + # is a subrepository now, but was a normal directory before. + # The old path auditor would have rejected by mistake since it + # panics when it sees sub/.hg/. + # + # All in all, checking against the working copy parent + # revision seems sensible since we want to prevent access to + # nested repositories on the filesystem *now*. + ctx = self['.'] + parts = util.splitpath(subpath) + while parts: + prefix = os.sep.join(parts) + if prefix in ctx.substate: + if prefix == subpath: + return True + else: + sub = ctx.sub(prefix) + return sub.checknested(subpath[len(prefix) + 1:]) + else: + parts.pop() + return False + + @propertycache def changelog(self): c = changelog.changelog(self.sopener) diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -210,6 +210,10 @@ class abstractsubrepo(object): """ raise NotImplementedError + def checknested(path): + """check if path is a subrepository within this repository""" + return False + def commit(self, text, user, date): """commit the current changes to the subrepo with the given log message. Use given user and date if possible. Return the @@ -280,6 +284,9 @@ class hgsubrepo(abstractsubrepo): return True return w.dirty() # working directory changed + def checknested(self, path): + return self._repo._checknested(self._repo.wjoin(path)) + def commit(self, text, user, date): self._repo.ui.debug("committing subrepo %s\n" % relpath(self)) n = self._repo.commit(text, user, date)