mercurial/repoview.py
author Augie Fackler <augie@google.com>
Tue, 11 Feb 2020 00:44:59 -0500
changeset 44477 ad718271a9eb
parent 43766 d4c2221240a6
child 45114 e2d17974a869
permissions -rw-r--r--
git: skeleton of a new extension to _directly_ operate on git repos This is based in part of work I did years ago in hgit, but it's mostly new code since I'm using pygit2 instead of dulwich and the hg storage interfaces have improved. Some cleanup of old hgit code by Pulkit, which I greatly appreciate. test-git-interop.t does not cover a whole lot of cases, but it passes. It includes status, diff, making a new commit, and `hg annotate` working on the git repository. This is _not_ (yet) production quality code: this is an experiment. Known technical debt lurking in this implementation: * Writing bookmarks just totally ignores transactions. * The way progress is threaded down into the gitstore is awful. * Ideally we'd find a way to incrementally reindex DAGs. I'm not sure how to do that efficiently, so we might need a "known only fast-forwards" mode on the DAG indexer for use on `hg commit` and friends. * We don't even _try_ to do anything reasonable for `hg pull` or `hg push`. * Mercurial need an interface for the changelog type. Tests currently require git 2.24 as far as I'm aware: `git status` has some changed output that I didn't try and handle in a compatible way. This patch has produced some interesting cleanups, most recently on the manifest type. I expect continuing down this road will produce other meritorious cleanups throughout our code. Differential Revision: https://phab.mercurial-scm.org/D6734
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     1
# repoview.py - Filtered view of a localrepo object
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     2
#
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     3
# Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     4
#                Logilab SA        <contact@logilab.fr>
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     5
#
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     6
# This software may be used and distributed according to the terms of the
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     7
# GNU General Public License version 2 or any later version.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
     8
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
     9
from __future__ import absolute_import
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    10
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
    11
import copy
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
    12
import weakref
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    13
43449
c45195f9af0a repoview: move changelog.rev() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43448
diff changeset
    14
from .i18n import _
c45195f9af0a repoview: move changelog.rev() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43448
diff changeset
    15
from .node import (
c45195f9af0a repoview: move changelog.rev() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43448
diff changeset
    16
    hex,
c45195f9af0a repoview: move changelog.rev() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43448
diff changeset
    17
    nullrev,
c45195f9af0a repoview: move changelog.rev() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43448
diff changeset
    18
)
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
    19
from .pycompat import (
43090
1f339b503a40 py3: manually import pycompat.delattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
    20
    delattr,
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
    21
    getattr,
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
    22
    setattr,
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
    23
)
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    24
from . import (
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
    25
    error,
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    26
    obsolete,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    27
    phases,
35249
d4ad9d695a9e repoview: include filter name in repr for debugging
Yuya Nishihara <yuya@tcha.org>
parents: 35248
diff changeset
    28
    pycompat,
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    29
    tags as tagsmod,
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
    30
    util,
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
    31
)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
    32
from .utils import repoviewutil
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
    33
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
    34
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    35
def hideablerevs(repo):
28780
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
    36
    """Revision candidates to be hidden
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
    37
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
    38
    This is a standalone function to allow extensions to wrap it.
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    39
28780
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
    40
    Because we use the set of immutable changesets as a fallback subset in
42138
caebe5e7f4bd repoview: move subsettable in a dedicated module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42126
diff changeset
    41
    branchmap (see mercurial.utils.repoviewutils.subsettable), you cannot set
caebe5e7f4bd repoview: move subsettable in a dedicated module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42126
diff changeset
    42
    "public" changesets as "hideable". Doing so would break multiple code
caebe5e7f4bd repoview: move subsettable in a dedicated module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42126
diff changeset
    43
    assertions and lead to crashes."""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    44
    obsoletes = obsolete.getrevs(repo, b'obsolete')
39297
06c976acc581 phases: add an internal phases
Boris Feld <boris.feld@octobus.net>
parents: 38851
diff changeset
    45
    internals = repo._phasecache.getrevset(repo, phases.localhiddenphases)
06c976acc581 phases: add an internal phases
Boris Feld <boris.feld@octobus.net>
parents: 38851
diff changeset
    46
    internals = frozenset(internals)
06c976acc581 phases: add an internal phases
Boris Feld <boris.feld@octobus.net>
parents: 38851
diff changeset
    47
    return obsoletes | internals
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    48
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
    49
32586
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    50
def pinnedrevs(repo):
32585
bceb398e6d72 hidden: drop obsolete comment about cacheability
Martin von Zweigbergk <martinvonz@google.com>
parents: 32480
diff changeset
    51
    """revisions blocking hidden changesets from being filtered
32480
43ae9e6eaaba hidden: drop outdated comment about "dynamic" performance
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32479
diff changeset
    52
    """
32426
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    53
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    54
    cl = repo.changelog
32586
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    55
    pinned = set()
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    56
    pinned.update([par.rev() for par in repo[None].parents()])
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    57
    pinned.update([cl.rev(bm) for bm in repo._bookmarks.values()])
32426
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    58
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    59
    tags = {}
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    60
    tagsmod.readlocaltags(repo.ui, repo, tags, {})
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    61
    if tags:
43559
90de6bcdf226 index: use `index.get_rev` in `repoview.pinnedrevs`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43510
diff changeset
    62
        rev = cl.index.get_rev
90de6bcdf226 index: use `index.get_rev` in `repoview.pinnedrevs`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43510
diff changeset
    63
        pinned.update(rev(t[0]) for t in tags.values())
90de6bcdf226 index: use `index.get_rev` in `repoview.pinnedrevs`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43510
diff changeset
    64
        pinned.discard(None)
32586
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    65
    return pinned
32426
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    66
32477
20c1c2fb8106 hidden: simplify the computation of consistency blocker
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32476
diff changeset
    67
32588
d964959cbf66 hidden: remove unnecessary 'domain' parameter from _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32587
diff changeset
    68
def _revealancestors(pfunc, hidden, revs):
d964959cbf66 hidden: remove unnecessary 'domain' parameter from _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32587
diff changeset
    69
    """reveals contiguous chains of hidden ancestors of 'revs' by removing them
d964959cbf66 hidden: remove unnecessary 'domain' parameter from _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32587
diff changeset
    70
    from 'hidden'
32475
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    71
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    72
    - pfunc(r): a funtion returning parent of 'r',
32587
b9b41d8f4522 hidden: change _domainancestors() to _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32586
diff changeset
    73
    - hidden: the (preliminary) hidden revisions, to be updated
32475
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    74
    - revs: iterable of revnum,
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    75
32591
2af0b9a02bf9 hidden: make _revealancestors() reveal ancestors exclusively
Martin von Zweigbergk <martinvonz@google.com>
parents: 32590
diff changeset
    76
    (Ancestors are revealed exclusively, i.e. the elements in 'revs' are
2af0b9a02bf9 hidden: make _revealancestors() reveal ancestors exclusively
Martin von Zweigbergk <martinvonz@google.com>
parents: 32590
diff changeset
    77
    *not* revealed)
32475
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    78
    """
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    79
    stack = list(revs)
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    80
    while stack:
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    81
        for p in pfunc(stack.pop()):
32588
d964959cbf66 hidden: remove unnecessary 'domain' parameter from _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32587
diff changeset
    82
            if p != nullrev and p in hidden:
32587
b9b41d8f4522 hidden: change _domainancestors() to _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32586
diff changeset
    83
                hidden.remove(p)
32475
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    84
                stack.append(p)
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    85
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
    86
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
    87
def computehidden(repo, visibilityexceptions=None):
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
    88
    """compute the set of hidden revision to filter
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
    89
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
    90
    During most operation hidden should be filtered."""
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
    91
    assert not repo.changelog.filteredrevs
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
    92
32479
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
    93
    hidden = hideablerevs(repo)
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
    94
    if hidden:
32592
c37ca35b8450 hidden: subtract pinned revs from hidden earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 32591
diff changeset
    95
        hidden = set(hidden - pinnedrevs(repo))
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
    96
        if visibilityexceptions:
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
    97
            hidden -= visibilityexceptions
32479
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
    98
        pfunc = repo.changelog.parentrevs
38157
02f992ac26e9 phases: define an official tuple of mutable phases
Boris Feld <boris.feld@octobus.net>
parents: 38156
diff changeset
    99
        mutable = repo._phasecache.getrevset(repo, phases.mutablephases)
32479
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
   100
32593
e4d0b2efb8b5 hidden: remove unnecessary guard condition
Martin von Zweigbergk <martinvonz@google.com>
parents: 32592
diff changeset
   101
        visible = mutable - hidden
e4d0b2efb8b5 hidden: remove unnecessary guard condition
Martin von Zweigbergk <martinvonz@google.com>
parents: 32592
diff changeset
   102
        _revealancestors(pfunc, hidden, visible)
32479
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
   103
    return frozenset(hidden)
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   104
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   105
42126
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   106
def computesecret(repo, visibilityexceptions=None):
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   107
    """compute the set of revision that can never be exposed through hgweb
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   108
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   109
    Changeset in the secret phase (or above) should stay unaccessible."""
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   110
    assert not repo.changelog.filteredrevs
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   111
    secrets = repo._phasecache.getrevset(repo, phases.remotehiddenphases)
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   112
    return frozenset(secrets)
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   113
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   114
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   115
def computeunserved(repo, visibilityexceptions=None):
18102
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   116
    """compute the set of revision that should be filtered when used a server
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   117
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   118
    Secret and hidden changeset should not pretend to be here."""
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   119
    assert not repo.changelog.filteredrevs
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   120
    # fast path in simple case to avoid impact of non optimised code
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   121
    hiddens = filterrevs(repo, b'visible')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   122
    secrets = filterrevs(repo, b'served.hidden')
42125
bc15e37ecc16 repoview: fix conditional around unserved changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 39297
diff changeset
   123
    if secrets:
42126
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   124
        return frozenset(hiddens | secrets)
18273
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   125
    else:
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   126
        return hiddens
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   127
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   128
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   129
def computemutable(repo, visibilityexceptions=None):
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   130
    assert not repo.changelog.filteredrevs
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   131
    # fast check to avoid revset call on huge repo
25149
3f0744eeaeaf cleanup: use __builtins__.any instead of util.any
Augie Fackler <augie@google.com>
parents: 25086
diff changeset
   132
    if any(repo._phasecache.phaseroots[1:]):
18274
254b708fd37d performance: speedup computation of mutable revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18273
diff changeset
   133
        getphase = repo._phasecache.phase
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   134
        maymutable = filterrevs(repo, b'base')
18274
254b708fd37d performance: speedup computation of mutable revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18273
diff changeset
   135
        return frozenset(r for r in maymutable if getphase(repo, r))
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   136
    return frozenset()
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   137
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   138
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   139
def computeimpactable(repo, visibilityexceptions=None):
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   140
    """Everything impactable by mutable revision
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   141
18462
593eb3786165 documentation: update to new filter names
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18445
diff changeset
   142
    The immutable filter still have some chance to get invalidated. This will
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   143
    happen when:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   144
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   145
    - you garbage collect hidden changeset,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   146
    - public phase is moved backward,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   147
    - something is changed in the filtering (this could be fixed)
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   148
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   149
    This filter out any mutable changeset and any public changeset that may be
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   150
    impacted by something happening to a mutable revision.
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   151
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   152
    This is achieved by filtered everything with a revision number egal or
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   153
    higher than the first mutable changeset is filtered."""
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   154
    assert not repo.changelog.filteredrevs
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   155
    cl = repo.changelog
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   156
    firstmutable = len(cl)
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   157
    for roots in repo._phasecache.phaseroots[1:]:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   158
        if roots:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   159
            firstmutable = min(firstmutable, min(cl.rev(r) for r in roots))
18443
64848f7fb764 repoview: protect `base` computation from weird phase root
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18382
diff changeset
   160
    # protect from nullrev root
64848f7fb764 repoview: protect `base` computation from weird phase root
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18382
diff changeset
   161
    firstmutable = max(0, firstmutable)
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38158
diff changeset
   162
    return frozenset(pycompat.xrange(firstmutable, len(cl)))
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   163
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   164
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   165
# function to compute filtered set
20196
59198508b0bd filter: add a comment so that people do not forget to update subsettable
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 20032
diff changeset
   166
#
20549
2025315cfb0c comments: fix minor spelling issues found with spell checker
Mads Kiilerich <madski@unity3d.com>
parents: 20405
diff changeset
   167
# When adding a new filter you MUST update the table at:
42138
caebe5e7f4bd repoview: move subsettable in a dedicated module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42126
diff changeset
   168
#     mercurial.utils.repoviewutil.subsettable
20196
59198508b0bd filter: add a comment so that people do not forget to update subsettable
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 20032
diff changeset
   169
# Otherwise your filter will have to recompute all its branches cache
59198508b0bd filter: add a comment so that people do not forget to update subsettable
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 20032
diff changeset
   170
# from scratch (very slow).
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   171
filtertable = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   172
    b'visible': computehidden,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   173
    b'visible-hidden': computehidden,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   174
    b'served.hidden': computesecret,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   175
    b'served': computeunserved,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   176
    b'immutable': computemutable,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   177
    b'base': computeimpactable,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   178
}
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   179
43766
d4c2221240a6 repoview: add an explicit set of all filter that show the wc parents
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43755
diff changeset
   180
# set of filter level that will include the working copy parent no matter what.
d4c2221240a6 repoview: add an explicit set of all filter that show the wc parents
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43755
diff changeset
   181
filter_has_wc = {b'visible', b'visible-hidden'}
d4c2221240a6 repoview: add an explicit set of all filter that show the wc parents
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43755
diff changeset
   182
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   183
_basefiltername = list(filtertable)
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   184
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   185
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   186
def extrafilter(ui):
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   187
    """initialize extra filter and return its id
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   188
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   189
    If extra filtering is configured, we make sure the associated filtered view
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   190
    are declared and return the associated id.
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   191
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   192
    frevs = ui.config(b'experimental', b'extra-filter-revs')
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   193
    if frevs is None:
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   194
        return None
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   195
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   196
    fid = pycompat.sysbytes(util.DIGESTS[b'sha1'](frevs).hexdigest())[:12]
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   197
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   198
    combine = lambda fname: fname + b'%' + fid
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   199
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   200
    subsettable = repoviewutil.subsettable
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   201
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   202
    if combine(b'base') not in filtertable:
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   203
        for name in _basefiltername:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   204
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   205
            def extrafilteredrevs(repo, *args, **kwargs):
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   206
                baserevs = filtertable[name](repo, *args, **kwargs)
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   207
                extrarevs = frozenset(repo.revs(frevs))
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   208
                return baserevs | extrarevs
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   209
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   210
            filtertable[combine(name)] = extrafilteredrevs
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   211
            if name in subsettable:
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   212
                subsettable[combine(name)] = combine(subsettable[name])
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   213
    return fid
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   214
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   215
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   216
def filterrevs(repo, filtername, visibilityexceptions=None):
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   217
    """returns set of filtered revision for this filter name
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   218
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   219
    visibilityexceptions is a set of revs which must are exceptions for
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   220
    hidden-state and must be visible. They are dynamic and hence we should not
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   221
    cache it's result"""
18101
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
   222
    if filtername not in repo.filteredrevcache:
43753
2276a9a1c037 repoview: add a 'devel.debug.repo-filter' option
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43559
diff changeset
   223
        if repo.ui.configbool(b'devel', b'debug.repo-filters'):
43755
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   224
            msg = b'computing revision filter for "%s"'
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   225
            msg %= filtername
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   226
            if repo.ui.tracebackflag and repo.ui.debugflag:
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   227
                # XXX use ui.write_err
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   228
                util.debugstacktrace(
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   229
                    msg,
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   230
                    f=repo.ui._fout,
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   231
                    otherf=repo.ui._ferr,
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   232
                    prefix=b'debug.filters: ',
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   233
                )
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   234
            else:
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   235
                repo.ui.debug(b'debug.filters: %s\n' % msg)
18101
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
   236
        func = filtertable[filtername]
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   237
        if visibilityexceptions:
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   238
            return func(repo.unfiltered, visibilityexceptions)
18101
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
   239
        repo.filteredrevcache[filtername] = func(repo.unfiltered())
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
   240
    return repo.filteredrevcache[filtername]
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   241
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   242
43441
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   243
def wrapchangelog(unfichangelog, filteredrevs):
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   244
    cl = copy.copy(unfichangelog)
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   245
    cl.filteredrevs = filteredrevs
43442
625e7d1ffd1c repoview: wrap changelog class when filtering
Martin von Zweigbergk <martinvonz@google.com>
parents: 43441
diff changeset
   246
43510
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   247
    class filteredchangelog(filteredchangelogmixin, cl.__class__):
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   248
        pass
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   249
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   250
    cl.__class__ = filteredchangelog
43442
625e7d1ffd1c repoview: wrap changelog class when filtering
Martin von Zweigbergk <martinvonz@google.com>
parents: 43441
diff changeset
   251
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   252
    return cl
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   253
43444
c470e699cd00 repoview: move changelog.__contains__() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43443
diff changeset
   254
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   255
class filteredchangelogmixin(object):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   256
    def tiprev(self):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   257
        """filtered version of revlog.tiprev"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   258
        for i in pycompat.xrange(len(self) - 1, -2, -1):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   259
            if i not in self.filteredrevs:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   260
                return i
43445
c093fb81404f repoview: move changelog.__iter__() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43444
diff changeset
   261
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   262
    def __contains__(self, rev):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   263
        """filtered version of revlog.__contains__"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   264
        return 0 <= rev < len(self) and rev not in self.filteredrevs
43445
c093fb81404f repoview: move changelog.__iter__() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43444
diff changeset
   265
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   266
    def __iter__(self):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   267
        """filtered version of revlog.__iter__"""
43445
c093fb81404f repoview: move changelog.__iter__() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43444
diff changeset
   268
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   269
        def filterediter():
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   270
            for i in pycompat.xrange(len(self)):
43446
5ade47284dda repoview: move changelog.revs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43445
diff changeset
   271
                if i not in self.filteredrevs:
5ade47284dda repoview: move changelog.revs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43445
diff changeset
   272
                    yield i
5ade47284dda repoview: move changelog.revs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43445
diff changeset
   273
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   274
        return filterediter()
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   275
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   276
    def revs(self, start=0, stop=None):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   277
        """filtered version of revlog.revs"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   278
        for i in super(filteredchangelogmixin, self).revs(start, stop):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   279
            if i not in self.filteredrevs:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   280
                yield i
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   281
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   282
    def _checknofilteredinrevs(self, revs):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   283
        """raise the appropriate error if 'revs' contains a filtered revision
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   284
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   285
        This returns a version of 'revs' to be used thereafter by the caller.
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   286
        In particular, if revs is an iterator, it is converted into a set.
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   287
        """
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   288
        safehasattr = util.safehasattr
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   289
        if safehasattr(revs, '__next__'):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   290
            # Note that inspect.isgenerator() is not true for iterators,
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   291
            revs = set(revs)
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   292
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   293
        filteredrevs = self.filteredrevs
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   294
        if safehasattr(revs, 'first'):  # smartset
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   295
            offenders = revs & filteredrevs
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   296
        else:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   297
            offenders = filteredrevs.intersection(revs)
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   298
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   299
        for rev in offenders:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   300
            raise error.FilteredIndexError(rev)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   301
        return revs
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   302
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   303
    def headrevs(self, revs=None):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   304
        if revs is None:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   305
            try:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   306
                return self.index.headrevsfiltered(self.filteredrevs)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   307
            # AttributeError covers non-c-extension environments and
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   308
            # old c extensions without filter handling.
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   309
            except AttributeError:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   310
                return self._headrevs()
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   311
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   312
        revs = self._checknofilteredinrevs(revs)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   313
        return super(filteredchangelogmixin, self).headrevs(revs)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   314
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   315
    def strip(self, *args, **kwargs):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   316
        # XXX make something better than assert
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   317
        # We can't expect proper strip behavior if we are filtered.
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   318
        assert not self.filteredrevs
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   319
        super(filteredchangelogmixin, self).strip(*args, **kwargs)
43448
c31fa28d1843 repoview: move changelog.strip() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43447
diff changeset
   320
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   321
    def rev(self, node):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   322
        """filtered version of revlog.rev"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   323
        r = super(filteredchangelogmixin, self).rev(node)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   324
        if r in self.filteredrevs:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   325
            raise error.FilteredLookupError(
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   326
                hex(node), self.indexfile, _(b'filtered node')
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   327
            )
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   328
        return r
43450
6f3222bbfce0 repoview: move changelog.node() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43449
diff changeset
   329
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   330
    def node(self, rev):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   331
        """filtered version of revlog.node"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   332
        if rev in self.filteredrevs:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   333
            raise error.FilteredIndexError(rev)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   334
        return super(filteredchangelogmixin, self).node(rev)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   335
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   336
    def linkrev(self, rev):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   337
        """filtered version of revlog.linkrev"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   338
        if rev in self.filteredrevs:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   339
            raise error.FilteredIndexError(rev)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   340
        return super(filteredchangelogmixin, self).linkrev(rev)
43451
983cda0e110c repoview: move changelog.linkrev() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43450
diff changeset
   341
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   342
    def parentrevs(self, rev):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   343
        """filtered version of revlog.parentrevs"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   344
        if rev in self.filteredrevs:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   345
            raise error.FilteredIndexError(rev)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   346
        return super(filteredchangelogmixin, self).parentrevs(rev)
43452
e1dae2ef5588 repoview: move changelog.parentrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43451
diff changeset
   347
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   348
    def flags(self, rev):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   349
        """filtered version of revlog.flags"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   350
        if rev in self.filteredrevs:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   351
            raise error.FilteredIndexError(rev)
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   352
        return super(filteredchangelogmixin, self).flags(rev)
43441
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   353
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   354
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   355
class repoview(object):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   356
    """Provide a read/write view of a repo through a filtered changelog
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   357
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   358
    This object is used to access a filtered version of a repository without
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   359
    altering the original repository object itself. We can not alter the
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   360
    original object for two main reasons:
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   361
    - It prevents the use of a repo with multiple filters at the same time. In
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   362
      particular when multiple threads are involved.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   363
    - It makes scope of the filtering harder to control.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   364
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   365
    This object behaves very closely to the original repository. All attribute
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   366
    operations are done on the original repository:
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   367
    - An access to `repoview.someattr` actually returns `repo.someattr`,
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   368
    - A write to `repoview.someattr` actually sets value of `repo.someattr`,
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   369
    - A deletion of `repoview.someattr` actually drops `someattr`
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   370
      from `repo.__dict__`.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   371
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   372
    The only exception is the `changelog` property. It is overridden to return
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   373
    a (surface) copy of `repo.changelog` with some revisions filtered. The
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   374
    `filtername` attribute of the view control the revisions that need to be
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   375
    filtered.  (the fact the changelog is copied is an implementation detail).
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   376
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   377
    Unlike attributes, this object intercepts all method calls. This means that
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   378
    all methods are run on the `repoview` object with the filtered `changelog`
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   379
    property. For this purpose the simple `repoview` class must be mixed with
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   380
    the actual class of the repository. This ensures that the resulting
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   381
    `repoview` object have the very same methods than the repo object. This
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   382
    leads to the property below.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   383
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   384
        repoview.method() --> repo.__class__.method(repoview)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   385
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   386
    The inheritance has to be done dynamically because `repo` can be of any
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
   387
    subclasses of `localrepo`. Eg: `bundlerepo` or `statichttprepo`.
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   388
    """
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   389
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   390
    def __init__(self, repo, filtername, visibilityexceptions=None):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   391
        object.__setattr__(self, '_unfilteredrepo', repo)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   392
        object.__setattr__(self, 'filtername', filtername)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   393
        object.__setattr__(self, '_clcachekey', None)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   394
        object.__setattr__(self, '_clcache', None)
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   395
        # revs which are exceptions and must not be hidden
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   396
        object.__setattr__(self, '_visibilityexceptions', visibilityexceptions)
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   397
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
   398
    # not a propertycache on purpose we shall implement a proper cache later
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   399
    @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   400
    def changelog(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   401
        """return a filtered version of the changeset
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   402
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   403
        this changelog must not be used for writing"""
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   404
        # some cache may be implemented later
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   405
        unfi = self._unfilteredrepo
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   406
        unfichangelog = unfi.changelog
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
   407
        # bypass call to changelog.method
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
   408
        unfiindex = unfichangelog.index
38851
781b2720d2ac index: don't include nullid in len()
Martin von Zweigbergk <martinvonz@google.com>
parents: 38783
diff changeset
   409
        unfilen = len(unfiindex)
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
   410
        unfinode = unfiindex[unfilen - 1][7]
43240
4353942be294 tracing: add a couple of trace points on obsolete and repoview
Augie Fackler <augie@google.com>
parents: 43090
diff changeset
   411
        with util.timedcm('repo filter for %s', self.filtername):
4353942be294 tracing: add a couple of trace points on obsolete and repoview
Augie Fackler <augie@google.com>
parents: 43090
diff changeset
   412
            revs = filterrevs(unfi, self.filtername, self._visibilityexceptions)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   413
        cl = self._clcache
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
   414
        newkey = (unfilen, unfinode, hash(revs), unfichangelog._delayed)
28265
332926212ef8 repoview: discard filtered changelog if index isn't shared with unfiltered
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27917
diff changeset
   415
        # if cl.index is not unfiindex, unfi.changelog would be
332926212ef8 repoview: discard filtered changelog if index isn't shared with unfiltered
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27917
diff changeset
   416
        # recreated, and our clcache refers to garbage object
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   417
        if cl is not None and (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   418
            cl.index is not unfiindex or newkey != self._clcachekey
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   419
        ):
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
   420
            cl = None
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   421
        # could have been made None by the previous if
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   422
        if cl is None:
43454
c8e5b3094a1d repoview: avoid wrapping changelog if there's nothing to filter
Martin von Zweigbergk <martinvonz@google.com>
parents: 43453
diff changeset
   423
            # Only filter if there's something to filter
c8e5b3094a1d repoview: avoid wrapping changelog if there's nothing to filter
Martin von Zweigbergk <martinvonz@google.com>
parents: 43453
diff changeset
   424
            cl = wrapchangelog(unfichangelog, revs) if revs else unfichangelog
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   425
            object.__setattr__(self, '_clcache', cl)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   426
            object.__setattr__(self, '_clcachekey', newkey)
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   427
        return cl
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   428
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   429
    def unfiltered(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   430
        """Return an unfiltered version of a repo"""
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   431
        return self._unfilteredrepo
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   432
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   433
    def filtered(self, name, visibilityexceptions=None):
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   434
        """Return a filtered version of a repository"""
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   435
        if name == self.filtername and not visibilityexceptions:
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   436
            return self
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   437
        return self.unfiltered().filtered(name, visibilityexceptions)
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   438
35249
d4ad9d695a9e repoview: include filter name in repr for debugging
Yuya Nishihara <yuya@tcha.org>
parents: 35248
diff changeset
   439
    def __repr__(self):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   440
        return '<%s:%s %r>' % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   441
            self.__class__.__name__,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   442
            pycompat.sysstr(self.filtername),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   443
            self.unfiltered(),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   444
        )
35249
d4ad9d695a9e repoview: include filter name in repr for debugging
Yuya Nishihara <yuya@tcha.org>
parents: 35248
diff changeset
   445
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   446
    # everything access are forwarded to the proxied repo
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   447
    def __getattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   448
        return getattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   449
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   450
    def __setattr__(self, attr, value):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   451
        return setattr(self._unfilteredrepo, attr, value)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   452
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   453
    def __delattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   454
        return delattr(self._unfilteredrepo, attr)
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   455
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   456
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   457
# Python <3.4 easily leaks types via __mro__. See
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   458
# https://bugs.python.org/issue17950. We cache dynamically created types
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   459
# so they won't be leaked on every invocation of repo.filtered().
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   460
_filteredrepotypes = weakref.WeakKeyDictionary()
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   461
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   462
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   463
def newtype(base):
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   464
    """Create a new type with the repoview mixin and the given base class"""
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   465
    if base not in _filteredrepotypes:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   466
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   467
        class filteredrepo(repoview, base):
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   468
            pass
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   469
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   470
        _filteredrepotypes[base] = filteredrepo
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   471
    return _filteredrepotypes[base]