diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -87,6 +87,7 @@ from . import ( upgrade, url as urlmod, util, + verify, vfs as vfsmod, wireprotoframing, wireprotoserver, @@ -554,15 +555,9 @@ def debugchangedfiles(ui, repo, rev, **o @command(b'debugcheckstate', [], b'') def debugcheckstate(ui, repo): """validate the correctness of the current dirstate""" - parent1, parent2 = repo.dirstate.parents() - m1 = repo[parent1].manifest() - m2 = repo[parent2].manifest() - errors = 0 - for err in repo.dirstate.verify(m1, m2): - ui.warn(err) - errors += 1 + errors = verify.verifier(repo)._verify_dirstate() if errors: - errstr = _(b".hg/dirstate inconsistent with current parent's manifest") + errstr = _(b"dirstate inconsistent with current parent's manifest") raise error.Abort(errstr) diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -15,6 +15,7 @@ from .utils import stringutil from . import ( error, pycompat, + requirements, revlog, util, ) @@ -210,6 +211,12 @@ class verifier: self._crosscheckfiles(filelinkrevs, filenodes) totalfiles, filerevisions = self._verifyfiles(filenodes, filelinkrevs) + if self.errors: + ui.warn(_(b"not checking dirstate because of previous errors\n")) + dirstate_errors = 0 + else: + dirstate_errors = self._verify_dirstate() + # final report ui.status( _(b"checked %d changesets with %d changes to %d files\n") @@ -225,6 +232,11 @@ class verifier: msg = _(b"(first damaged changeset appears to be %d)\n") msg %= min(self.badrevs) ui.warn(msg) + if dirstate_errors: + ui.warn( + _(b"dirstate inconsistent with current parent's manifest\n") + ) + ui.warn(_(b"%d dirstate errors\n") % dirstate_errors) return 1 return 0 @@ -585,3 +597,25 @@ class verifier: self._warn(_(b"warning: orphan data file '%s'") % f) return len(files), revisions + + def _verify_dirstate(self): + """Check that the dirstate is consistent with the parent's manifest""" + repo = self.repo + ui = self.ui + ui.status(_(b"checking dirstate\n")) + + parent1, parent2 = repo.dirstate.parents() + m1 = repo[parent1].manifest() + m2 = repo[parent2].manifest() + dirstate_errors = 0 + + is_narrow = requirements.NARROW_REQUIREMENT in repo.requirements + narrow_matcher = repo.narrowmatch() if is_narrow else None + + for err in repo.dirstate.verify(m1, m2, narrow_matcher): + ui.error(err) + dirstate_errors += 1 + + if dirstate_errors: + self.errors += dirstate_errors + return dirstate_errors diff --git a/tests/test-amend-subrepo.t b/tests/test-amend-subrepo.t --- a/tests/test-amend-subrepo.t +++ b/tests/test-amend-subrepo.t @@ -190,6 +190,7 @@ broken repositories will refuse to push checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 5 changesets with 12 changes to 4 files checking subrepo links subrepo 't' not found in revision 04aa62396ec6 diff --git a/tests/test-basic.t b/tests/test-basic.t --- a/tests/test-basic.t +++ b/tests/test-basic.t @@ -121,6 +121,7 @@ Verify should succeed: checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 1 changesets with 1 changes to 1 files Repository root: diff --git a/tests/test-censor.t b/tests/test-censor.t --- a/tests/test-censor.t +++ b/tests/test-censor.t @@ -175,6 +175,7 @@ Repo fails verification due to censorshi checking files target@1: censored file data target@2: censored file data + not checking dirstate because of previous errors checked 5 changesets with 7 changes to 2 files 2 integrity errors encountered! (first damaged changeset appears to be 1) diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t --- a/tests/test-commandserver.t +++ b/tests/test-commandserver.t @@ -541,6 +541,7 @@ changelog and manifest would have invali checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 2 changesets with 2 changes to 1 files $ hg revert --no-backup -aq @@ -825,6 +826,7 @@ structured message channel: message: '\xa6Ditem@Cpos\xf6EtopicMcrosscheckingEtotal\xf6DtypeHprogressDunit@' message: '\xa2DdataOchecking files\nDtypeFstatus' message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@' + message: '\xa2DdataRchecking dirstate\nDtypeFstatus' message: '\xa2DdataX/checked 0 changesets with 0 changes to 0 files\nDtypeFstatus' >>> from hgclient import checkwith, readchannel, runcommand, stringio diff --git a/tests/test-fncache.t b/tests/test-fncache.t --- a/tests/test-fncache.t +++ b/tests/test-fncache.t @@ -61,6 +61,7 @@ Testing verify: warning: revlog 'data/a.i' not in fncache! warning: revlog 'data/a.i.hg/c.i' not in fncache! warning: revlog 'data/a.i/b.i' not in fncache! + checking dirstate checked 3 changesets with 3 changes to 3 files 3 warnings encountered! hint: run "hg debugrebuildfncache" to recover from corrupt fncache @@ -349,6 +350,7 @@ Clean cached versions checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 1 changesets with 1 changes to 1 files $ cat .hg/store/fncache data/y.i diff --git a/tests/test-largefiles-wireproto.t b/tests/test-largefiles-wireproto.t --- a/tests/test-largefiles-wireproto.t +++ b/tests/test-largefiles-wireproto.t @@ -242,6 +242,7 @@ test 'verify' with remotestore: checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 1 changesets with 1 changes to 1 files searching 1 changesets for largefiles changeset 0:cf03e5bb9936: f1 missing diff --git a/tests/test-largefiles.t b/tests/test-largefiles.t --- a/tests/test-largefiles.t +++ b/tests/test-largefiles.t @@ -1545,6 +1545,7 @@ revert some files to an older revision checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 10 changesets with 28 changes to 10 files searching 1 changesets for largefiles verified existence of 3 revisions of 3 largefiles diff --git a/tests/test-lfconvert.t b/tests/test-lfconvert.t --- a/tests/test-lfconvert.t +++ b/tests/test-lfconvert.t @@ -345,6 +345,7 @@ process. checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 8 changesets with 13 changes to 9 files searching 7 changesets for largefiles changeset 0:d4892ec57ce2: large references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/2e000fa7e85759c7f4c254d4d9c33ef481e459a7 diff --git a/tests/test-lfs.t b/tests/test-lfs.t --- a/tests/test-lfs.t +++ b/tests/test-lfs.t @@ -789,6 +789,7 @@ Repo with damaged lfs objects in any rev checking files l@1: unpacking 46a2f24864bc: integrity check failed on l:0 large@0: unpacking 2c531e0992ff: integrity check failed on large:0 + not checking dirstate because of previous errors checked 5 changesets with 10 changes to 4 files 2 integrity errors encountered! (first damaged changeset appears to be 0) @@ -851,6 +852,7 @@ blob, and the output shows that it isn't checking files lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store lfs blob sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e renamed large -> l + checking dirstate checked 5 changesets with 10 changes to 4 files Verify will not try to download lfs blobs, if told not to by the config option @@ -865,6 +867,7 @@ Verify will not try to download lfs blob checking files lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store lfs blob sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e renamed large -> l + checking dirstate checked 5 changesets with 10 changes to 4 files Verify will copy/link all lfs objects into the local store that aren't already @@ -885,6 +888,7 @@ the (uncorrupted) remote store. lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store + checking dirstate checked 5 changesets with 10 changes to 4 files Verify will not copy/link a corrupted file from the usercache into the local @@ -902,6 +906,7 @@ store, and poison it. (The verify with large@0: unpacking 2c531e0992ff: integrity check failed on large:0 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store + not checking dirstate because of previous errors checked 5 changesets with 10 changes to 4 files 2 integrity errors encountered! (first damaged changeset appears to be 0) @@ -917,6 +922,7 @@ store, and poison it. (The verify with lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store + checking dirstate checked 5 changesets with 10 changes to 4 files Damaging a file required by the update destination fails the update. @@ -943,6 +949,7 @@ usercache or local store. checking files l@1: unpacking 46a2f24864bc: integrity check failed on l:0 large@0: unpacking 2c531e0992ff: integrity check failed on large:0 + not checking dirstate because of previous errors checked 5 changesets with 10 changes to 4 files 2 integrity errors encountered! (first damaged changeset appears to be 0) @@ -972,6 +979,7 @@ avoids the corrupt lfs object in the ori large@0: unpacking 2c531e0992ff: integrity check failed on large:0 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store + not checking dirstate because of previous errors checked 5 changesets with 10 changes to 4 files 2 integrity errors encountered! (first damaged changeset appears to be 0) diff --git a/tests/test-narrow-clone-stream.t b/tests/test-narrow-clone-stream.t --- a/tests/test-narrow-clone-stream.t +++ b/tests/test-narrow-clone-stream.t @@ -101,4 +101,5 @@ Checking that repository has all the req checking directory manifests (tree !) crosschecking files in changesets and manifests checking files + checking dirstate checked 40 changesets with 1 changes to 1 files diff --git a/tests/test-push.t b/tests/test-push.t --- a/tests/test-push.t +++ b/tests/test-push.t @@ -141,6 +141,7 @@ Expected to fail: $ hg verify -q beta@1: dddc47b3ba30 not in manifests + not checking dirstate because of previous errors 1 integrity errors encountered! (first damaged changeset appears to be 1) [1] @@ -171,6 +172,7 @@ Expected to fail: $ hg verify -q beta@1: manifest refers to unknown revision dddc47b3ba30 + not checking dirstate because of previous errors 1 integrity errors encountered! (first damaged changeset appears to be 1) [1] diff --git a/tests/test-repair-strip.t b/tests/test-repair-strip.t --- a/tests/test-repair-strip.t +++ b/tests/test-repair-strip.t @@ -66,6 +66,7 @@ (expected 1) b@?: 736c29771fba not in manifests warning: orphan data file 'data/c.i' + not checking dirstate because of previous errors checked 2 changesets with 3 changes to 2 files 2 warnings encountered! 2 integrity errors encountered! @@ -79,6 +80,7 @@ checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 2 changesets with 2 changes to 2 files $ teststrip 0 2 r .hg/store/data/b.i % before update 0, strip 2 @@ -93,6 +95,7 @@ checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 4 changesets with 4 changes to 3 files % journal contents (no journal) @@ -124,6 +127,7 @@ b@?: rev 1 points to nonexistent changeset 2 (expected 1) c@?: rev 0 points to nonexistent changeset 3 + not checking dirstate because of previous errors checked 2 changesets with 4 changes to 3 files 1 warnings encountered! 7 integrity errors encountered! @@ -138,6 +142,7 @@ checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 2 changesets with 2 changes to 2 files $ cd .. diff --git a/tests/test-treemanifest.t b/tests/test-treemanifest.t --- a/tests/test-treemanifest.t +++ b/tests/test-treemanifest.t @@ -619,6 +619,7 @@ Verify reports missing dirlog b/bar/orange/fly/housefly.txt@0: in changeset but not in manifest b/foo/apple/bees/flower.py@0: in changeset but not in manifest checking files + not checking dirstate because of previous errors checked 4 changesets with 18 changes to 8 files 6 warnings encountered! (reporevlogstore !) 9 integrity errors encountered! @@ -644,6 +645,7 @@ Verify reports missing dirlog entry (expected None) crosschecking files in changesets and manifests checking files + not checking dirstate because of previous errors checked 4 changesets with 18 changes to 8 files 2 warnings encountered! 8 integrity errors encountered! diff --git a/tests/test-verify.t b/tests/test-verify.t --- a/tests/test-verify.t +++ b/tests/test-verify.t @@ -20,6 +20,7 @@ verify checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 1 changesets with 3 changes to 3 files verify with journal @@ -31,6 +32,7 @@ verify with journal checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 1 changesets with 3 changes to 3 files $ rm .hg/store/journal @@ -55,6 +57,7 @@ introduce some bugs in repo warning: revlog 'data/bar.txt.i' not in fncache! 0: empty or missing bar.txt bar.txt@0: manifest refers to unknown revision 256559129457 + not checking dirstate because of previous errors checked 1 changesets with 0 changes to 3 files 3 warnings encountered! hint: run "hg debugrebuildfncache" to recover from corrupt fncache @@ -83,6 +86,7 @@ Entire changelog missing 0: empty or missing changelog manifest@0: d0b6632564d4 not in changesets manifest@1: 941fc4534185 not in changesets + not checking dirstate because of previous errors 3 integrity errors encountered! (first damaged changeset appears to be 0) [1] @@ -93,6 +97,7 @@ Entire manifest log missing $ rm .hg/store/00manifest.* $ hg verify -q 0: empty or missing manifest + not checking dirstate because of previous errors 1 integrity errors encountered! (first damaged changeset appears to be 0) [1] @@ -106,6 +111,7 @@ Entire filelog missing 0: empty or missing file file@0: manifest refers to unknown revision 362fef284ce2 file@1: manifest refers to unknown revision c10f2164107d + not checking dirstate because of previous errors 1 warnings encountered! hint: run "hg debugrebuildfncache" to recover from corrupt fncache 3 integrity errors encountered! @@ -119,7 +125,13 @@ Entire changelog and manifest log missin $ rm .hg/store/00manifest.* $ hg verify -q warning: orphan data file 'data/file.i' + warning: ignoring unknown working parent c5ddb05ab828! + file marked as tracked in p1 but not in manifest1 1 warnings encountered! + 1 integrity errors encountered! + dirstate inconsistent with current parent's manifest + 1 dirstate errors + [1] $ cp -R .hg/store-full/. .hg/store Entire changelog and filelog missing @@ -134,6 +146,7 @@ Entire changelog and filelog missing ?: empty or missing file file@0: manifest refers to unknown revision 362fef284ce2 file@1: manifest refers to unknown revision c10f2164107d + not checking dirstate because of previous errors 1 warnings encountered! hint: run "hg debugrebuildfncache" to recover from corrupt fncache 6 integrity errors encountered! @@ -149,6 +162,7 @@ Entire manifest log and filelog missing 0: empty or missing manifest warning: revlog 'data/file.i' not in fncache! 0: empty or missing file + not checking dirstate because of previous errors 1 warnings encountered! hint: run "hg debugrebuildfncache" to recover from corrupt fncache 2 integrity errors encountered! @@ -164,6 +178,7 @@ Changelog missing entry manifest@?: 941fc4534185 not in changesets file@?: rev 1 points to nonexistent changeset 1 (expected 0) + not checking dirstate because of previous errors 1 warnings encountered! 3 integrity errors encountered! [1] @@ -175,6 +190,7 @@ Manifest log missing entry $ hg verify -q manifest@1: changeset refers to unknown revision 941fc4534185 file@1: c10f2164107d not in manifests + not checking dirstate because of previous errors 2 integrity errors encountered! (first damaged changeset appears to be 1) [1] @@ -185,6 +201,7 @@ Filelog missing entry $ cp -f .hg/store-partial/data/file.* .hg/store/data $ hg verify -q file@1: manifest refers to unknown revision c10f2164107d + not checking dirstate because of previous errors 1 integrity errors encountered! (first damaged changeset appears to be 1) [1] @@ -198,6 +215,7 @@ Changelog and manifest log missing entry file@?: rev 1 points to nonexistent changeset 1 (expected 0) file@?: c10f2164107d not in manifests + not checking dirstate because of previous errors 1 warnings encountered! 2 integrity errors encountered! [1] @@ -211,6 +229,7 @@ Changelog and filelog missing entry manifest@?: rev 1 points to nonexistent changeset 1 manifest@?: 941fc4534185 not in changesets file@?: manifest refers to unknown revision c10f2164107d + not checking dirstate because of previous errors 3 integrity errors encountered! [1] $ cp -R .hg/store-full/. .hg/store @@ -221,6 +240,7 @@ Manifest and filelog missing entry $ cp -f .hg/store-partial/data/file.* .hg/store/data $ hg verify -q manifest@1: changeset refers to unknown revision 941fc4534185 + not checking dirstate because of previous errors 1 integrity errors encountered! (first damaged changeset appears to be 1) [1] @@ -236,6 +256,7 @@ Corrupt changelog base node to cause fai manifest@?: d0b6632564d4 not in changesets file@?: rev 0 points to unexpected changeset 0 (expected 1) + not checking dirstate because of previous errors 1 warnings encountered! 4 integrity errors encountered! (first damaged changeset appears to be 0) @@ -249,6 +270,7 @@ Corrupt manifest log base node to cause $ hg verify -q manifest@0: reading delta d0b6632564d4: * (glob) file@0: 362fef284ce2 not in manifests + not checking dirstate because of previous errors 2 integrity errors encountered! (first damaged changeset appears to be 0) [1] @@ -260,6 +282,7 @@ Corrupt filelog base node to cause failu > 2> /dev/null $ hg verify -q file@0: unpacking 362fef284ce2: * (glob) + not checking dirstate because of previous errors 1 integrity errors encountered! (first damaged changeset appears to be 0) [1] @@ -290,6 +313,7 @@ test revlog corruption $ hg verify -q a@1: broken revlog! (index a is corrupted) warning: orphan data file 'data/a.i' + not checking dirstate because of previous errors 1 warnings encountered! 1 integrity errors encountered! (first damaged changeset appears to be 1) @@ -307,6 +331,7 @@ test revlog format 0 checking manifests crosschecking files in changesets and manifests checking files + checking dirstate checked 1 changesets with 1 changes to 1 files $ cd .. @@ -332,6 +357,7 @@ test flag processor and skipflags $ hg verify -q base64@0: unpacking 794cee7777cb: integrity check failed on base64:0 + not checking dirstate because of previous errors 1 integrity errors encountered! (first damaged changeset appears to be 0) [1]