diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -284,6 +284,12 @@ class localrepository(object): else: self.supported = self._basesupported + # Add compression engines. + for name in util.compengines: + engine = util.compengines[name] + if engine.revlogheader(): + self.supported.add('exp-compression-%s' % name) + if not self.vfs.isdir(): if create: self.requirements = newreporequirements(self) @@ -397,6 +403,10 @@ class localrepository(object): self.svfs.options['aggressivemergedeltas'] = aggressivemergedeltas self.svfs.options['lazydeltabase'] = not scmutil.gddeltaconfig(self.ui) + for r in self.requirements: + if r.startswith('exp-compression-'): + self.svfs.options['compengine'] = r[len('exp-compression-'):] + def _writerequirements(self): scmutil.writerequires(self.vfs, self.requirements) @@ -1994,6 +2004,18 @@ def newreporequirements(repo): if ui.configbool('format', 'dotencode', True): requirements.add('dotencode') + compengine = ui.config('experimental', 'format.compression', 'zlib') + if compengine not in util.compengines: + raise error.Abort(_('compression engine %s defined by ' + 'experimental.format.compression not available') % + compengine, + hint=_('run "hg debuginstall" to list available ' + 'compression engines')) + + # zlib is the historical default and doesn't need an explicit requirement. + if compengine != 'zlib': + requirements.add('exp-compression-%s' % compengine) + if scmutil.gdinitconfig(ui): requirements.add('generaldelta') if ui.configbool('experimental', 'treemanifest', False): diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -272,6 +272,7 @@ class revlog(object): # Mapping of revision integer to full node. self._nodecache = {nullid: nullrev} self._nodepos = None + self._compengine = 'zlib' v = REVLOG_DEFAULT_VERSION opts = getattr(opener, 'options', None) @@ -288,6 +289,8 @@ class revlog(object): if 'aggressivemergedeltas' in opts: self._aggressivemergedeltas = opts['aggressivemergedeltas'] self._lazydeltabase = bool(opts.get('lazydeltabase', False)) + if 'compengine' in opts: + self._compengine = opts['compengine'] if self._chunkcachesize <= 0: raise RevlogError(_('revlog chunk cache size %r is not greater ' @@ -345,7 +348,7 @@ class revlog(object): @util.propertycache def _compressor(self): - return util.compengines['zlib'].revlogcompressor() + return util.compengines[self._compengine].revlogcompressor() def tip(self): return self.node(len(self.index) - 2) diff --git a/tests/test-repo-compengines.t b/tests/test-repo-compengines.t new file mode 100644 --- /dev/null +++ b/tests/test-repo-compengines.t @@ -0,0 +1,78 @@ +A new repository uses zlib storage, which doesn't need a requirement + + $ hg init default + $ cd default + $ cat .hg/requires + dotencode + fncache + generaldelta + revlogv1 + store + + $ touch foo + $ hg -q commit -A -m 'initial commit with a lot of repeated repeated repeated text to trigger compression' + $ hg debugrevlog -c | grep 0x78 + 0x78 (x) : 1 (100.00%) + 0x78 (x) : 110 (100.00%) + + $ cd .. + +Unknown compression engine to format.compression aborts + + $ hg --config experimental.format.compression=unknown init unknown + abort: compression engine unknown defined by experimental.format.compression not available + (run "hg debuginstall" to list available compression engines) + [255] + +A requirement specifying an unknown compression engine results in bail + + $ hg init unknownrequirement + $ cd unknownrequirement + $ echo exp-compression-unknown >> .hg/requires + $ hg log + abort: repository requires features unknown to this Mercurial: exp-compression-unknown! + (see https://mercurial-scm.org/wiki/MissingRequirement for more information) + [255] + + $ cd .. + +#if zstd + + $ hg --config experimental.format.compression=zstd init zstd + $ cd zstd + $ cat .hg/requires + dotencode + exp-compression-zstd + fncache + generaldelta + revlogv1 + store + + $ touch foo + $ hg -q commit -A -m 'initial commit with a lot of repeated repeated repeated text' + + $ hg debugrevlog -c | grep 0x28 + 0x28 : 1 (100.00%) + 0x28 : 98 (100.00%) + + $ cd .. + +Specifying a new format.compression on an existing repo won't introduce data +with that engine or a requirement + + $ cd default + $ touch bar + $ hg --config experimental.format.compression=zstd -q commit -A -m 'add bar with a lot of repeated repeated repeated text' + + $ cat .hg/requires + dotencode + fncache + generaldelta + revlogv1 + store + + $ hg debugrevlog -c | grep 0x78 + 0x78 (x) : 2 (100.00%) + 0x78 (x) : 199 (100.00%) + +#endif