diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -664,7 +664,28 @@ def revert(repo, node, choose): def verify(repo): """verify the consistency of a repository""" - return verifymod.verify(repo) + ret = verifymod.verify(repo) + + # Broken subrepo references in hidden csets don't seem worth worrying about, + # since they can't be pushed/pulled, and --hidden can be used if they are a + # concern. + + # pathto() is needed for -R case + revs = repo.revs("filelog(%s)", + util.pathto(repo.root, repo.getcwd(), '.hgsubstate')) + + if revs: + repo.ui.status(_('checking subrepo links\n')) + for rev in revs: + ctx = repo[rev] + try: + for subpath in ctx.substate: + ret = ctx.sub(subpath).verify() or ret + except Exception: + repo.ui.warn(_('.hgsubstate is corrupt in revision %s\n') % + node.short(ctx.node())) + + return ret def remoteui(src, opts): 'build a remote ui from ui or repo and opts' diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -572,6 +572,12 @@ class abstractsubrepo(object): def shortid(self, revid): return revid + def verify(self): + '''verify the integrity of the repository. Return 0 on success or + warning, 1 on any error. + ''' + return 0 + @propertycache def wvfs(self): """return vfs to access the working directory of this subrepository @@ -1011,6 +1017,24 @@ class hgsubrepo(abstractsubrepo): def shortid(self, revid): return revid[:12] + def verify(self): + try: + rev = self._state[1] + ctx = self._repo.unfiltered()[rev] + if ctx.hidden(): + # Since hidden revisions aren't pushed/pulled, it seems worth an + # explicit warning. + ui = self._repo.ui + ui.warn(_("subrepo '%s' is hidden in revision %s\n") % + (self._relpath, node.short(self._ctx.node()))) + return 0 + except error.RepoLookupError: + # A missing subrepo revision may be a case of needing to pull it, so + # don't treat this as an error. + self._repo.ui.warn(_("subrepo '%s' not found in revision %s\n") % + (self._relpath, node.short(self._ctx.node()))) + return 0 + @propertycache def wvfs(self): """return own wvfs for efficiency and consitency diff --git a/tests/test-static-http.t b/tests/test-static-http.t --- a/tests/test-static-http.t +++ b/tests/test-static-http.t @@ -129,6 +129,7 @@ test with "/" URI (issue747) and subrepo crosschecking files in changesets and manifests checking files 3 files, 1 changesets, 3 total revisions + checking subrepo links $ cat a a $ hg paths diff --git a/tests/test-subrepo-missing.t b/tests/test-subrepo-missing.t --- a/tests/test-subrepo-missing.t +++ b/tests/test-subrepo-missing.t @@ -106,4 +106,19 @@ check that --hidden is propagated to the $ hg --hidden cat subrepo/a foo +verify will warn if locked-in subrepo revisions are hidden or missing + + $ hg ci -m "amended subrepo (again)" + $ hg --config extensions.strip= --hidden strip -R subrepo -qr 'tip' + $ hg verify + checking changesets + checking manifests + crosschecking files in changesets and manifests + checking files + 2 files, 5 changesets, 5 total revisions + checking subrepo links + subrepo 'subrepo' is hidden in revision a66de08943b6 + subrepo 'subrepo' is hidden in revision 674d05939c1e + subrepo 'subrepo' not found in revision a7d05d9055a4 + $ cd ..