diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -39,8 +39,6 @@ parsers = policy.importmod('parsers') rustmod = policy.importrust('dirstate') -SUPPORTS_DIRSTATE_V2 = rustmod is not None - propertycache = util.propertycache filecache = scmutil.filecache _rangemask = dirstatemap.rangemask diff --git a/mercurial/dirstatemap.py b/mercurial/dirstatemap.py --- a/mercurial/dirstatemap.py +++ b/mercurial/dirstatemap.py @@ -332,15 +332,6 @@ denormalized form that they appear as in the dirstate. """ - def __init__(self, ui, opener, root, nodeconstants, use_dirstate_v2): - super(dirstatemap, self).__init__( - ui, opener, root, nodeconstants, use_dirstate_v2 - ) - if self._use_dirstate_v2: - msg = "Dirstate V2 not supportedi" - msg += "(should have detected unsupported requirement)" - raise error.ProgrammingError(msg) - ### Core data storage and access @propertycache @@ -406,19 +397,17 @@ self._opener.join(self._filename) ) - try: - fp = self._opendirstatefile() - try: - st = fp.read() - finally: - fp.close() - except IOError as err: - if err.errno != errno.ENOENT: - raise - return + if self._use_dirstate_v2: + if not self.docket.uuid: + return + st = self._opener.read(self.docket.data_filename()) + else: + st = self._readdirstatefile() + if not st: return + # TODO: adjust this estimate for dirstate-v2 if util.safehasattr(parsers, b'dict_new_presized'): # Make an estimate of the number of files in the dirstate based on # its size. This trades wasting some memory for avoiding costly @@ -440,8 +429,14 @@ # parsing the dirstate. # # (we cannot decorate the function directly since it is in a C module) - parse_dirstate = util.nogc(parsers.parse_dirstate) - p = parse_dirstate(self._map, self.copymap, st) + if self._use_dirstate_v2: + p = self.docket.parents + meta = self.docket.tree_metadata + parse_dirstate = util.nogc(v2.parse_dirstate) + parse_dirstate(self._map, self.copymap, st, meta) + else: + parse_dirstate = util.nogc(parsers.parse_dirstate) + p = parse_dirstate(self._map, self.copymap, st) if not self._dirtyparents: self.setparents(*p) @@ -450,10 +445,16 @@ self.__getitem__ = self._map.__getitem__ self.get = self._map.get - def write(self, _tr, st, now): - d = parsers.pack_dirstate(self._map, self.copymap, self.parents(), now) - st.write(d) - st.close() + def write(self, tr, st, now): + if self._use_dirstate_v2: + packed, meta = v2.pack_dirstate(self._map, self.copymap, now) + self.write_v2_no_append(tr, st, meta, packed) + else: + packed = parsers.pack_dirstate( + self._map, self.copymap, self.parents(), now + ) + st.write(packed) + st.close() self._dirtyparents = False @propertycache diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -917,9 +917,6 @@ # Start with all requirements supported by this file. supported = set(localrepository._basesupported) - if dirstate.SUPPORTS_DIRSTATE_V2: - supported.add(requirementsmod.DIRSTATE_V2_REQUIREMENT) - # Execute ``featuresetupfuncs`` entries if they belong to an extension # relevant to this ui instance. modules = {m.__name__ for n, m in extensions.extensions(ui)} @@ -1266,6 +1263,7 @@ requirementsmod.NODEMAP_REQUIREMENT, bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT, requirementsmod.SHARESAFE_REQUIREMENT, + requirementsmod.DIRSTATE_V2_REQUIREMENT, } _basesupported = supportedformats | { requirementsmod.STORE_REQUIREMENT, @@ -3609,15 +3607,7 @@ # experimental config: format.exp-dirstate-v2 # Keep this logic in sync with `has_dirstate_v2()` in `tests/hghave.py` if ui.configbool(b'format', b'exp-dirstate-v2'): - if dirstate.SUPPORTS_DIRSTATE_V2: - requirements.add(requirementsmod.DIRSTATE_V2_REQUIREMENT) - else: - raise error.Abort( - _( - b"dirstate v2 format requested by config " - b"but not supported (requires Rust extensions)" - ) - ) + requirements.add(requirementsmod.DIRSTATE_V2_REQUIREMENT) # experimental config: format.exp-use-copies-side-data-changeset if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'): diff --git a/tests/test-dirstate-race.t b/tests/test-dirstate-race.t --- a/tests/test-dirstate-race.t +++ b/tests/test-dirstate-race.t @@ -1,7 +1,6 @@ #testcases dirstate-v1 dirstate-v2 #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif diff --git a/tests/test-dirstate-race2.t b/tests/test-dirstate-race2.t --- a/tests/test-dirstate-race2.t +++ b/tests/test-dirstate-race2.t @@ -1,7 +1,6 @@ #testcases dirstate-v1 dirstate-v2 #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif diff --git a/tests/test-dirstate.t b/tests/test-dirstate.t --- a/tests/test-dirstate.t +++ b/tests/test-dirstate.t @@ -1,7 +1,6 @@ #testcases dirstate-v1 dirstate-v2 #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif diff --git a/tests/test-hgignore.t b/tests/test-hgignore.t --- a/tests/test-hgignore.t +++ b/tests/test-hgignore.t @@ -1,7 +1,6 @@ #testcases dirstate-v1 dirstate-v2 #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif @@ -397,9 +396,10 @@ #endif -#if dirstate-v2 +#if dirstate-v2 rust Check the hash of ignore patterns written in the dirstate +This is an optimization that is only relevant when using the Rust extensions $ hg status > /dev/null $ cat .hg/testhgignore .hg/testhgignorerel .hgignore dir2/.hgignore dir1/.hgignore dir1/.hgignoretwo | $TESTDIR/f --sha1 diff --git a/tests/test-permissions.t b/tests/test-permissions.t --- a/tests/test-permissions.t +++ b/tests/test-permissions.t @@ -3,7 +3,6 @@ #testcases dirstate-v1 dirstate-v2 #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif diff --git a/tests/test-purge.t b/tests/test-purge.t --- a/tests/test-purge.t +++ b/tests/test-purge.t @@ -1,7 +1,6 @@ #testcases dirstate-v1 dirstate-v2 #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif diff --git a/tests/test-status.t b/tests/test-status.t --- a/tests/test-status.t +++ b/tests/test-status.t @@ -1,13 +1,6 @@ #testcases dirstate-v1 dirstate-v2 -#if no-rust - $ hg init repo0 --config format.exp-dirstate-v2=1 - abort: dirstate v2 format requested by config but not supported (requires Rust extensions) - [255] -#endif - #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif @@ -743,7 +736,7 @@ if also listing unknowns. The tree-based dirstate and status algorithm fix this: -#if symlink no-dirstate-v1 +#if symlink no-dirstate-v1 rust $ cd .. $ hg init issue6335 @@ -759,11 +752,11 @@ ? bar/a ? foo - $ hg status -c # incorrect output with `dirstate-v1` + $ hg status -c # incorrect output without the Rust implementation $ hg status -cu ? bar/a ? foo - $ hg status -d # incorrect output with `dirstate-v1` + $ hg status -d # incorrect output without the Rust implementation ! foo/a $ hg status -du ! foo/a @@ -910,7 +903,7 @@ I B.hs I ignored-folder/ctest.hs -#if dirstate-v2 +#if rust dirstate-v2 Check read_dir caching diff --git a/tests/test-symlinks.t b/tests/test-symlinks.t --- a/tests/test-symlinks.t +++ b/tests/test-symlinks.t @@ -3,7 +3,6 @@ #testcases dirstate-v1 dirstate-v2 #if dirstate-v2 -#require rust $ echo '[format]' >> $HGRCPATH $ echo 'exp-dirstate-v2=1' >> $HGRCPATH #endif