mercurial/repoview.py
author Siddharth Agarwal <sid0@fb.com>
Tue, 24 Nov 2015 15:26:51 -0800
changeset 27132 baa7571f40c5
parent 25972 f279191124f3
child 27257 49a76d3d43b1
permissions -rw-r--r--
merge.recordupdates: mark 'a' files as added unconditionally See the previous patch for why we do this.
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
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    12
import heapq
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    13
import struct
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    14
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    15
from .node import nullrev
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    16
from . import (
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    17
    error,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    18
    obsolete,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    19
    phases,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    20
    tags as tagsmod,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    21
    util,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
    22
)
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
    23
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    24
def hideablerevs(repo):
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    25
    """Revisions candidates to be hidden
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    26
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    27
    This is a standalone function to help extensions to wrap it."""
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    28
    return obsolete.getrevs(repo, 'obsolete')
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
    29
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
    30
def _getstatichidden(repo):
24615
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    31
    """Revision to be hidden (disregarding dynamic blocker)
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
    32
24615
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    33
    To keep a consistent graph, we cannot hide any revisions with
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    34
    non-hidden descendants. This function computes the set of
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    35
    revisions that could be hidden while keeping the graph consistent.
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    36
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    37
    A second pass will be done to apply "dynamic blocker" like bookmarks or
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    38
    working directory parents.
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    39
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
    40
    """
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
    41
    assert not repo.changelog.filteredrevs
24617
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    42
    hidden = set(hideablerevs(repo))
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    43
    if hidden:
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
    44
        getphase = repo._phasecache.phase
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
    45
        getparentrevs = repo.changelog.parentrevs
24618
cde57a8d8fe7 repoview: directly skip public head in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24617
diff changeset
    46
        # Skip heads which are public (guaranteed to not be hidden)
cde57a8d8fe7 repoview: directly skip public head in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24617
diff changeset
    47
        heap = [-r for r in repo.changelog.headrevs() if getphase(repo, r)]
24616
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
    48
        heapq.heapify(heap)
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
    49
        heappop = heapq.heappop
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
    50
        heappush = heapq.heappush
24620
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
    51
        seen = set() # no need to init it with heads, they have no children
24616
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
    52
        while heap:
24617
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    53
            rev = -heappop(heap)
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    54
            # All children have been processed so at that point, if no children
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    55
            # removed 'rev' from the 'hidden' set, 'rev' is going to be hidden.
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    56
            blocker = rev not in hidden
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    57
            for parent in getparentrevs(rev):
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    58
                if parent == nullrev:
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    59
                    continue
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    60
                if blocker:
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    61
                    # If visible, ensure parent will be visible too
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    62
                    hidden.discard(parent)
24620
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
    63
                # - Avoid adding the same revision twice
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
    64
                # - Skip nodes which are public (guaranteed to not be hidden)
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
    65
                pre = len(seen)
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
    66
                seen.add(parent)
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
    67
                if pre < len(seen) and getphase(repo, rev):
24619
ad6dea5d96f2 repoview: skip public parent earlier in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24618
diff changeset
    68
                    heappush(heap, -parent)
24617
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
    69
    return hidden
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    70
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    71
def _getdynamicblockers(repo):
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    72
    """Non-cacheable revisions blocking hidden changesets from being filtered.
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    73
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    74
    Get revisions that will block hidden changesets and are likely to change,
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    75
    but unlikely to create hidden blockers. They won't be cached, so be careful
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    76
    with adding additional computation."""
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    77
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    78
    cl = repo.changelog
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    79
    blockers = set()
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    80
    blockers.update([par.rev() for par in repo[None].parents()])
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    81
    blockers.update([cl.rev(bm) for bm in repo._bookmarks.values()])
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    82
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    83
    tags = {}
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    84
    tagsmod.readlocaltags(repo.ui, repo, tags, {})
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    85
    if tags:
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    86
        rev, nodemap = cl.rev, cl.nodemap
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
    87
        blockers.update(rev(t[0]) for t in tags.values() if t[0] in nodemap)
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
    88
    return blockers
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
    89
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    90
cacheversion = 1
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    91
cachefile = 'cache/hidden'
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    92
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    93
def cachehash(repo, hideable):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    94
    """return sha1 hash of repository data to identify a valid cache.
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    95
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    96
    We calculate a sha1 of repo heads and the content of the obsstore and write
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    97
    it to the cache. Upon reading we can easily validate by checking the hash
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    98
    against the stored one and discard the cache in case the hashes don't match.
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
    99
    """
22282
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
   100
    h = util.sha1()
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
   101
    h.update(''.join(repo.heads()))
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   102
    h.update(str(hash(frozenset(hideable))))
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   103
    return h.digest()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   104
23378
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
   105
def _writehiddencache(cachefile, cachehash, hidden):
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
   106
    """write hidden data to a cache file"""
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
   107
    data = struct.pack('>%ii' % len(hidden), *sorted(hidden))
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
   108
    cachefile.write(struct.pack(">H", cacheversion))
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
   109
    cachefile.write(cachehash)
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
   110
    cachefile.write(data)
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
   111
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   112
def trywritehiddencache(repo, hideable, hidden):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   113
    """write cache of hidden changesets to disk
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   114
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   115
    Will not write the cache if a wlock cannot be obtained lazily.
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   116
    The cache consists of a head of 22byte:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   117
       2 byte    version number of the cache
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   118
      20 byte    sha1 to validate the cache
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   119
     n*4 byte    hidden revs
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   120
    """
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   121
    wlock = fh = None
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   122
    try:
25086
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   123
        wlock = repo.wlock(wait=False)
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   124
        # write cache to file
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   125
        newhash = cachehash(repo, hideable)
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   126
        fh = repo.vfs.open(cachefile, 'w+b', atomictemp=True)
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   127
        _writehiddencache(fh, newhash, hidden)
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   128
    except (IOError, OSError):
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   129
        repo.ui.debug('error writing hidden changesets cache')
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   130
    except error.LockHeld:
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
   131
        repo.ui.debug('cannot obtain lock to write hidden changesets cache')
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   132
    finally:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   133
        if fh:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   134
            fh.close()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   135
        if wlock:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   136
            wlock.release()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   137
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   138
def tryreadcache(repo, hideable):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   139
    """read a cache if the cache exists and is valid, otherwise returns None."""
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   140
    hidden = fh = None
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   141
    try:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   142
        if repo.vfs.exists(cachefile):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   143
            fh = repo.vfs.open(cachefile, 'rb')
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   144
            version, = struct.unpack(">H", fh.read(2))
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   145
            oldhash = fh.read(20)
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   146
            newhash = cachehash(repo, hideable)
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   147
            if (cacheversion, oldhash) == (version, newhash):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   148
                # cache is valid, so we can start reading the hidden revs
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   149
                data = fh.read()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   150
                count = len(data) / 4
22282
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
   151
                hidden = frozenset(struct.unpack('>%ii' % count, data))
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   152
        return hidden
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   153
    finally:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   154
        if fh:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   155
            fh.close()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
   156
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   157
def computehidden(repo):
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   158
    """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
   159
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   160
    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
   161
    assert not repo.changelog.filteredrevs
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
   162
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   163
    hidden = frozenset()
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
   164
    hideable = hideablerevs(repo)
18272
95ef7a87c053 performance: speedup computation of hidden revisions
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18250
diff changeset
   165
    if hideable:
95ef7a87c053 performance: speedup computation of hidden revisions
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18250
diff changeset
   166
        cl = repo.changelog
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
   167
        hidden = tryreadcache(repo, hideable)
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
   168
        if hidden is None:
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
   169
            hidden = frozenset(_getstatichidden(repo))
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
   170
            trywritehiddencache(repo, hideable, hidden)
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   171
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   172
        # check if we have wd parents, bookmarks or tags pointing to hidden
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   173
        # changesets and remove those.
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   174
        dynamic = hidden & _getdynamicblockers(repo)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   175
        if dynamic:
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   176
            blocked = cl.ancestors(dynamic, inclusive=True)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   177
            hidden = frozenset(r for r in hidden if r not in blocked)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
   178
    return hidden
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
   179
18102
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   180
def computeunserved(repo):
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   181
    """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
   182
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   183
    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
   184
    assert not repo.changelog.filteredrevs
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
   185
    # fast path in simple case to avoid impact of non optimised code
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
   186
    hiddens = filterrevs(repo, 'visible')
18273
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   187
    if phases.hassecret(repo):
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   188
        cl = repo.changelog
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   189
        secret = phases.secret
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   190
        getphase = repo._phasecache.phase
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   191
        first = min(cl.rev(n) for n in repo._phasecache.phaseroots[secret])
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   192
        revs = cl.revs(start=first)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   193
        secrets = set(r for r in revs if getphase(repo, r) >= secret)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   194
        return frozenset(hiddens | secrets)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   195
    else:
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
   196
        return hiddens
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   197
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   198
def computemutable(repo):
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   199
    """compute the set of revision that should be filtered when used a server
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   200
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   201
    Secret and hidden changeset should not pretend to be here."""
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   202
    assert not repo.changelog.filteredrevs
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   203
    # 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
   204
    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
   205
        getphase = repo._phasecache.phase
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
   206
        maymutable = filterrevs(repo, 'base')
18274
254b708fd37d performance: speedup computation of mutable revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18273
diff changeset
   207
        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
   208
    return frozenset()
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
   209
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   210
def computeimpactable(repo):
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   211
    """Everything impactable by mutable revision
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   212
18462
593eb3786165 documentation: update to new filter names
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18445
diff changeset
   213
    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
   214
    happen when:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   215
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   216
    - you garbage collect hidden changeset,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   217
    - public phase is moved backward,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   218
    - 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
   219
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   220
    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
   221
    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
   222
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   223
    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
   224
    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
   225
    assert not repo.changelog.filteredrevs
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   226
    cl = repo.changelog
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   227
    firstmutable = len(cl)
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   228
    for roots in repo._phasecache.phaseroots[1:]:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   229
        if roots:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   230
            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
   231
    # 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
   232
    firstmutable = max(0, firstmutable)
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   233
    return frozenset(xrange(firstmutable, len(cl)))
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
   234
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   235
# 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
   236
#
20549
2025315cfb0c comments: fix minor spelling issues found with spell checker
Mads Kiilerich <madski@unity3d.com>
parents: 20405
diff changeset
   237
# When adding a new filter you MUST update the table at:
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
   238
#     mercurial.branchmap.subsettable
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
   239
# 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
   240
# from scratch (very slow).
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
   241
filtertable = {'visible': computehidden,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
   242
               'served': computeunserved,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
   243
               'immutable':  computemutable,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
   244
               'base':  computeimpactable}
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   245
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
   246
def filterrevs(repo, filtername):
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   247
    """returns set of filtered revision for this filter name"""
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
   248
    if filtername not in repo.filteredrevcache:
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
        func = filtertable[filtername]
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
        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
   251
    return repo.filteredrevcache[filtername]
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   252
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   253
class repoview(object):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   254
    """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
   255
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   256
    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
   257
    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
   258
    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
   259
    - 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
   260
      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
   261
    - 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
   262
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   263
    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
   264
    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
   265
    - 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
   266
    - 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
   267
    - 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
   268
      from `repo.__dict__`.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   269
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   270
    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
   271
    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
   272
    `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
   273
    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
   274
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   275
    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
   276
    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
   277
    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
   278
    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
   279
    `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
   280
    leads to the property below.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   281
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   282
        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
   283
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   284
    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
   285
    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
   286
    """
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   287
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   288
    def __init__(self, repo, filtername):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   289
        object.__setattr__(self, '_unfilteredrepo', repo)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   290
        object.__setattr__(self, 'filtername', filtername)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   291
        object.__setattr__(self, '_clcachekey', None)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   292
        object.__setattr__(self, '_clcache', None)
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   293
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
   294
    # 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
   295
    @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   296
    def changelog(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   297
        """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
   298
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   299
        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
   300
        # some cache may be implemented later
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   301
        unfi = self._unfilteredrepo
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   302
        unfichangelog = unfi.changelog
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   303
        revs = filterrevs(unfi, self.filtername)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   304
        cl = self._clcache
24154
a41902aac76d repoview: invalidate cached changelog if _delayed changes (issue4549)
Matt Mackall <mpm@selenic.com>
parents: 23636
diff changeset
   305
        newkey = (len(unfichangelog), unfichangelog.tip(), hash(revs),
a41902aac76d repoview: invalidate cached changelog if _delayed changes (issue4549)
Matt Mackall <mpm@selenic.com>
parents: 23636
diff changeset
   306
                  unfichangelog._delayed)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   307
        if cl is not None:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   308
            # we need to check curkey too for some obscure reason.
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   309
            # MQ test show a corruption of the underlying repo (in _clcache)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   310
            # without change in the cachekey.
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   311
            oldfilter = cl.filteredrevs
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   312
            try:
22317
e1d5fcab58b6 repoview: fix typo in repoview.changelog
Mike Hommey <mh@glandium.org>
parents: 22106
diff changeset
   313
                cl.filteredrevs = ()  # disable filtering for tip
24154
a41902aac76d repoview: invalidate cached changelog if _delayed changes (issue4549)
Matt Mackall <mpm@selenic.com>
parents: 23636
diff changeset
   314
                curkey = (len(cl), cl.tip(), hash(oldfilter), cl._delayed)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   315
            finally:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   316
                cl.filteredrevs = oldfilter
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   317
            if newkey != self._clcachekey or newkey != curkey:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   318
                cl = None
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   319
        # 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
   320
        if cl is None:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   321
            cl = copy.copy(unfichangelog)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   322
            cl.filteredrevs = revs
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   323
            object.__setattr__(self, '_clcache', cl)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
   324
            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
   325
        return cl
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   326
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   327
    def unfiltered(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   328
        """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
   329
        return self._unfilteredrepo
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   330
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   331
    def filtered(self, name):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   332
        """Return a filtered version of a repository"""
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   333
        if name == self.filtername:
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   334
            return self
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   335
        return self.unfiltered().filtered(name)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   336
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   337
    # 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
   338
    def __getattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   339
        return getattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   340
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   341
    def __setattr__(self, attr, value):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   342
        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
   343
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   344
    def __delattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   345
        return delattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   346
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
   347
    # The `requirements` attribute is initialized during __init__. But
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   348
    # __getattr__ won't be called as it also exists on the class. We need
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   349
    # explicit forwarding to main repo here
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   350
    @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   351
    def requirements(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
   352
        return self._unfilteredrepo.requirements