D10670: rewriteutil: give examples of public changesets that can't be rewritten
martinvonz created this revision. Herald added a reviewer: durin42. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This patch copies the feature from the evolve extension. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10670 AFFECTED FILES mercurial/rewriteutil.py tests/test-amend.t tests/test-branch-change.t tests/test-commit-amend.t tests/test-fix.t tests/test-histedit-obsolete.t tests/test-rebase-scenario-global.t tests/test-split.t tests/test-unamend.t CHANGE DETAILS diff --git a/tests/test-unamend.t b/tests/test-unamend.t --- a/tests/test-unamend.t +++ b/tests/test-unamend.t @@ -298,7 +298,7 @@ $ hg phase -r . -p 1 new phase-divergent changesets $ hg unamend - abort: cannot unamend public changesets + abort: cannot unamend public changesets: 03ddd6fc5af1 (see 'hg help phases' for details) [10] diff --git a/tests/test-split.t b/tests/test-split.t --- a/tests/test-split.t +++ b/tests/test-split.t @@ -77,7 +77,7 @@ $ hg phase --public -r 'all()' $ hg split . - abort: cannot split public changesets + abort: cannot split public changesets: 1df0d5c5a3ab (see 'hg help phases' for details) [10] diff --git a/tests/test-rebase-scenario-global.t b/tests/test-rebase-scenario-global.t --- a/tests/test-rebase-scenario-global.t +++ b/tests/test-rebase-scenario-global.t @@ -328,11 +328,11 @@ nothing to rebase [1] $ hg rebase -d 5 -b 6 - abort: cannot rebase public changesets + abort: cannot rebase public changesets: e1c4361dd923 (see 'hg help phases' for details) [10] $ hg rebase -d 5 -r '1 + (6::)' - abort: cannot rebase public changesets + abort: cannot rebase public changesets: e1c4361dd923 (see 'hg help phases' for details) [10] diff --git a/tests/test-histedit-obsolete.t b/tests/test-histedit-obsolete.t --- a/tests/test-histedit-obsolete.t +++ b/tests/test-histedit-obsolete.t @@ -307,7 +307,7 @@ o 0:cb9a9f314b8b (public) a $ hg histedit -r '.~2' - abort: cannot edit public changesets + abort: cannot edit public changesets: cb9a9f314b8b, 40db8afa467b (see 'hg help phases' for details) [10] diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -264,11 +264,11 @@ $ hg commit -Aqm "hello" $ hg phase -r 0 --public $ hg fix -r 0 - abort: cannot fix public changesets + abort: cannot fix public changesets: 6470986d2e7b (see 'hg help phases' for details) [10] $ hg fix -r 0 --working-dir - abort: cannot fix public changesets + abort: cannot fix public changesets: 6470986d2e7b (see 'hg help phases' for details) [10] $ hg cat -r tip hello.whole diff --git a/tests/test-commit-amend.t b/tests/test-commit-amend.t --- a/tests/test-commit-amend.t +++ b/tests/test-commit-amend.t @@ -10,7 +10,7 @@ $ hg phase -r . -p $ hg ci --amend - abort: cannot amend public changesets + abort: cannot amend public changesets: ad120869acf0 (see 'hg help phases' for details) [10] $ hg phase -r . -f -d diff --git a/tests/test-branch-change.t b/tests/test-branch-change.t --- a/tests/test-branch-change.t +++ b/tests/test-branch-change.t @@ -369,7 +369,7 @@ $ hg phase -r . -p $ hg branch -r . def - abort: cannot change branch of public changesets + abort: cannot change branch of public changesets: d1c2addda4a2 (see 'hg help phases' for details) [10] diff --git a/tests/test-amend.t b/tests/test-amend.t --- a/tests/test-amend.t +++ b/tests/test-amend.t @@ -250,7 +250,7 @@ $ hg phase -r A --public $ hg update -C -q A $ hg amend -m AMEND - abort: cannot amend public changesets + abort: cannot amend public changesets: 426bada5c675 (see 'hg help phases' for details) [10] diff --git a/mercurial/rewriteutil.py b/mercurial/rewriteutil.py --- a/mercurial/rewriteutil.py +++ b/mercurial/rewriteutil.py @@ -17,6 +17,7 @@ from . import ( error, +node, obsolete, obsutil, revset, @@ -28,6 +29,26 @@ NODE_RE = re.compile(br'\b[0-9a-f]{6,64}\b') +def _formatrevs(repo, revs, maxrevs=4): +"""returns a string summarizing revisions in a decent size + +If there are few enough revisions, we list them all. Otherwise we display a +summary of the form: + +1ea73414a91b and 5 others +""" +tonode = repo.changelog.node +numrevs = len(revs) +if numrevs < maxrevs: +shorts = [node.short(tonode(r)) for r in revs] +summary = b', '.join(shorts) +else: +first = revs.first() +summary = _(b'%s and %d others') +summary %= (node.short(tonode(first)), numrevs - 1) +return summary + + def precheck(repo, revs, action=b'rewrite'): """check if revs can be rewritten action is used to control the error message. @@ -50,7 +71,8 @@ publicrevs = repo.revs(b'%ld and public()', revs) if publicrevs: -msg = _(b"cannot %s
D10671: rewriteutil: say how many commits would become orphan if commit is rewritten
martinvonz created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This copies the message from the evolve extension, but modifies it a bit to work with the grammar (in particular with the use of "change branch of" as `action`). I don't know why it doesn't use the same `_formatrevs()` as for public commmits. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10671 AFFECTED FILES mercurial/rewriteutil.py tests/test-amend.t tests/test-branch-change.t tests/test-fix.t tests/test-rebase-collapse.t tests/test-rebase-scenario-global.t tests/test-split.t tests/test-unamend.t CHANGE DETAILS diff --git a/tests/test-unamend.t b/tests/test-unamend.t --- a/tests/test-unamend.t +++ b/tests/test-unamend.t @@ -284,7 +284,7 @@ $ hg --config experimental.evolution=createmarkers unamend - abort: cannot unamend changeset with children + abort: cannot unamend changeset, as that will orphan 3 descendants (see 'hg help evolution.instability') [10] diff --git a/tests/test-split.t b/tests/test-split.t --- a/tests/test-split.t +++ b/tests/test-split.t @@ -466,7 +466,7 @@ $ cd $TESTTMP/d #if obsstore-off $ runsplit -r 1 --no-rebase - abort: cannot split changeset with children + abort: cannot split changeset, as that will orphan 3 descendants (see 'hg help evolution.instability') [10] #else @@ -518,7 +518,7 @@ $ eval `hg tags -T '{tag}={node}\n'` $ rm .hg/localtags $ hg split $B --config experimental.evolution=createmarkers - abort: cannot split changeset with children + abort: cannot split changeset, as that will orphan 4 descendants (see 'hg help evolution.instability') [10] $ cat > $TESTTMP/messages < foo.whole $ hg commit -m "second" $ hg --config experimental.evolution.allowunstable=False fix -r '.^' - abort: cannot fix changeset with children + abort: cannot fix changeset, as that will orphan 1 descendants (see 'hg help evolution.instability') [10] $ hg fix -r '.^' diff --git a/tests/test-branch-change.t b/tests/test-branch-change.t --- a/tests/test-branch-change.t +++ b/tests/test-branch-change.t @@ -57,7 +57,7 @@ Change in middle of the stack (linear commits) $ hg branch -r 1::3 foo - abort: cannot change branch of changeset with children + abort: cannot change branch of changeset, as that will orphan 1 descendants (see 'hg help evolution.instability') [10] @@ -129,7 +129,7 @@ Changing on a branch head which is not topological head $ hg branch -r 2 stable - abort: cannot change branch of changeset with children + abort: cannot change branch of changeset, as that will orphan 2 descendants (see 'hg help evolution.instability') [10] diff --git a/tests/test-amend.t b/tests/test-amend.t --- a/tests/test-amend.t +++ b/tests/test-amend.t @@ -196,7 +196,7 @@ $ hg update -q B $ echo 2 >> B $ hg amend - abort: cannot amend changeset with children + abort: cannot amend changeset, as that will orphan 1 descendants (see 'hg help evolution.instability') [10] diff --git a/mercurial/rewriteutil.py b/mercurial/rewriteutil.py --- a/mercurial/rewriteutil.py +++ b/mercurial/rewriteutil.py @@ -80,7 +80,9 @@ if newunstable: hint = _(b"see 'hg help evolution.instability'") raise error.InputError( -_(b"cannot %s changeset with children") % action, hint=hint +_(b"cannot %s changeset, as that will orphan %d descendants") +% (action, len(newunstable)), +hint=hint, ) if not obsolete.isenabled(repo, obsolete.allowdivergenceopt): To: martinvonz, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10669: debugcommands: fix some plural-agreements I noticed
durin42 created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10669 AFFECTED FILES mercurial/debugcommands.py CHANGE DETAILS diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -4086,7 +4086,7 @@ should complete almost instantaneously and the chances of a consumer being unable to access the repository should be low. -By default, all revlog will be upgraded. You can restrict this using flag +By default, all revlogs will be upgraded. You can restrict this using flags such as `--manifest`: * `--manifest`: only optimize the manifest To: durin42, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10668: config: add --source option to include source of value
martinvonz created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Showing the source of each config option is quite useful and not something the user should have to reach for the `--debug` flag for. I updates documentation and tests, except for one place in `test-hgrc.t` where I thought the test might have been intended to also test that `--debug` results in `ui.quiet` etc being test. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10668 AFFECTED FILES mercurial/commands.py mercurial/helptext/config.txt relnotes/next tests/test-completion.t tests/test-config.t tests/test-hgrc.t tests/test-lfs-bundle.t tests/test-phabricator.t CHANGE DETAILS diff --git a/tests/test-phabricator.t b/tests/test-phabricator.t --- a/tests/test-phabricator.t +++ b/tests/test-phabricator.t @@ -509,9 +509,8 @@ A bad .arcconfig doesn't error out $ echo 'garbage' > .arcconfig - $ hg config phabricator --debug + $ hg config phabricator --source invalid JSON in $TESTTMP/repo/.arcconfig - read config from: */.hgrc (glob) */.hgrc:*: phabricator.debug=True (glob) $TESTTMP/repo/.hg/hgrc:*: phabricator.url=https://phab.mercurial-scm.org/ (glob) $TESTTMP/repo/.hg/hgrc:*: phabricator.callsign=HG (glob) @@ -524,8 +523,7 @@ > EOF $ cp $TESTDIR/../.arcconfig . $ mv .hg/hgrc .hg/hgrc.bak - $ hg config phabricator --debug - read config from: */.hgrc (glob) + $ hg config phabricator --source */.hgrc:*: phabricator.debug=True (glob) $TESTTMP/repo/.arcconfig: phabricator.callsign=HG $TESTTMP/repo/.arcconfig: phabricator.url=https://phab.mercurial-scm.org/ @@ -536,8 +534,7 @@ > url = local > callsign = local > EOF - $ hg config phabricator --debug - read config from: */.hgrc (glob) + $ hg config phabricator --source */.hgrc:*: phabricator.debug=True (glob) $TESTTMP/repo/.hg/hgrc:*: phabricator.url=local (glob) $TESTTMP/repo/.hg/hgrc:*: phabricator.callsign=local (glob) diff --git a/tests/test-lfs-bundle.t b/tests/test-lfs-bundle.t --- a/tests/test-lfs-bundle.t +++ b/tests/test-lfs-bundle.t @@ -101,7 +101,7 @@ #if windows $ unset LOCALAPPDATA $ unset APPDATA - $ HGRCPATH= hg config lfs --debug + $ HGRCPATH= hg config lfs --source abort: unknown lfs usercache location (define LOCALAPPDATA or APPDATA in the environment, or set lfs.usercache) [255] @@ -109,7 +109,7 @@ #if osx $ unset HOME - $ HGRCPATH= hg config lfs --debug + $ HGRCPATH= hg config lfs --source abort: unknown lfs usercache location (define HOME in the environment, or set lfs.usercache) [255] @@ -118,7 +118,7 @@ #if no-windows no-osx $ unset XDG_CACHE_HOME $ unset HOME - $ HGRCPATH= hg config lfs --debug + $ HGRCPATH= hg config lfs --source abort: unknown lfs usercache location (define XDG_CACHE_HOME or HOME in the environment, or set lfs.usercache) [255] diff --git a/tests/test-hgrc.t b/tests/test-hgrc.t --- a/tests/test-hgrc.t +++ b/tests/test-hgrc.t @@ -253,9 +253,8 @@ > [paths] > foo = bar > EOF - $ hg showconfig --debug paths + $ hg showconfig --source paths plain: True - read config from: $TESTTMP/hgrc $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar Test we can skip the user configuration diff --git a/tests/test-config.t b/tests/test-config.t --- a/tests/test-config.t +++ b/tests/test-config.t @@ -277,8 +277,7 @@ > emptysource = `pwd`/emptysource.py > EOF - $ hg config --debug empty.source - read config from: * (glob) + $ hg config --source empty.source none: value $ hg config empty.source -Tjson [ @@ -349,16 +348,16 @@ config affected by environment variables - $ EDITOR=e1 VISUAL=e2 hg config --debug | grep 'ui\.editor' + $ EDITOR=e1 VISUAL=e2 hg config --source | grep 'ui\.editor' $VISUAL: ui.editor=e2 - $ VISUAL=e2 hg config --debug --config ui.editor=e3 | grep 'ui\.editor' + $ VISUAL=e2 hg config --source --config ui.editor=e3 | grep 'ui\.editor' --config: ui.editor=e3 - $ PAGER=p1 hg config --debug | grep 'pager\.pager' + $ PAGER=p1 hg config --source | grep 'pager\.pager' $PAGER: pager.pager=p1 - $ PAGER=p1 hg config --debug --config pager.pager=p2 | grep 'pager\.pager' + $ PAGER=p1 hg config --source --config pager.pager=p2 | grep 'pager\.pager' --config: pager.pager=p2 verify that aliases are evaluated as well diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -262,7 +262,7 @@ cat: output, rev, decode, include, exclude, template clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos - config: untrusted, edit, local, shared, non-shared, global, template + config: untrusted,
D10660: changelogv2: introduce a "changelogv2" feature
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Right now, this means using revlogv2, but only for the changelog. We will have the format more unique in future changesets. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10660 AFFECTED FILES mercurial/changegroup.py mercurial/configitems.py mercurial/localrepo.py mercurial/requirements.py mercurial/revlog.py mercurial/upgrade_utils/actions.py tests/test-copies-chain-merge.t tests/test-copies-in-changeset.t tests/test-persistent-nodemap.t tests/test-sidedata.t tests/test-transaction-safety.t tests/test-upgrade-repo.t CHANGE DETAILS diff --git a/tests/test-upgrade-repo.t b/tests/test-upgrade-repo.t --- a/tests/test-upgrade-repo.t +++ b/tests/test-upgrade-repo.t @@ -65,6 +65,7 @@ persistent-nodemap: yes (rust !) copies-sdc: no revlog-v2: no + changelog-v2:no plain-cl-delta: yes compression:zlib compression-level: default @@ -79,6 +80,7 @@ persistent-nodemap: yesyes no (rust !) copies-sdc: no no no revlog-v2: no no no + changelog-v2:no no no plain-cl-delta: yesyes yes compression:zlib zlibzlib (no-zstd !) compression:zlib zlibzstd (zstd !) @@ -94,6 +96,7 @@ persistent-nodemap: yesyes no (rust !) copies-sdc: no no no revlog-v2: no no no + changelog-v2:no no no plain-cl-delta: yesyes yes compression:zlib zlibzlib (no-zstd !) compression:zlib zlibzstd (zstd !) @@ -109,6 +112,7 @@ [formatvariant.name.mismatchdefault|persistent-nodemap:][formatvariant.repo.mismatchdefault| yes][formatvariant.config.special|yes][formatvariant.default| no] (rust !) [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] + [formatvariant.name.uptodate|changelog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default|zlib] (no-zstd !) [formatvariant.name.mismatchdefault|compression: ][formatvariant.repo.mismatchdefault| zlib][formatvariant.config.special| zlib][formatvariant.default|zstd] (zstd !) @@ -166,6 +170,12 @@ "repo": false }, { +"config": false, +"default": false, +"name": "changelog-v2", +"repo": false + }, + { "config": true, "default": true, "name": "plain-cl-delta", @@ -324,6 +334,7 @@ persistent-nodemap: no copies-sdc: no revlog-v2: no + changelog-v2:no plain-cl-delta: yes compression:zlib compression-level: default @@ -338,6 +349,7 @@ persistent-nodemap: noyes no (rust !) copies-sdc: no no no revlog-v2: no no no + changelog-v2:no no no plain-cl-delta: yesyes yes compression:zlib zlibzlib (no-zstd !) compression:zlib zlibzstd (zstd !) @@ -353,6 +365,7 @@ persistent-nodemap: noyes no (rust !) copies-sdc: no no no revlog-v2: no no no + changelog-v2:no no no plain-cl-delta: yesyes yes compression:zlib zlibzlib (no-zstd !) compression:zlib zlibzstd (zstd !) @@ -368,6 +381,7 @@ [formatvariant.name.mismatchconfig|persistent-nodemap:][formatvariant.repo.mismatchconfig| no][formatvariant.config.special|yes][formatvariant.default| no] (rust !) [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] + [formatvariant.name.uptodate|changelog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
D10667: changelogv2: use a dedicated on disk format for changelogv2
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We drop two unused entry. This is mostly a proof of concept before starting to actually rework the format. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10667 AFFECTED FILES mercurial/configitems.py mercurial/pure/parsers.py mercurial/revlog.py mercurial/revlogutils/constants.py CHANGE DETAILS diff --git a/mercurial/revlogutils/constants.py b/mercurial/revlogutils/constants.py --- a/mercurial/revlogutils/constants.py +++ b/mercurial/revlogutils/constants.py @@ -93,6 +93,20 @@ INDEX_ENTRY_V2 = struct.Struct(b">Qii20s12xQiB19x") assert INDEX_ENTRY_V2.size == 32 * 3, INDEX_ENTRY_V2.size +# 6 bytes: offset +# 2 bytes: flags +# 4 bytes: compressed length +# 4 bytes: uncompressed length +# 4 bytes: parent 1 rev +# 4 bytes: parent 2 rev +# 32 bytes: nodeid +# 8 bytes: sidedata offset +# 4 bytes: sidedata compressed length +# 1 bytes: compression mode (2 lower bit are data_compression_mode) +# 27 bytes: Padding to align to 96 bytes (see RevlogV2Plan wiki page) +INDEX_ENTRY_CL_V2 = struct.Struct(b">Q20s12xQiB27x") +assert INDEX_ENTRY_CL_V2.size == 32 * 3, INDEX_ENTRY_V2.size + # revlog index flags # For historical reasons, revlog's internal flags were exposed via the diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -227,6 +227,15 @@ return index, cache +def parse_index_cl_v2(data, inline): +# call the C implementation to parse the index data +assert not inline +from .pure.parsers import parse_index_cl_v2 + +index, cache = parse_index_cl_v2(data) +return index, cache + + if util.safehasattr(parsers, 'parse_index_devel_nodemap'): def parse_index_v1_nodemap(data, inline): @@ -651,7 +660,7 @@ elif self._format_version == REVLOGV2: self._parse_index = parse_index_v2 elif self._format_version == CHANGELOGV2: -self._parse_index = parse_index_v2 +self._parse_index = parse_index_cl_v2 elif devel_nodemap: self._parse_index = parse_index_v1_nodemap elif use_rust_index: diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -295,6 +295,10 @@ return cls(data, inline), (0, data) +def parse_index_cl_v2(data): +return IndexChangelogV2(data), None + + class IndexObject2(IndexObject): index_format = revlog_constants.INDEX_ENTRY_V2 @@ -355,6 +359,26 @@ raise error.ProgrammingError(msg) +class IndexChangelogV2(IndexObject2): +index_format = revlog_constants.INDEX_ENTRY_CL_V2 + +def _unpack_entry(self, rev, data, r=True): +items = self.index_format.unpack(data) +entry = items[:3] + (rev, rev) + items[3:8] +data_comp = items[8] & 3 +sidedata_comp = (items[8] >> 2) & 3 +return entry + (data_comp, sidedata_comp) + +def _pack_entry(self, rev, entry): +assert entry[3] == rev, entry[3] +assert entry[4] == rev, entry[4] +data = entry[:3] + entry[5:10] +data_comp = entry[10] & 3 +sidedata_comp = (entry[11] & 3) << 2 +data += (data_comp | sidedata_comp,) +return self.index_format.pack(*data) + + def parse_index_devel_nodemap(data, inline): """like parse_index2, but alway return a PersistentNodeMapIndexObject""" return PersistentNodeMapIndexObject(data), None diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -1339,7 +1339,6 @@ # Experimental TODOs: # # * Same as for evlogv2 (but for the reduction of the number of files) -# * drop the storage of the base # * Improvement to investigate # - storing .hgtags fnode # - storing `rank` of changesets To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10665: revlog: signal which revlog index are compatible with Rust
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Otherwise, Rust may treat python object like `cindex` object, leading to trouble. The new attribute is an integer because I expect we might need a flag field in the future. As a start we get the rust code to raise a clear TypeError. We will use the information in a smarter way in the next changesets. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10665 AFFECTED FILES mercurial/cext/parsers.c mercurial/cext/revlog.c mercurial/policy.py mercurial/pure/parsers.py mercurial/revlogutils/revlogv0.py rust/hg-cpython/src/cindex.rs rust/hg-cpython/src/revlog.rs CHANGE DETAILS diff --git a/rust/hg-cpython/src/revlog.rs b/rust/hg-cpython/src/revlog.rs --- a/rust/hg-cpython/src/revlog.rs +++ b/rust/hg-cpython/src/revlog.rs @@ -300,6 +300,11 @@ self.cindex(py).borrow().inner().getattr(py, "entry_size")?.extract::(py) } +@property +def rust_ext_compat() -> PyResult { +self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::(py) +} + }); impl MixedIndex { diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -11,8 +11,8 @@ //! but this will take some time to get there. use cpython::{ -exc::ImportError, ObjectProtocol, PyClone, PyErr, PyObject, PyResult, -PyTuple, Python, PythonObject, +exc::ImportError, exc::TypeError, ObjectProtocol, PyClone, PyErr, +PyObject, PyResult, PyTuple, Python, PythonObject, }; use hg::revlog::{Node, RevlogIndex}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; @@ -90,6 +90,13 @@ ), )); } +let compat: u64 = index.getattr(py, "rust_ext_compat")?.extract(py)?; +if compat == 0 { +return Err(PyErr::new::( +py, +"index object not compatible with Rust", +)); +} Ok(Index { index, capi }) } diff --git a/mercurial/revlogutils/revlogv0.py b/mercurial/revlogutils/revlogv0.py --- a/mercurial/revlogutils/revlogv0.py +++ b/mercurial/revlogutils/revlogv0.py @@ -42,6 +42,7 @@ class revlogoldindex(list): +rust_ext_compat = 0 entry_size = INDEX_ENTRY_V0.size null_item = ( 0, diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -47,6 +47,8 @@ class BaseIndexObject(object): +# Can I be passed to an algorithme implemented in Rust ? +rust_ext_compat = 0 # Format of an index entry according to Python's `struct` language index_format = revlog_constants.INDEX_ENTRY_V1 # Size of a C unsigned long long int, platform independent diff --git a/mercurial/policy.py b/mercurial/policy.py --- a/mercurial/policy.py +++ b/mercurial/policy.py @@ -80,7 +80,7 @@ ('cext', 'bdiff'): 3, ('cext', 'mpatch'): 1, ('cext', 'osutil'): 4, -('cext', 'parsers'): 19, +('cext', 'parsers'): 20, } # map import request to other package or module diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -101,8 +101,10 @@ int inlined; long entry_size; /* size of index headers. Differs in v1 v.s. v2 format */ - char format_version; /* size of index headers. Differs in v1 v.s. v2 - format */ + long rust_ext_compat; /* compatibility with being used in rust +extensions */ + char format_version; /* size of index headers. Differs in v1 v.s. v2 +format */ }; static Py_ssize_t index_length(const indexObject *self) @@ -2769,6 +2771,7 @@ self->offsets = NULL; self->nodelen = 20; self->nullentry = NULL; + self->rust_ext_compat = 1; revlogv2 = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O", kwlist, @@ -2941,6 +2944,8 @@ static PyMemberDef index_members[] = { {"entry_size", T_LONG, offsetof(indexObject, entry_size), 0, "size of an index entry"}, +{"rust_ext_compat", T_LONG, offsetof(indexObject, rust_ext_compat), 0, + "size of an index entry"}, {NULL} /* Sentinel */ }; diff --git a/mercurial/cext/parsers.c b/mercurial/cext/parsers.c --- a/mercurial/cext/parsers.c +++ b/mercurial/cext/parsers.c @@ -668,7 +668,7 @@ void manifest_module_init(PyObject *mod); void revlog_module_init(PyObject *mod); -static const int version = 19; +static const int version = 20; static void module_init(PyObject *mod) { To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list
D10662: changelogv2: `copies-side-data` now implies `changelogv2`
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY To store information about file changes and copies only requires sidedata support for the changelog. So we only enables `changelogv2`. This is less impactful and should help us to ship the changeset centric copy tracing sooner. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10662 AFFECTED FILES mercurial/localrepo.py tests/test-copies-chain-merge.t tests/test-copies-in-changeset.t CHANGE DETAILS diff --git a/tests/test-copies-in-changeset.t b/tests/test-copies-in-changeset.t --- a/tests/test-copies-in-changeset.t +++ b/tests/test-copies-in-changeset.t @@ -42,8 +42,8 @@ persistent-nodemap: no no no (no-rust !) persistent-nodemap: yesyes no (rust !) copies-sdc: yesyes no - revlog-v2: yesyes no - changelog-v2:no no no + revlog-v2: no no no + changelog-v2: yesyes no plain-cl-delta: yesyes yes compression:zlib zlibzlib (no-zstd !) compression:zstd zstdzstd (zstd !) @@ -433,8 +433,8 @@ persistent-nodemap: no no no (no-rust !) persistent-nodemap: yesyes no (rust !) copies-sdc: yesyes no - revlog-v2: yesyes no - changelog-v2:no no no + revlog-v2: no no no + changelog-v2: yesyes no plain-cl-delta: yesyes yes compression:zlib zlibzlib (no-zstd !) compression:zstd zstdzstd (zstd !) @@ -490,8 +490,8 @@ persistent-nodemap: no no no (no-rust !) persistent-nodemap: yesyes no (rust !) copies-sdc: yesyes no - revlog-v2: yesyes no - changelog-v2:no no no + revlog-v2: no no no + changelog-v2: yesyes no plain-cl-delta: yesyes yes compression:zlib zlibzlib (no-zstd !) compression:zstd zstdzstd (zstd !) diff --git a/tests/test-copies-chain-merge.t b/tests/test-copies-chain-merge.t --- a/tests/test-copies-chain-merge.t +++ b/tests/test-copies-chain-merge.t @@ -1660,8 +1660,8 @@ persistent-nodemap: no no no (no-rust !) persistent-nodemap: yesyes no (rust !) copies-sdc: noyes no - revlog-v2: noyes no - changelog-v2:no no no + revlog-v2: no no no + changelog-v2:noyes no plain-cl-delta: yesyes yes compression:* (glob) compression-level: default default default @@ -1670,8 +1670,7 @@ requirements preserved: * (glob) - removed: revlogv1 - added: exp-copies-sidedata-changeset, exp-revlogv2.2 + added: exp-changelog-v2, exp-copies-sidedata-changeset processed revlogs: - all-filelogs @@ -1700,8 +1699,8 @@ persistent-nodemap: no no no (no-rust !) persistent-nodemap: yesyes no (rust !) copies-sdc: noyes no - revlog-v2: noyes no - changelog-v2:no no no + revlog-v2: no no no + changelog-v2:noyes no plain-cl-delta: yesyes yes compression:* (glob) compression-level: default default default @@ -1710,8 +1709,7 @@ requirements preserved: * (glob) - removed: revlogv1 - added: exp-copies-sidedata-changeset, exp-revlogv2.2 + added: exp-changelog-v2, exp-copies-sidedata-changeset processed revlogs: - all-filelogs diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -3523,8 +3523,7 @@ # experimental config: format.exp-use-copies-side-data-changeset if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'): -requirements.discard(requirementsmod.REVLOGV1_REQUIREMENT) -requirements.add(requirementsmod.REVLOGV2_REQUIREMENT) +requirements.add(requirementsmod.CHANGELOGV2_REQUIREMENT) requirements.add(requirementsmod.COPIESSDC_REQUIREMENT) if ui.configbool(b'experimental', b'treemanifest'): requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10666: revlog: do not call Rust code if the index is not compatible with it
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This will avoid hitting the TypeError we defined in the previous changesets. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10666 AFFECTED FILES mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -1062,7 +1062,7 @@ checkrev(r) # and we're sure ancestors aren't filtered as well -if rustancestor is not None: +if rustancestor is not None and self.index.rust_ext_compat: lazyancestors = rustancestor.LazyAncestors arg = self.index else: @@ -1149,7 +1149,7 @@ if common is None: common = [nullrev] -if rustancestor is not None: +if rustancestor is not None and self.index.rust_ext_compat: return rustancestor.MissingAncestors(self.index, common) return ancestor.incrementalmissingancestors(self.parentrevs, common) @@ -1369,7 +1369,7 @@ return self.index.headrevs() except AttributeError: return self._headrevs() -if rustdagop is not None: +if rustdagop is not None and self.index.rust_ext_compat: return rustdagop.headrevs(self.index, revs) return dagop.headrevs(revs, self._uncheckedparentrevs) To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10663: changelogv2: use a dedicated version number
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY If we want to change the format, we need a new version number. We start with that. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10663 AFFECTED FILES mercurial/revlog.py mercurial/revlogutils/constants.py mercurial/revlogutils/docket.py CHANGE DETAILS diff --git a/mercurial/revlogutils/docket.py b/mercurial/revlogutils/docket.py --- a/mercurial/revlogutils/docket.py +++ b/mercurial/revlogutils/docket.py @@ -145,7 +145,8 @@ def default_docket(revlog, version_header): """given a revlog version a new docket object for the given revlog""" -if (version_header & 0x) != constants.REVLOGV2: +rl_version = version_header & 0x +if rl_version not in (constants.REVLOGV2, constants.CHANGELOGV2): return None comp = util.compengines[revlog._compengine].revlogheader() docket = RevlogDocket( diff --git a/mercurial/revlogutils/constants.py b/mercurial/revlogutils/constants.py --- a/mercurial/revlogutils/constants.py +++ b/mercurial/revlogutils/constants.py @@ -36,6 +36,8 @@ REVLOGV1 = 1 # Dummy value until file format is finalized. REVLOGV2 = 0xDEAD +# Dummy value until file format is finalized. +CHANGELOGV2 = 0xD34D ## global revlog header flags # Shared across v1 and v2. @@ -48,6 +50,7 @@ REVLOGV0_FLAGS = 0 REVLOGV1_FLAGS = FLAG_INLINE_DATA | FLAG_GENERALDELTA REVLOGV2_FLAGS = FLAG_INLINE_DATA +CHANGELOGV2_FLAGS = 0 ### individual entry @@ -125,6 +128,7 @@ REVLOGV0: REVLOGV0_FLAGS, REVLOGV1: REVLOGV1_FLAGS, REVLOGV2: REVLOGV2_FLAGS, +CHANGELOGV2: CHANGELOGV2_FLAGS, } _no = lambda flags: False @@ -157,6 +161,13 @@ b'sidedata': True, b'docket': True, }, +CHANGELOGV2: { +b'inline': _no, +# General delta is useless for changelog since we don't do any delta +b'generaldelta': _no, +b'sidedata': True, +b'docket': True, +}, } diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -35,6 +35,7 @@ from .pycompat import getattr from .revlogutils.constants import ( ALL_KINDS, +CHANGELOGV2, COMP_MODE_DEFAULT, COMP_MODE_INLINE, COMP_MODE_PLAIN, @@ -459,7 +460,7 @@ opts = self.opener.options if b'changelogv2' in opts and self.revlog_kind == KIND_CHANGELOG: -new_header = REVLOGV2 +new_header = CHANGELOGV2 elif b'revlogv2' in opts: new_header = REVLOGV2 elif b'revlogv1' in opts: @@ -649,6 +650,8 @@ self._parse_index = revlogv0.parse_index_v0 elif self._format_version == REVLOGV2: self._parse_index = parse_index_v2 +elif self._format_version == CHANGELOGV2: +self._parse_index = parse_index_v2 elif devel_nodemap: self._parse_index = parse_index_v1_nodemap elif use_rust_index: To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10664: revlog: pass around the `rev` we deal with when packing/unpacking entry
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This will help code to compute some flag on the fly. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10664 AFFECTED FILES mercurial/pure/parsers.py CHANGE DETAILS diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -118,10 +118,10 @@ def append(self, tup): if '_nodemap' in vars(self): self._nodemap[tup[7]] = len(self) -data = self._pack_entry(tup) +data = self._pack_entry(len(self), tup) self._extra.append(data) -def _pack_entry(self, entry): +def _pack_entry(self, rev, entry): assert entry[8] == 0 assert entry[9] == 0 return self.index_format.pack(*entry[:8]) @@ -141,12 +141,12 @@ else: index = self._calculate_index(i) data = self._data[index : index + self.entry_size] -r = self._unpack_entry(data) +r = self._unpack_entry(i, data) if self._lgt and i == 0: r = (offset_type(0, gettype(r[0])),) + r[1:] return r -def _unpack_entry(self, data): +def _unpack_entry(self, rev, data): r = self.index_format.unpack(data) r = r + ( 0, @@ -323,17 +323,17 @@ entry[9] = sidedata_length entry[11] = compression_mode entry = tuple(entry) -new = self._pack_entry(entry) +new = self._pack_entry(rev, entry) self._extra[rev - self._lgt] = new -def _unpack_entry(self, data): +def _unpack_entry(self, rev, data): data = self.index_format.unpack(data) entry = data[:10] data_comp = data[10] & 3 sidedata_comp = (data[10] & (3 << 2)) >> 2 return entry + (data_comp, sidedata_comp) -def _pack_entry(self, entry): +def _pack_entry(self, rev, entry): data = entry[:10] data_comp = entry[10] & 3 sidedata_comp = (entry[11] & 3) << 2 @@ -344,7 +344,7 @@ def entry_binary(self, rev): """return the raw binary string representing a revision""" entry = self[rev] -return self._pack_entry(entry) +return self._pack_entry(rev, entry) def pack_header(self, header): """pack header information as binary""" To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10658: revlogv2: no longer attempt to use inline for new revlog
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY revlogv2 steered away for the inline feature. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10658 AFFECTED FILES mercurial/revlog.py tests/test-revlog-v2.t CHANGE DETAILS diff --git a/tests/test-revlog-v2.t b/tests/test-revlog-v2.t --- a/tests/test-revlog-v2.t +++ b/tests/test-revlog-v2.t @@ -61,8 +61,8 @@ $ f --hexdump --bytes 4 .hg/store/00changelog.i .hg/store/00changelog.i: - : 00 01 de ad || + : 00 00 de ad || $ f --hexdump --bytes 4 .hg/store/data/foo.i .hg/store/data/foo.i: - : 00 01 de ad || + : 00 00 de ad || diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -458,7 +458,7 @@ opts = self.opener.options if b'revlogv2' in opts: -new_header = REVLOGV2 | FLAG_INLINE_DATA +new_header = REVLOGV2 elif b'revlogv1' in opts: new_header = REVLOGV1 | FLAG_INLINE_DATA if b'generaldelta' in opts: To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10657: sidedata: use the "feature" to detect that sidedata are enabled
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is more versatile than relying on the revlogv2 requirements. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10657 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -3366,7 +3366,7 @@ return self.pathto(fp.name[len(self.root) + 1 :]) def register_wanted_sidedata(self, category): -if requirementsmod.REVLOGV2_REQUIREMENT not in self.requirements: +if repository.REPO_FEATURE_SIDE_DATA not in self.features: # Only revlogv2 repos can want sidedata. return self._wanted_sidedata.add(pycompat.bytestr(category)) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10661: changelogv2: allow upgrade from and to this format
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10661 AFFECTED FILES mercurial/upgrade_utils/actions.py CHANGE DETAILS diff --git a/mercurial/upgrade_utils/actions.py b/mercurial/upgrade_utils/actions.py --- a/mercurial/upgrade_utils/actions.py +++ b/mercurial/upgrade_utils/actions.py @@ -31,6 +31,7 @@ requirements.GENERALDELTA_REQUIREMENT, requirements.SPARSEREVLOG_REQUIREMENT, requirements.REVLOGV2_REQUIREMENT, +requirements.CHANGELOGV2_REQUIREMENT, } @@ -949,6 +950,7 @@ requirements.NODEMAP_REQUIREMENT, requirements.SHARESAFE_REQUIREMENT, requirements.REVLOGV2_REQUIREMENT, +requirements.CHANGELOGV2_REQUIREMENT, requirements.REVLOGV1_REQUIREMENT, } for name in compression.compengines: @@ -979,6 +981,7 @@ requirements.NODEMAP_REQUIREMENT, requirements.SHARESAFE_REQUIREMENT, requirements.REVLOGV2_REQUIREMENT, +requirements.CHANGELOGV2_REQUIREMENT, } for name in compression.compengines: engine = compression.compengines[name] @@ -1009,6 +1012,7 @@ requirements.SHARESAFE_REQUIREMENT, requirements.REVLOGV1_REQUIREMENT, requirements.REVLOGV2_REQUIREMENT, +requirements.CHANGELOGV2_REQUIREMENT, } for name in compression.compengines: engine = compression.compengines[name] To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10656: revlog: compress sidedata when doing "post-pull" sidedata update
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY All path writing sidedata are now using compression (when appropriate). REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10656 AFFECTED FILES mercurial/cext/revlog.c mercurial/pure/parsers.py mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -3380,6 +3380,26 @@ serialized_sidedata = sidedatautil.serialize_sidedata( new_sidedata ) + +sidedata_compression_mode = COMP_MODE_INLINE +if serialized_sidedata and self.hassidedata: +sidedata_compression_mode = COMP_MODE_PLAIN +h, comp_sidedata = self.compress(serialized_sidedata) +if ( +h != b'u' +and comp_sidedata[0] != b'\0' +and len(comp_sidedata) < len(serialized_sidedata) +): +assert not h +if ( +comp_sidedata[0] +== self._docket.default_compression_header +): +sidedata_compression_mode = COMP_MODE_DEFAULT +serialized_sidedata = comp_sidedata +else: +sidedata_compression_mode = COMP_MODE_INLINE +serialized_sidedata = comp_sidedata if entry[8] != 0 or entry[9] != 0: # rewriting entries that already have sidedata is not # supported yet, because it introduces garbage data in the @@ -3394,6 +3414,7 @@ current_offset, len(serialized_sidedata), new_offset_flags, +sidedata_compression_mode, ) # the sidedata computation might have move the file cursors around diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -297,7 +297,12 @@ index_format = revlog_constants.INDEX_ENTRY_V2 def replace_sidedata_info( -self, rev, sidedata_offset, sidedata_length, offset_flags +self, +rev, +sidedata_offset, +sidedata_length, +offset_flags, +compression_mode, ): """ Replace an existing index entry's sidedata offset and length with new @@ -316,6 +321,7 @@ entry[0] = offset_flags entry[8] = sidedata_offset entry[9] = sidedata_length +entry[11] = compression_mode entry = tuple(entry) new = self._pack_entry(entry) self._extra[rev - self._lgt] = new diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -533,12 +533,13 @@ { uint64_t offset_flags, sidedata_offset; int rev; + char comp_mode; Py_ssize_t sidedata_comp_len; char *data; #if LONG_MAX == 0x7fffL - const char *const sidedata_format = PY23("nKiK", "nKiK"); + const char *const sidedata_format = PY23("nKiKB", "nKiKB"); #else - const char *const sidedata_format = PY23("nkik", "nkik"); + const char *const sidedata_format = PY23("nkikB", "nkikB"); #endif if (self->entry_size == v1_entry_size || self->inlined) { @@ -553,7 +554,7 @@ } if (!PyArg_ParseTuple(args, sidedata_format, , _offset, - _comp_len, _flags)) + _comp_len, _flags, _mode)) return NULL; if (rev < 0 || rev >= index_length(self)) { @@ -573,6 +574,7 @@ putbe64(offset_flags, data); putbe64(sidedata_offset, data + 64); putbe32(sidedata_comp_len, data + 72); + data[76] = (data[76] & ~(3 << 2)) | ((comp_mode & 3) << 2); Py_RETURN_NONE; } To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10659: revlogv2: drop the code related to inlined revlogv2
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Tevlogv2 will not use inlined revlog. As a result we can drop the associated code. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10659 AFFECTED FILES mercurial/pure/parsers.py CHANGE DETAILS diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -289,11 +289,11 @@ if not inline: cls = IndexObject2 if revlogv2 else IndexObject return cls(data), None -cls = InlinedIndexObject2 if revlogv2 else InlinedIndexObject +cls = InlinedIndexObject return cls(data, inline), (0, data) -class Index2Mixin(object): +class IndexObject2(IndexObject): index_format = revlog_constants.INDEX_ENTRY_V2 def replace_sidedata_info( @@ -353,36 +353,6 @@ raise error.ProgrammingError(msg) -class IndexObject2(Index2Mixin, IndexObject): -pass - - -class InlinedIndexObject2(Index2Mixin, InlinedIndexObject): -def _inline_scan(self, lgt): -sidedata_length_pos = 72 -off = 0 -if lgt is not None: -self._offsets = [0] * lgt -count = 0 -while off <= len(self._data) - self.entry_size: -start = off + self.big_int_size -(data_size,) = struct.unpack( -b'>i', -self._data[start : start + self.int_size], -) -start = off + sidedata_length_pos -(side_data_size,) = struct.unpack( -b'>i', self._data[start : start + self.int_size] -) -if lgt is not None: -self._offsets[count] = off -count += 1 -off += self.entry_size + data_size + side_data_size -if off != len(self._data): -raise ValueError(b"corrupted data") -return count - - def parse_index_devel_nodemap(data, inline): """like parse_index2, but alway return a PersistentNodeMapIndexObject""" return PersistentNodeMapIndexObject(data), None To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10653: revlog: introduce a compression mode for sidedata in the revlog index
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We will use this for compression for the sidedata payload. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10653 AFFECTED FILES mercurial/bundlerepo.py mercurial/cext/revlog.c mercurial/pure/parsers.py mercurial/revlog.py mercurial/revlogutils/revlogv0.py mercurial/unionrepo.py tests/test-parseindex2.py CHANGE DETAILS diff --git a/tests/test-parseindex2.py b/tests/test-parseindex2.py --- a/tests/test-parseindex2.py +++ b/tests/test-parseindex2.py @@ -52,7 +52,12 @@ cache = (0, data) while off <= l: e = struct.unpack(indexformatng, data[off : off + s]) -e = e + (0, 0, constants.COMP_MODE_INLINE) +e = e + ( +0, +0, +constants.COMP_MODE_INLINE, +constants.COMP_MODE_INLINE, +) nodemap[e[7]] = n append(e) n += 1 @@ -62,7 +67,12 @@ else: while off <= l: e = struct.unpack(indexformatng, data[off : off + s]) -e = e + (0, 0, constants.COMP_MODE_INLINE) +e = e + ( +0, +0, +constants.COMP_MODE_INLINE, +constants.COMP_MODE_INLINE, +) nodemap[e[7]] = n append(e) n += 1 @@ -257,6 +267,7 @@ 0, 0, constants.COMP_MODE_INLINE, +constants.COMP_MODE_INLINE, ) index, junk = parsers.parse_index2(data_inlined, True) got = index[-1] @@ -291,6 +302,7 @@ 0, 0, constants.COMP_MODE_INLINE, +constants.COMP_MODE_INLINE, ) index.append(e) diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py --- a/mercurial/unionrepo.py +++ b/mercurial/unionrepo.py @@ -70,6 +70,7 @@ _sdo, _sds, _dcm, +_sdcm, ) = rev flags = _start & 0x @@ -105,6 +106,7 @@ 0, # sidedata offset 0, # sidedata size revlog_constants.COMP_MODE_INLINE, +revlog_constants.COMP_MODE_INLINE, ) self.index.append(e) self.bundlerevs.add(n) diff --git a/mercurial/revlogutils/revlogv0.py b/mercurial/revlogutils/revlogv0.py --- a/mercurial/revlogutils/revlogv0.py +++ b/mercurial/revlogutils/revlogv0.py @@ -55,6 +55,7 @@ 0, 0, COMP_MODE_INLINE, +COMP_MODE_INLINE, ) @property diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -343,6 +343,10 @@ [10] data compression mode: two bits that details the way the data chunk is compressed on disk. (see "COMP_MODE_*" constant for details) + +[11] side-data compression mode: +two bits that details the way the sidedata chunk is compressed on disk. +(see "COMP_MODE_*" constant for details) """ _flagserrorclass = error.RevlogError @@ -2515,7 +2519,9 @@ compression_mode = COMP_MODE_PLAIN deltainfo = deltautil.drop_u_compression(deltainfo) +sidedata_compression_mode = COMP_MODE_INLINE if sidedata and self.hassidedata: +sidedata_compression_mode = COMP_MODE_PLAIN serialized_sidedata = sidedatautil.serialize_sidedata(sidedata) sidedata_offset = offset + deltainfo.deltalen else: @@ -2537,6 +2543,7 @@ sidedata_offset, len(serialized_sidedata), compression_mode, +sidedata_compression_mode, ) self.index.append(e) diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -66,6 +66,7 @@ 0, 0, revlog_constants.COMP_MODE_INLINE, +revlog_constants.COMP_MODE_INLINE, ) @util.propertycache @@ -147,7 +148,12 @@ def _unpack_entry(self, data): r = self.index_format.unpack(data) -r = r + (0, 0, revlog_constants.COMP_MODE_INLINE) +r = r + ( +0, +0, +revlog_constants.COMP_MODE_INLINE, +revlog_constants.COMP_MODE_INLINE, +) return r def pack_header(self, header): @@ -315,10 +321,19 @@ self._extra[rev - self._lgt] = new def _unpack_entry(self, data): -return self.index_format.unpack(data) +data = self.index_format.unpack(data) +entry = data[:10] +data_comp = data[10] & 3 +sidedata_comp = (data[10] & (3 << 2))
D10655: revlog: compress sidedata in `_writeentry`
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY When appropriate we store the sidedata in a compressed form. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10655 AFFECTED FILES mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -2536,6 +2536,22 @@ sidedata_compression_mode = COMP_MODE_PLAIN serialized_sidedata = sidedatautil.serialize_sidedata(sidedata) sidedata_offset = offset + deltainfo.deltalen +h, comp_sidedata = self.compress(serialized_sidedata) +if ( +h != b'u' +and comp_sidedata[0:1] != b'\0' +and len(comp_sidedata) < len(serialized_sidedata) +): +assert not h +if ( +comp_sidedata[0:1] +== self._docket.default_compression_header +): +sidedata_compression_mode = COMP_MODE_DEFAULT +serialized_sidedata = comp_sidedata +else: +sidedata_compression_mode = COMP_MODE_INLINE +serialized_sidedata = comp_sidedata else: serialized_sidedata = b"" # Don't store the offset if the sidedata is empty, that way To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10654: revlog: apply compression mode while reading sidedata
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Right now, we only store things as PLAIN, but we are ready for some compression now. Future changeset will start using some. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10654 AFFECTED FILES mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -2060,7 +2060,19 @@ if sidedata_size == 0: return {} -segment = self._getsegment(sidedata_offset, sidedata_size) +comp_segment = self._getsegment(sidedata_offset, sidedata_size) +comp = self.index[rev][11] +if comp == COMP_MODE_PLAIN: +segment = comp_segment +elif comp == COMP_MODE_DEFAULT: +segment = self._decompressor(comp_segment) +elif comp == COMP_MODE_INLINE: +segment = self.decompress(comp_segment) +else: +msg = 'unknown compression mode %d' +msg %= comp +raise error.RevlogError(msg) + sidedata = sidedatautil.deserialize_sidedata(segment) return sidedata To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10652: revlog: implement a "default compression" mode
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The revlog docker is now storing a default compression engine. When a chunk use that compression, a dedicated mode is used in the revlog entry and we can directly route it to the right decompressor. We should probably make PLAIN and DEFAULT mode the only available mode for revlogv2, but this is something for later. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10652 AFFECTED FILES mercurial/revlog.py mercurial/revlogutils/constants.py mercurial/revlogutils/docket.py CHANGE DETAILS diff --git a/mercurial/revlogutils/docket.py b/mercurial/revlogutils/docket.py --- a/mercurial/revlogutils/docket.py +++ b/mercurial/revlogutils/docket.py @@ -21,6 +21,7 @@ from .. import ( error, +util, ) from . import ( @@ -36,7 +37,8 @@ # * 8 bytes: pending size of index-data # * 8 bytes: size of data # * 8 bytes: pending size of data -S_HEADER = struct.Struct(constants.INDEX_HEADER.format + '') +# * 1 bytes: default compression header +S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'c') class RevlogDocket(object): @@ -51,6 +53,7 @@ pending_index_end=0, data_end=0, pending_data_end=0, +default_compression_header=None, ): self._version_header = version_header self._read_only = bool(use_pending) @@ -71,6 +74,7 @@ else: self._index_end = self._initial_index_end self._data_end = self._initial_data_end +self.default_compression_header = default_compression_header def index_filepath(self): """file path to the current index file associated to this docket""" @@ -134,6 +138,7 @@ self._index_end, official_data_end, self._data_end, +self.default_compression_header, ) return S_HEADER.pack(*data) @@ -142,7 +147,12 @@ """given a revlog version a new docket object for the given revlog""" if (version_header & 0x) != constants.REVLOGV2: return None -docket = RevlogDocket(revlog, version_header=version_header) +comp = util.compengines[revlog._compengine].revlogheader() +docket = RevlogDocket( +revlog, +version_header=version_header, +default_compression_header=comp, +) docket._dirty = True return docket @@ -155,6 +165,7 @@ pending_index_size = header[2] data_size = header[3] pending_data_size = header[4] +default_compression_header = header[5] docket = RevlogDocket( revlog, use_pending=use_pending, @@ -163,5 +174,6 @@ pending_index_end=pending_index_size, data_end=data_size, pending_data_end=pending_data_size, +default_compression_header=default_compression_header, ) return docket diff --git a/mercurial/revlogutils/constants.py b/mercurial/revlogutils/constants.py --- a/mercurial/revlogutils/constants.py +++ b/mercurial/revlogutils/constants.py @@ -117,6 +117,7 @@ ## chunk compression mode constants: # chunk use a compression stored "inline" at the start of the chunk itself. +COMP_MODE_DEFAULT = 1 COMP_MODE_INLINE = 2 COMP_MODE_PLAIN = 0 diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -35,6 +35,7 @@ from .pycompat import getattr from .revlogutils.constants import ( ALL_KINDS, +COMP_MODE_DEFAULT, COMP_MODE_INLINE, COMP_MODE_PLAIN, FEATURES_BY_VERSION, @@ -706,6 +707,15 @@ engine = util.compengines[self._compengine] return engine.revlogcompressor(self._compengineopts) +@util.propertycache +def _decompressor(self): +"""the default decompressor""" +if self._docket is None: +return None +t = self._docket.default_compression_header +c = self._get_decompressor(t) +return c.decompress + def _indexfp(self): """file object for the revlog's index file""" return self.opener(self._indexfile, mode=b"r") @@ -1774,6 +1784,8 @@ data = self._getsegmentforrevs(rev, rev, df=df)[1] if compression_mode == COMP_MODE_PLAIN: return data +elif compression_mode == COMP_MODE_DEFAULT: +return self._decompressor(data) elif compression_mode == COMP_MODE_INLINE: return self.decompress(data) else: @@ -1827,6 +1839,8 @@ return [self._chunk(rev, df=df) for rev in revschunk] decomp = self.decompress +# self._decompressor might be None, but will not be used in that case +def_decomp = self._decompressor for rev in revschunk: chunkstart = start(rev) if inline: @@ -1838,6 +1852,8
D10651: revlog: add a `_get_decompressor` method
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This logic is non-trivial and we will need to reuse it. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10651 AFFECTED FILES mercurial/configitems.py mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -687,6 +687,20 @@ # revlog.target instead of using `self.radix` return self.radix +def _get_decompressor(self, t): +try: +compressor = self._decompressors[t] +except KeyError: +try: +engine = util.compengines.forrevlogheader(t) +compressor = engine.revlogcompressor(self._compengineopts) +self._decompressors[t] = compressor +except KeyError: +raise error.RevlogError( +_(b'unknown compression type %s') % binascii.hexlify(t) +) +return compressor + @util.propertycache def _compressor(self): engine = util.compengines[self._compengine] @@ -2373,17 +2387,7 @@ elif t == b'u': return util.buffer(data, 1) -try: -compressor = self._decompressors[t] -except KeyError: -try: -engine = util.compengines.forrevlogheader(t) -compressor = engine.revlogcompressor(self._compengineopts) -self._decompressors[t] = compressor -except KeyError: -raise error.RevlogError( -_(b'unknown compression type %s') % binascii.hexlify(t) -) +compressor = self._get_decompressor(t) return compressor.decompress(data) diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -1158,7 +1158,8 @@ # * sidedata compression # * introduce a proper solution to reduce the number of filelog related files. # * Improvement to consider -# - track compression mode in the index entris instead of the chunks +# - avoid compression header in chunk using the default compression? +# - forbid "inline" compression mode entirely? # - split the data offset and flag field (the 2 bytes save are mostly trouble) # - keep track of uncompressed -chunk- size (to preallocate memory better) # - keep track of chain base or size (probably not that useful anymore) To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10646: revlog: add a "data compression mode" entry in the index tuple
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY That will make it possible to keep track of compression information in the revlog index, opening the way to more efficient revision restoration (in native code, but the python usage is already defeating performance work). We start with adding a new entry to the index tuple, using a value matching the current behavior. We will introduce storage and other value in later changesets. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10646 AFFECTED FILES mercurial/bundlerepo.py mercurial/cext/parsers.c mercurial/cext/revlog.c mercurial/policy.py mercurial/pure/parsers.py mercurial/revlog.py mercurial/revlogutils/constants.py mercurial/revlogutils/revlogv0.py mercurial/unionrepo.py tests/test-parseindex2.py CHANGE DETAILS diff --git a/tests/test-parseindex2.py b/tests/test-parseindex2.py --- a/tests/test-parseindex2.py +++ b/tests/test-parseindex2.py @@ -21,6 +21,9 @@ policy, pycompat, ) +from mercurial.revlogutils import ( +constants, +) parsers = policy.importmod('parsers') @@ -49,7 +52,7 @@ cache = (0, data) while off <= l: e = struct.unpack(indexformatng, data[off : off + s]) -e = e + (0, 0) +e = e + (0, 0, constants.COMP_MODE_INLINE) nodemap[e[7]] = n append(e) n += 1 @@ -59,7 +62,7 @@ else: while off <= l: e = struct.unpack(indexformatng, data[off : off + s]) -e = e + (0, 0) +e = e + (0, 0, constants.COMP_MODE_INLINE) nodemap[e[7]] = n append(e) n += 1 @@ -242,7 +245,19 @@ break def testminusone(self): -want = (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid, 0, 0) +want = ( +0, +0, +0, +-1, +-1, +-1, +-1, +sha1nodeconstants.nullid, +0, +0, +constants.COMP_MODE_INLINE, +) index, junk = parsers.parse_index2(data_inlined, True) got = index[-1] self.assertEqual(want, got) # inline data @@ -264,7 +279,20 @@ # node won't matter for this test, let's just make sure # they don't collide. Other data don't matter either. node = hexrev(p1) + hexrev(p2) + b'.' * 12 -index.append((0, 0, 12, 1, 34, p1, p2, node, 0, 0)) +e = ( +0, +0, +12, +1, +34, +p1, +p2, +node, +0, +0, +constants.COMP_MODE_INLINE, +) +index.append(e) appendrev(4) appendrev(5) diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py --- a/mercurial/unionrepo.py +++ b/mercurial/unionrepo.py @@ -31,6 +31,10 @@ vfs as vfsmod, ) +from .revlogutils import ( +constants as revlog_constants, +) + class unionrevlog(revlog.revlog): def __init__(self, opener, radix, revlog2, linkmapper): @@ -65,6 +69,7 @@ node, _sdo, _sds, +_dcm, ) = rev flags = _start & 0x @@ -99,6 +104,7 @@ node, 0, # sidedata offset 0, # sidedata size +revlog_constants.COMP_MODE_INLINE, ) self.index.append(e) self.bundlerevs.add(n) diff --git a/mercurial/revlogutils/revlogv0.py b/mercurial/revlogutils/revlogv0.py --- a/mercurial/revlogutils/revlogv0.py +++ b/mercurial/revlogutils/revlogv0.py @@ -9,6 +9,7 @@ from ..node import sha1nodeconstants from .constants import ( +COMP_MODE_INLINE, INDEX_ENTRY_V0, ) from ..i18n import _ @@ -42,7 +43,19 @@ class revlogoldindex(list): entry_size = INDEX_ENTRY_V0.size -null_item = (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid, 0, 0) +null_item = ( +0, +0, +0, +-1, +-1, +-1, +-1, +sha1nodeconstants.nullid, +0, +0, +COMP_MODE_INLINE, +) @property def nodemap(self): @@ -138,6 +151,7 @@ e[6], 0, # no side data support 0, # no side data support +COMP_MODE_INLINE, ) index.append(e2) nodemap[e[6]] = n diff --git a/mercurial/revlogutils/constants.py b/mercurial/revlogutils/constants.py --- a/mercurial/revlogutils/constants.py +++ b/mercurial/revlogutils/constants.py @@ -114,6 +114,10 @@ # bitmark for flags that could cause rawdata content change REVIDX_RAWTEXT_CHANGING_FLAGS =
D10650: revlog: introduce a plain compression mode
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY That mode is simple it means the chunk contains uncompressed data and can be used directly. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10650 AFFECTED FILES mercurial/revlog.py mercurial/revlogutils/constants.py mercurial/revlogutils/deltas.py CHANGE DETAILS diff --git a/mercurial/revlogutils/deltas.py b/mercurial/revlogutils/deltas.py --- a/mercurial/revlogutils/deltas.py +++ b/mercurial/revlogutils/deltas.py @@ -553,6 +553,24 @@ snapshotdepth = attr.ib() +def drop_u_compression(delta): +"""turn into a "u" (no-compression) into no-compression without header + +This is useful for revlog format that has better compression method. +""" +assert delta.data[0] == b'u', delta.data[0] +return _deltainfo( +delta.distance, +delta.deltalen - 1, +(b'', delta.data[1]), +delta.base, +delta.chainbase, +delta.chainlen, +delta.compresseddeltalen, +delta.snapshotdepth, +) + + def isgooddeltainfo(revlog, deltainfo, revinfo): """Returns True if the given delta is good. Good means that it is within the disk span, disk size, and chain length bounds that we know to be diff --git a/mercurial/revlogutils/constants.py b/mercurial/revlogutils/constants.py --- a/mercurial/revlogutils/constants.py +++ b/mercurial/revlogutils/constants.py @@ -118,6 +118,7 @@ ## chunk compression mode constants: # chunk use a compression stored "inline" at the start of the chunk itself. COMP_MODE_INLINE = 2 +COMP_MODE_PLAIN = 0 SUPPORTED_FLAGS = { REVLOGV0: REVLOGV0_FLAGS, diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -36,6 +36,7 @@ from .revlogutils.constants import ( ALL_KINDS, COMP_MODE_INLINE, +COMP_MODE_PLAIN, FEATURES_BY_VERSION, FLAG_GENERALDELTA, FLAG_INLINE_DATA, @@ -1755,7 +1756,16 @@ Returns a str holding uncompressed data for the requested revision. """ -return self.decompress(self._getsegmentforrevs(rev, rev, df=df)[1]) +compression_mode = self.index[rev][10] +data = self._getsegmentforrevs(rev, rev, df=df)[1] +if compression_mode == COMP_MODE_PLAIN: +return data +elif compression_mode == COMP_MODE_INLINE: +return self.decompress(data) +else: +msg = 'unknown compression mode %d' +msg %= compression_mode +raise error.RevlogError(msg) def _chunks(self, revs, df=None, targetsize=None): """Obtain decompressed chunks for the specified revisions. @@ -1808,8 +1818,16 @@ if inline: chunkstart += (rev + 1) * iosize chunklength = length(rev) +comp_mode = self.index[rev][10] c = buffer(data, chunkstart - offset, chunklength) -ladd(decomp(c)) +if comp_mode == COMP_MODE_PLAIN: +ladd(c) +elif comp_mode == COMP_MODE_INLINE: +ladd(decomp(c)) +else: +msg = 'unknown compression mode %d' +msg %= comp_mode +raise error.RevlogError(msg) return l @@ -2459,6 +2477,20 @@ deltainfo = deltacomputer.finddeltainfo(revinfo, fh) +compression_mode = COMP_MODE_INLINE +if self._docket is not None: +h, d = deltainfo.data +if not h and not d: +# not data to store at all... declare them uncompressed +compression_mode = COMP_MODE_PLAIN +elif not h and d[0:1] == b'\0': +compression_mode = COMP_MODE_PLAIN +elif h == b'u': +# we have a more efficient way to declare uncompressed +h = b'' +compression_mode = COMP_MODE_PLAIN +deltainfo = deltautil.drop_u_compression(deltainfo) + if sidedata and self.hassidedata: serialized_sidedata = sidedatautil.serialize_sidedata(sidedata) sidedata_offset = offset + deltainfo.deltalen @@ -2480,7 +2512,7 @@ node, sidedata_offset, len(serialized_sidedata), -COMP_MODE_INLINE, +compression_mode, ) self.index.append(e) To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10649: revlog: use an intermediate variable for `data` in `_chunk`
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This will help us to dispatch this to the right decompressor. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10649 AFFECTED FILES mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -1808,7 +1808,8 @@ if inline: chunkstart += (rev + 1) * iosize chunklength = length(rev) -ladd(decomp(buffer(data, chunkstart - offset, chunklength))) +c = buffer(data, chunkstart - offset, chunklength) +ladd(decomp(c)) return l To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10648: revlogv2: preserve the compression mode on disk
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The value is still the same and still not treated, but now it exists one disk. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10648 AFFECTED FILES mercurial/cext/revlog.c mercurial/pure/parsers.py mercurial/revlogutils/constants.py CHANGE DETAILS diff --git a/mercurial/revlogutils/constants.py b/mercurial/revlogutils/constants.py --- a/mercurial/revlogutils/constants.py +++ b/mercurial/revlogutils/constants.py @@ -85,9 +85,10 @@ # 32 bytes: nodeid # 8 bytes: sidedata offset # 4 bytes: sidedata compressed length -# 20 bytes: Padding to align to 96 bytes (see RevlogV2Plan wiki page) -INDEX_ENTRY_V2 = struct.Struct(b">Qii20s12xQi20x") -assert INDEX_ENTRY_V2.size == 32 * 3 +# 1 bytes: compression mode (2 lower bit are data_compression_mode) +# 19 bytes: Padding to align to 96 bytes (see RevlogV2Plan wiki page) +INDEX_ENTRY_V2 = struct.Struct(b">Qii20s12xQiB19x") +assert INDEX_ENTRY_V2.size == 32 * 3, INDEX_ENTRY_V2.size # revlog index flags diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -315,12 +315,10 @@ self._extra[rev - self._lgt] = new def _unpack_entry(self, data): -return self.index_format.unpack(data) + ( -revlog_constants.COMP_MODE_INLINE, -) +return self.index_format.unpack(data) def _pack_entry(self, entry): -return self.index_format.pack(*entry[:10]) +return self.index_format.pack(*entry[:11]) def entry_binary(self, rev): """return the raw binary string representing a revision""" diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -338,12 +338,13 @@ if (self->format_version == format_v1) { sidedata_offset = 0; sidedata_comp_len = 0; + data_comp_mode = comp_mode_inline; } else { sidedata_offset = getbe64(data + 64); sidedata_comp_len = getbe32(data + 72); + data_comp_mode = data[76]; } - data_comp_mode = comp_mode_inline; return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2, c_node_id, self->nodelen, sidedata_offset, sidedata_comp_len, @@ -466,7 +467,8 @@ PyErr_SetString(PyExc_TypeError, "invalid node"); return NULL; } - if (data_comp_mode != comp_mode_inline) { + if (self->format_version == format_v1 && + data_comp_mode != comp_mode_inline) { PyErr_Format(PyExc_ValueError, "invalid data compression mode: %i", data_comp_mode); @@ -499,8 +501,9 @@ if (self->format_version == format_v2) { putbe64(sidedata_offset, data + 64); putbe32(sidedata_comp_len, data + 72); + data[76] = (char)data_comp_mode; /* Padding for 96 bytes alignment */ - memset(data + 76, 0, self->entry_size - 76); + memset(data + 77, 0, self->entry_size - 77); } if (self->ntinitialized) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10647: revlog: use `format_version` to dispatch different version in index_get
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is semantically more correct. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10647 AFFECTED FILES mercurial/cext/revlog.c CHANGE DETAILS diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -335,7 +335,7 @@ parent_2 = getbe32(data + 28); c_node_id = data + 32; - if (self->entry_size == v1_entry_size) { + if (self->format_version == format_v1) { sidedata_offset = 0; sidedata_comp_len = 0; } else { To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10643: revlog: improve documentation of the entry tuple
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The code in revlog, and outside revlog directly use the index's entry tuple, with direct integer indexing. This is a voluntary trade off to obtains better performance from the Python code at the expense of the developers sanity. Let's at least have a clear and central documentation about what this tuple is about. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10643 AFFECTED FILES mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -284,6 +284,58 @@ file handle, a filename, and an expected position. It should check whether the current position in the file handle is valid, and log/warn/fail (by raising). + + +Internal details + + +A large part of the revlog logic deal with revision "index entry" a tuple +object that constains the same "items" whatever the revlog version. +Different version will have different way to store these items (sometime +not having them at all), but the tuple will always be the same. New fields +are usually added at the end to avoid breaking existing, other, code +relying on the existing order. The field are defined as follow: + +[0] offset: +The byte index of the start of revision data chunk. +That value is shifted up by 16 bits. use "offsett = field >> 16" to +retrieve it. + +flags: +A flag fields that carry special information or change the behavior +of the revision. (see `REVIDX_*` constants for details) +The flag field only occupy the first 16 bits of this field, +use "flags = field && 0x" to retrive the value. + +[1] compressed length: +The size, in bytes, of the chunk on disk + +[2] uncompressed length: +The size, in bytes, of the full revision once reconstructed. + +[3] base rev: +Either the base of the revision delta chain (without general +delta). Or the base of the delte (stored in the data chunk) +with general delta. + +[4] link rev: +Changelog revision number of the changeset introducing this +revision. + +[5] parent 1 rev: +Revision number of the first parent + +[6] parent 2 rev: +Revision number of the second parent + +[7] node id: +The node id of the current revision + +[8] sidedata offset: +The byte index of the start of the revision side-data chunk. + +[9] sidedata chunk length: +The size, in bytes, of the revision side-data chunk. """ _flagserrorclass = error.RevlogError To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10642: revlog: simplify entry update logic in `rewrite_sidedata`
marmoute created this revision. Herald added a reviewer: indygreg. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We don't need to rebuild the full entry. So lets just gather the data we need to pass to `replace_sidedata_info`. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10642 AFFECTED FILES mercurial/revlog.py CHANGE DETAILS diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -3240,13 +3240,16 @@ # Apply (potential) flags to add and to remove after running # the sidedata helpers new_offset_flags = entry[0] | flags[0] & ~flags[1] -entry = (new_offset_flags,) + entry[1:8] -entry += (current_offset, len(serialized_sidedata)) +entry_update = ( +current_offset, +len(serialized_sidedata), +new_offset_flags, +) # the sidedata computation might have move the file cursors around dfh.seek(current_offset, os.SEEK_SET) dfh.write(serialized_sidedata) -new_entries.append(entry) +new_entries.append(entry_update) current_offset += len(serialized_sidedata) if self._docket is not None: self._docket.data_end = dfh.tell() @@ -3255,7 +3258,7 @@ ifh.seek(startrev * self.index.entry_size) for i, e in enumerate(new_entries): rev = startrev + i -self.index.replace_sidedata_info(rev, e[8], e[9], e[0]) +self.index.replace_sidedata_info(rev, *e) packed = self.index.entry_binary(rev) if rev == 0 and self._docket is None: header = self._format_flags | self._format_version To: marmoute, indygreg, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10645: revlog: fix the `null_item` attribute for V0
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is not a proper index tuple. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10645 AFFECTED FILES mercurial/revlogutils/revlogv0.py CHANGE DETAILS diff --git a/mercurial/revlogutils/revlogv0.py b/mercurial/revlogutils/revlogv0.py --- a/mercurial/revlogutils/revlogv0.py +++ b/mercurial/revlogutils/revlogv0.py @@ -42,7 +42,7 @@ class revlogoldindex(list): entry_size = INDEX_ENTRY_V0.size -null_item = (0, 0, 0, -1, -1, -1, -1, node.nullid) +null_item = (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid, 0, 0) @property def nodemap(self): To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10644: revlog: create a create `null_item` attribute for V0
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This value is currently wrong, but at least it is now -obviously- wrong. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10644 AFFECTED FILES mercurial/revlogutils/revlogv0.py CHANGE DETAILS diff --git a/mercurial/revlogutils/revlogv0.py b/mercurial/revlogutils/revlogv0.py --- a/mercurial/revlogutils/revlogv0.py +++ b/mercurial/revlogutils/revlogv0.py @@ -42,6 +42,7 @@ class revlogoldindex(list): entry_size = INDEX_ENTRY_V0.size +null_item = (0, 0, 0, -1, -1, -1, -1, node.nullid) @property def nodemap(self): @@ -89,7 +90,7 @@ def __getitem__(self, i): if i == -1: -return (0, 0, 0, -1, -1, -1, -1, node.nullid) +return self.null_item return list.__getitem__(self, i) def pack_header(self, header): To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10641: revlog: simplify the replace_sidedata_info code
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We already know how to serialize and de-serialize and enty. So lets just do that and modify the entry tuple directly. This avoid having to duplicated binary operation in complicated code. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10641 AFFECTED FILES mercurial/pure/parsers.py CHANGE DETAILS diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -290,17 +290,17 @@ if rev < 0: raise KeyError self._check_index(rev) -sidedata_format = b">Qi" -packed_size = struct.calcsize(sidedata_format) -if rev >= self._lgt: -packed = _pack(sidedata_format, sidedata_offset, sidedata_length) -old = self._extra[rev - self._lgt] -offset_flags = struct.pack(b">Q", offset_flags) -new = offset_flags + old[8:64] + packed + old[64 + packed_size :] -self._extra[rev - self._lgt] = new -else: +if rev < self._lgt: msg = b"cannot rewrite entries outside of this transaction" raise KeyError(msg) +else: +entry = list(self[rev]) +entry[0] = offset_flags +entry[8] = sidedata_offset +entry[9] = sidedata_length +entry = tuple(entry) +new = self._pack_entry(entry) +self._extra[rev - self._lgt] = new def _unpack_entry(self, data): return self.index_format.unpack(data) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10640: revlog: use `rev` instead of `i` in replace_sidedata_info
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is clearer. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10640 AFFECTED FILES mercurial/pure/parsers.py CHANGE DETAILS diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -279,25 +279,25 @@ index_format = revlog_constants.INDEX_ENTRY_V2 def replace_sidedata_info( -self, i, sidedata_offset, sidedata_length, offset_flags +self, rev, sidedata_offset, sidedata_length, offset_flags ): """ Replace an existing index entry's sidedata offset and length with new ones. This cannot be used outside of the context of sidedata rewriting, -inside the transaction that creates the revision `i`. +inside the transaction that creates the revision `rev`. """ -if i < 0: +if rev < 0: raise KeyError -self._check_index(i) +self._check_index(rev) sidedata_format = b">Qi" packed_size = struct.calcsize(sidedata_format) -if i >= self._lgt: +if rev >= self._lgt: packed = _pack(sidedata_format, sidedata_offset, sidedata_length) -old = self._extra[i - self._lgt] +old = self._extra[rev - self._lgt] offset_flags = struct.pack(b">Q", offset_flags) new = offset_flags + old[8:64] + packed + old[64 + packed_size :] -self._extra[i - self._lgt] = new +self._extra[rev - self._lgt] = new else: msg = b"cannot rewrite entries outside of this transaction" raise KeyError(msg) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10639: rust-status: fix ignore and include not composing (issue6514)
Alphare created this revision. Alphare added a comment. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. Pending CI refresh REVISION SUMMARY While the fix is pretty simple, the overall dispatch logic has become kind of ugly. Thankfully we're currently upstreaming a better algorithm, this code is temporary anyway. REPOSITORY rHG Mercurial BRANCH stable REVISION DETAIL https://phab.mercurial-scm.org/D10639 AFFECTED FILES rust/hg-core/src/dirstate/status.rs tests/test-status.t CHANGE DETAILS diff --git a/tests/test-status.t b/tests/test-status.t --- a/tests/test-status.t +++ b/tests/test-status.t @@ -708,4 +708,3 @@ I A.hs I B.hs I ignored-folder/ctest.hs - I ignored-folder/other.txt (known-bad-output rust !) diff --git a/rust/hg-core/src/dirstate/status.rs b/rust/hg-core/src/dirstate/status.rs --- a/rust/hg-core/src/dirstate/status.rs +++ b/rust/hg-core/src/dirstate/status.rs @@ -557,9 +557,11 @@ .unwrap(); } } else if self.is_ignored() && self.options.list_ignored { -files_sender -.send((filename.to_owned(), Dispatch::Ignored)) -.unwrap(); +if self.matcher.matches() { +files_sender +.send((filename.to_owned(), Dispatch::Ignored)) +.unwrap(); +} } } else if let Some(entry) = entry_option { // Used to be a file or a folder, now something else. To: Alphare, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10638: rust-status: highlight a bug in Rust-augmented status
Alphare created this revision. Alphare added a comment. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. Pending CI refresh REVISION SUMMARY This was reported in issue6514, confirmed with this test reproduction. This will be fixed with the next changeset. REPOSITORY rHG Mercurial BRANCH stable REVISION DETAIL https://phab.mercurial-scm.org/D10638 AFFECTED FILES tests/test-status.t CHANGE DETAILS diff --git a/tests/test-status.t b/tests/test-status.t --- a/tests/test-status.t +++ b/tests/test-status.t @@ -691,3 +691,21 @@ $ hg add a.py b.rs $ hg st -aI "*.py" A a.py + +Check using include flag while listing ignored composes correctly (issue6514) + + $ cd .. + $ hg init issue6514 + $ cd issue6514 + $ mkdir ignored-folder + $ touch A.hs B.hs C.hs ignored-folder/other.txt ignored-folder/ctest.hs + $ cat >.hgignore < A.hs + > B.hs + > ignored-folder/ + > EOF + $ hg st -i -I 're:.*\.hs$' + I A.hs + I B.hs + I ignored-folder/ctest.hs + I ignored-folder/other.txt (known-bad-output rust !) To: Alphare, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel