mercurial/repoview.py
author Augie Fackler <augie@google.com>
Mon, 03 May 2021 15:14:09 -0400
changeset 47060 fde5bb5d1acf
parent 47011 b7e623ac98b6
child 47148 a07d5cb03a85
permissions -rw-r--r--
merge: with stable
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):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45761
diff changeset
    51
    """revisions blocking hidden changesets from being filtered"""
32426
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    52
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    53
    cl = repo.changelog
32586
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    54
    pinned = set()
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    55
    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
    56
    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
    57
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    58
    tags = {}
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    59
    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
    60
    if tags:
43559
90de6bcdf226 index: use `index.get_rev` in `repoview.pinnedrevs`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43510
diff changeset
    61
        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
    62
        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
    63
        pinned.discard(None)
45412
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    64
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    65
    # Avoid cycle: mercurial.filemerge -> mercurial.templater ->
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    66
    # mercurial.templatefuncs -> mercurial.revset -> mercurial.repoview ->
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    67
    # mercurial.mergestate -> mercurial.filemerge
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    68
    from . import mergestate
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    69
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    70
    ms = mergestate.mergestate.read(repo)
45761
341e014fe0fb repoview: only pin obsolete wdir parents while there are unresolved conflicts
Matt Harbison <matt_harbison@yahoo.com>
parents: 45523
diff changeset
    71
    if ms.active() and ms.unresolvedcount():
45523
5ed6efedc457 repoview: don't crash if mergestate points to non-existent node
Martin von Zweigbergk <martinvonz@google.com>
parents: 45412
diff changeset
    72
        for node in (ms.local, ms.other):
5ed6efedc457 repoview: don't crash if mergestate points to non-existent node
Martin von Zweigbergk <martinvonz@google.com>
parents: 45412
diff changeset
    73
            rev = cl.index.get_rev(node)
5ed6efedc457 repoview: don't crash if mergestate points to non-existent node
Martin von Zweigbergk <martinvonz@google.com>
parents: 45412
diff changeset
    74
            if rev is not None:
5ed6efedc457 repoview: don't crash if mergestate points to non-existent node
Martin von Zweigbergk <martinvonz@google.com>
parents: 45412
diff changeset
    75
                pinned.add(rev)
45412
aaeccdb6e654 repoview: pin revisions for `local` and `other` when a merge is active
Matt Harbison <matt_harbison@yahoo.com>
parents: 45115
diff changeset
    76
32586
47e4c6bb39f1 hidden: rename "revealedrevs" to "pinnedrevs" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
    77
    return pinned
32426
06aa645e2372 repoview: move '_getdynamicblock' next to 'hideablerevs'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 31444
diff changeset
    78
32477
20c1c2fb8106 hidden: simplify the computation of consistency blocker
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32476
diff changeset
    79
32588
d964959cbf66 hidden: remove unnecessary 'domain' parameter from _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32587
diff changeset
    80
def _revealancestors(pfunc, hidden, revs):
d964959cbf66 hidden: remove unnecessary 'domain' parameter from _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32587
diff changeset
    81
    """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
    82
    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
    83
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
    - 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
    85
    - 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
    86
    - 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
    87
32591
2af0b9a02bf9 hidden: make _revealancestors() reveal ancestors exclusively
Martin von Zweigbergk <martinvonz@google.com>
parents: 32590
diff changeset
    88
    (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
    89
    *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
    90
    """
1d70ec85ae00 hidden: add a function returning ancestors of revs within a domain
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32427
diff changeset
    91
    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
    92
    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
    93
        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
    94
            if p != nullrev and p in hidden:
32587
b9b41d8f4522 hidden: change _domainancestors() to _revealancestors()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32586
diff changeset
    95
                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
    96
                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
    97
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
    98
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
    99
def computehidden(repo, visibilityexceptions=None):
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   100
    """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
   101
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   102
    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
   103
    assert not repo.changelog.filteredrevs
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
   104
32479
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
   105
    hidden = hideablerevs(repo)
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
   106
    if hidden:
32592
c37ca35b8450 hidden: subtract pinned revs from hidden earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 32591
diff changeset
   107
        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
   108
        if visibilityexceptions:
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   109
            hidden -= visibilityexceptions
32479
4c5bc7cbd989 hidden: unify the static and dynamic blocker logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32478
diff changeset
   110
        pfunc = repo.changelog.parentrevs
38157
02f992ac26e9 phases: define an official tuple of mutable phases
Boris Feld <boris.feld@octobus.net>
parents: 38156
diff changeset
   111
        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
   112
32593
e4d0b2efb8b5 hidden: remove unnecessary guard condition
Martin von Zweigbergk <martinvonz@google.com>
parents: 32592
diff changeset
   113
        visible = mutable - hidden
e4d0b2efb8b5 hidden: remove unnecessary guard condition
Martin von Zweigbergk <martinvonz@google.com>
parents: 32592
diff changeset
   114
        _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
   115
    return frozenset(hidden)
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   116
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   117
42126
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   118
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
   119
    """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
   120
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   121
    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
   122
    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
   123
    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
   124
    return frozenset(secrets)
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   125
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   126
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   127
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
   128
    """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
   129
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   130
    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
   131
    assert not repo.changelog.filteredrevs
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   132
    # 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
   133
    hiddens = filterrevs(repo, b'visible')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   134
    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
   135
    if secrets:
42126
ef0e3cc684b3 repoview: introduce a filter for serving hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42125
diff changeset
   136
        return frozenset(hiddens | secrets)
18273
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   137
    else:
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   138
        return hiddens
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   139
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   140
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   141
def computemutable(repo, visibilityexceptions=None):
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   142
    assert not repo.changelog.filteredrevs
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   143
    # fast check to avoid revset call on huge repo
45114
e2d17974a869 phases: provide a test and accessor for non-public phase roots
Joerg Sonnenberger <joerg@bec.de>
parents: 43766
diff changeset
   144
    if repo._phasecache.hasnonpublicphases(repo):
45115
672ad1f6eeb8 repoview: use the phasecache directly to determine mutable revisions
Joerg Sonnenberger <joerg@bec.de>
parents: 45114
diff changeset
   145
        return frozenset(repo._phasecache.getrevset(repo, phases.mutablephases))
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   146
    return frozenset()
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   147
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   148
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   149
def computeimpactable(repo, visibilityexceptions=None):
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   150
    """Everything impactable by mutable revision
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   151
18462
593eb3786165 documentation: update to new filter names
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18445
diff changeset
   152
    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
   153
    happen when:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   154
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   155
    - you garbage collect hidden changeset,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   156
    - public phase is moved backward,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   157
    - 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
   158
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   159
    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
   160
    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
   161
46195
d6a9e690d620 comments: fix typos
Joerg Sonnenberger <joerg@bec.de>
parents: 45942
diff changeset
   162
    This is achieved by filtered everything with a revision number equal or
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   163
    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
   164
    assert not repo.changelog.filteredrevs
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   165
    cl = repo.changelog
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   166
    firstmutable = len(cl)
45114
e2d17974a869 phases: provide a test and accessor for non-public phase roots
Joerg Sonnenberger <joerg@bec.de>
parents: 43766
diff changeset
   167
    roots = repo._phasecache.nonpublicphaseroots(repo)
e2d17974a869 phases: provide a test and accessor for non-public phase roots
Joerg Sonnenberger <joerg@bec.de>
parents: 43766
diff changeset
   168
    if roots:
e2d17974a869 phases: provide a test and accessor for non-public phase roots
Joerg Sonnenberger <joerg@bec.de>
parents: 43766
diff changeset
   169
        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
   170
    # 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
   171
    firstmutable = max(0, firstmutable)
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38158
diff changeset
   172
    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
   173
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   174
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   175
# 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
   176
#
20549
2025315cfb0c comments: fix minor spelling issues found with spell checker
Mads Kiilerich <madski@unity3d.com>
parents: 20405
diff changeset
   177
# 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
   178
#     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
   179
# 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
   180
# from scratch (very slow).
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   181
filtertable = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   182
    b'visible': computehidden,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   183
    b'visible-hidden': computehidden,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   184
    b'served.hidden': computesecret,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   185
    b'served': computeunserved,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   186
    b'immutable': computemutable,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   187
    b'base': computeimpactable,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   188
}
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   189
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
   190
# 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
   191
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
   192
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   193
_basefiltername = list(filtertable)
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   194
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   195
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   196
def extrafilter(ui):
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   197
    """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
   198
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   199
    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
   200
    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
   201
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   202
    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
   203
    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
   204
        return None
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   205
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   206
    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
   207
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   208
    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
   209
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   210
    subsettable = repoviewutil.subsettable
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   211
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   212
    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
   213
        for name in _basefiltername:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   214
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   215
            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
   216
                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
   217
                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
   218
                return baserevs | extrarevs
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   219
42231
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   220
            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
   221
            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
   222
                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
   223
    return fid
d345627d104b repoview: introduce a `experimental.extra-filter-revs` config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42138
diff changeset
   224
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   225
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   226
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
   227
    """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
   228
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   229
    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
   230
    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
   231
    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
   232
    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
   233
        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
   234
            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
   235
            msg %= filtername
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   236
            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
   237
                # 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
   238
                util.debugstacktrace(
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   239
                    msg,
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   240
                    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
   241
                    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
   242
                    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
   243
                )
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   244
            else:
d2a7f0aab540 repoview: display stack trace along side the debug message
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43753
diff changeset
   245
                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
   246
        func = filtertable[filtername]
35493
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   247
        if visibilityexceptions:
3c9c05a38d78 repoview: add visibilityexception argument to filterrevs() and related fns
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35492
diff changeset
   248
            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
   249
        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
   250
    return repo.filteredrevcache[filtername]
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   251
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   252
43441
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   253
def wrapchangelog(unfichangelog, filteredrevs):
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   254
    cl = copy.copy(unfichangelog)
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   255
    cl.filteredrevs = filteredrevs
43442
625e7d1ffd1c repoview: wrap changelog class when filtering
Martin von Zweigbergk <martinvonz@google.com>
parents: 43441
diff changeset
   256
43510
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   257
    class filteredchangelog(filteredchangelogmixin, cl.__class__):
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   258
        pass
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   259
85628a595c37 repoview: use class literal for creating filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   260
    cl.__class__ = filteredchangelog
43442
625e7d1ffd1c repoview: wrap changelog class when filtering
Martin von Zweigbergk <martinvonz@google.com>
parents: 43441
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
    return cl
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   263
43444
c470e699cd00 repoview: move changelog.__contains__() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43443
diff changeset
   264
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   265
class filteredchangelogmixin(object):
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   266
    def tiprev(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.tiprev"""
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   268
        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
   269
            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
   270
                return i
43445
c093fb81404f repoview: move changelog.__iter__() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43444
diff changeset
   271
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   272
    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
   273
        """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
   274
        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
   275
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   276
    def __iter__(self):
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.__iter__"""
43445
c093fb81404f repoview: move changelog.__iter__() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43444
diff changeset
   278
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   279
        def filterediter():
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   280
            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
   281
                if i not in self.filteredrevs:
5ade47284dda repoview: move changelog.revs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43445
diff changeset
   282
                    yield i
5ade47284dda repoview: move changelog.revs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43445
diff changeset
   283
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   284
        return filterediter()
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   285
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   286
    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
   287
        """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
   288
        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
   289
            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
   290
                yield i
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   291
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   292
    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
   293
        """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
   294
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   295
        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
   296
        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
   297
        """
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   298
        safehasattr = util.safehasattr
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   299
        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
   300
            # 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
   301
            revs = set(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
        filteredrevs = self.filteredrevs
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   304
        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
   305
            offenders = revs & filteredrevs
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   306
        else:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   307
            offenders = filteredrevs.intersection(revs)
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   308
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   309
        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
   310
            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
   311
        return revs
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   312
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   313
    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
   314
        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
   315
            try:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   316
                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
   317
            # 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
   318
            # 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
   319
            except AttributeError:
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   320
                return self._headrevs()
43447
476754edac1f repoview: move changelog.headrevs() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43446
diff changeset
   321
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   322
        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
   323
        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
   324
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   325
    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
   326
        # 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
   327
        # 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
   328
        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
   329
        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
   330
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   331
    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
   332
        """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
   333
        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
   334
        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
   335
            raise error.FilteredLookupError(
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   336
                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
   337
            )
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   338
        return r
43450
6f3222bbfce0 repoview: move changelog.node() override to filteredchangelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43449
diff changeset
   339
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   340
    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
   341
        """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
   342
        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
   343
            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
   344
        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
   345
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   346
    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
   347
        """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
   348
        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
   349
            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
   350
        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
   351
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   352
    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
   353
        """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
   354
        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
   355
            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
   356
        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
   357
43492
bad4a26b4607 repoview: define filteredchangelog as a top-level (non-local) class
Martin von Zweigbergk <martinvonz@google.com>
parents: 43454
diff changeset
   358
    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
   359
        """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
   360
        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
   361
            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
   362
        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
   363
d630c5710801 repoview: extract a function for wrapping changelog
Martin von Zweigbergk <martinvonz@google.com>
parents: 43240
diff changeset
   364
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   365
class repoview(object):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   366
    """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
   367
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   368
    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
   369
    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
   370
    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
   371
    - 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
   372
      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
   373
    - 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
   374
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   375
    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
   376
    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
   377
    - 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
   378
    - 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
   379
    - 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
   380
      from `repo.__dict__`.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   381
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   382
    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
   383
    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
   384
    `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
   385
    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
   386
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   387
    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
   388
    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
   389
    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
   390
    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
   391
    `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
   392
    leads to the property below.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   393
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   394
        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
   395
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   396
    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
   397
    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
   398
    """
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   399
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   400
    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
   401
        object.__setattr__(self, '_unfilteredrepo', repo)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   402
        object.__setattr__(self, 'filtername', filtername)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   403
        object.__setattr__(self, '_clcachekey', None)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   404
        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
   405
        # 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
   406
        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
   407
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
   408
    # 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
   409
    @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   410
    def changelog(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   411
        """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
   412
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   413
        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
   414
        # some cache may be implemented later
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   415
        unfi = self._unfilteredrepo
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   416
        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
   417
        # 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
   418
        unfiindex = unfichangelog.index
38851
781b2720d2ac index: don't include nullid in len()
Martin von Zweigbergk <martinvonz@google.com>
parents: 38783
diff changeset
   419
        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
   420
        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
   421
        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
   422
            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
   423
        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
   424
        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
   425
        # 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
   426
        # recreated, and our clcache refers to garbage object
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   427
        if cl is not None and (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   428
            cl.index is not unfiindex or newkey != self._clcachekey
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   429
        ):
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
   430
            cl = None
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   431
        # 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
   432
        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
   433
            # 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
   434
            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
   435
            object.__setattr__(self, '_clcache', cl)
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   436
            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
   437
        return cl
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   438
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   439
    def unfiltered(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   440
        """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
   441
        return self._unfilteredrepo
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   442
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   443
    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
   444
        """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
   445
        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
   446
            return self
35492
3ad582b2895c repoview: add visibilityexceptions as an optional argument to repo.filtered()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35249
diff changeset
   447
        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
   448
35249
d4ad9d695a9e repoview: include filter name in repr for debugging
Yuya Nishihara <yuya@tcha.org>
parents: 35248
diff changeset
   449
    def __repr__(self):
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43492
diff changeset
   450
        return '<%s:%s %r>' % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   451
            self.__class__.__name__,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   452
            pycompat.sysstr(self.filtername),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   453
            self.unfiltered(),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   454
        )
35249
d4ad9d695a9e repoview: include filter name in repr for debugging
Yuya Nishihara <yuya@tcha.org>
parents: 35248
diff changeset
   455
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   456
    # 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
   457
    def __getattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   458
        return getattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   459
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   460
    def __setattr__(self, attr, value):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   461
        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
   462
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   463
    def __delattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   464
        return delattr(self._unfilteredrepo, attr)
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   465
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   466
47011
b7e623ac98b6 repoview: separate concerns in _filteredrepotypes comment
Georges Racinet <georges.racinet@octobus.net>
parents: 47010
diff changeset
   467
# Dynamically created classes introduce memory cycles via __mro__. See
b7e623ac98b6 repoview: separate concerns in _filteredrepotypes comment
Georges Racinet <georges.racinet@octobus.net>
parents: 47010
diff changeset
   468
# https://bugs.python.org/issue17950.
b7e623ac98b6 repoview: separate concerns in _filteredrepotypes comment
Georges Racinet <georges.racinet@octobus.net>
parents: 47010
diff changeset
   469
# This need of the garbage collector can turn into memory leak in
b7e623ac98b6 repoview: separate concerns in _filteredrepotypes comment
Georges Racinet <georges.racinet@octobus.net>
parents: 47010
diff changeset
   470
# Python <3.4, which is the first version released with PEP 442.
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   471
_filteredrepotypes = weakref.WeakKeyDictionary()
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   472
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   473
35248
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   474
def newtype(base):
c752fbe228fb repoview: extract a factory function of proxy class
Yuya Nishihara <yuya@tcha.org>
parents: 34649
diff changeset
   475
    """Create a new type with the repoview mixin and the given base class"""
47010
76ae43d5b1db repoview: fix memory leak of filtered repo classes
Georges Racinet <georges.racinet@octobus.net>
parents: 47009
diff changeset
   476
    ref = _filteredrepotypes.get(base)
76ae43d5b1db repoview: fix memory leak of filtered repo classes
Georges Racinet <georges.racinet@octobus.net>
parents: 47009
diff changeset
   477
    if ref is not None:
76ae43d5b1db repoview: fix memory leak of filtered repo classes
Georges Racinet <georges.racinet@octobus.net>
parents: 47009
diff changeset
   478
        cls = ref()
76ae43d5b1db repoview: fix memory leak of filtered repo classes
Georges Racinet <georges.racinet@octobus.net>
parents: 47009
diff changeset
   479
        if cls is not None:
76ae43d5b1db repoview: fix memory leak of filtered repo classes
Georges Racinet <georges.racinet@octobus.net>
parents: 47009
diff changeset
   480
            return cls
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   481
47009
42eb8b7881b8 repoview: style change in newtype() cache handling
Georges Racinet <georges.racinet@octobus.net>
parents: 46195
diff changeset
   482
    class filteredrepo(repoview, base):
42eb8b7881b8 repoview: style change in newtype() cache handling
Georges Racinet <georges.racinet@octobus.net>
parents: 46195
diff changeset
   483
        pass
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42231
diff changeset
   484
47010
76ae43d5b1db repoview: fix memory leak of filtered repo classes
Georges Racinet <georges.racinet@octobus.net>
parents: 47009
diff changeset
   485
    _filteredrepotypes[base] = weakref.ref(filteredrepo)
76ae43d5b1db repoview: fix memory leak of filtered repo classes
Georges Racinet <georges.racinet@octobus.net>
parents: 47009
diff changeset
   486
    # do not reread from weakref to be 100% sure not to return None
47009
42eb8b7881b8 repoview: style change in newtype() cache handling
Georges Racinet <georges.racinet@octobus.net>
parents: 46195
diff changeset
   487
    return filteredrepo