/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/matchers.py

Merge fix for bug #388269 into trunk, resolve conflicts and add release notes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
"""
28
28
 
29
29
__all__ = [
 
30
    'HasLayout',
 
31
    'MatchesAncestry',
30
32
    'ReturnsUnlockable',
31
33
    ]
32
34
 
33
 
from testtools.matchers import Mismatch, Matcher
 
35
from bzrlib import (
 
36
    revision as _mod_revision,
 
37
    )
 
38
 
 
39
from testtools.matchers import Equals, Mismatch, Matcher
34
40
 
35
41
 
36
42
class ReturnsUnlockable(Matcher):
66
72
 
67
73
    def describe(self):
68
74
        return "%s is locked" % self.lockable_thing
 
75
 
 
76
 
 
77
class _AncestryMismatch(Mismatch):
 
78
    """Ancestry matching mismatch."""
 
79
 
 
80
    def __init__(self, tip_revision, got, expected):
 
81
        self.tip_revision = tip_revision
 
82
        self.got = got
 
83
        self.expected = expected
 
84
 
 
85
    def describe(self):
 
86
        return "mismatched ancestry for revision %r was %r, expected %r" % (
 
87
            self.tip_revision, self.got, self.expected)
 
88
 
 
89
 
 
90
class MatchesAncestry(Matcher):
 
91
    """A matcher that checks the ancestry of a particular revision.
 
92
 
 
93
    :ivar graph: Graph in which to check the ancestry
 
94
    :ivar revision_id: Revision id of the revision
 
95
    """
 
96
 
 
97
    def __init__(self, repository, revision_id):
 
98
        Matcher.__init__(self)
 
99
        self.repository = repository
 
100
        self.revision_id = revision_id
 
101
 
 
102
    def __str__(self):
 
103
        return ('MatchesAncestry(repository=%r, revision_id=%r)' % (
 
104
            self.repository, self.revision_id))
 
105
 
 
106
    def match(self, expected):
 
107
        self.repository.lock_read()
 
108
        try:
 
109
            graph = self.repository.get_graph()
 
110
            got = [r for r, p in graph.iter_ancestry([self.revision_id])]
 
111
            if _mod_revision.NULL_REVISION in got:
 
112
                got.remove(_mod_revision.NULL_REVISION)
 
113
        finally:
 
114
            self.repository.unlock()
 
115
        if sorted(got) != sorted(expected):
 
116
            return _AncestryMismatch(self.revision_id, sorted(got),
 
117
                sorted(expected))
 
118
 
 
119
 
 
120
class HasLayout(Matcher):
 
121
    """A matcher that checks if a tree has a specific layout.
 
122
 
 
123
    :ivar entries: List of expected entries, as (path, file_id) pairs.
 
124
    """
 
125
 
 
126
    def __init__(self, entries):
 
127
        Matcher.__init__(self)
 
128
        self.entries = entries
 
129
 
 
130
    def get_tree_layout(self, tree):
 
131
        """Get the (path, file_id) pairs for the current tree."""
 
132
        tree.lock_read()
 
133
        try:
 
134
            return [(path, ie.file_id) for path, ie
 
135
                    in tree.iter_entries_by_dir()]
 
136
        finally:
 
137
            tree.unlock()
 
138
 
 
139
    def __str__(self):
 
140
        return ('HasLayout(%r)' % self.entries)
 
141
 
 
142
    def match(self, tree):
 
143
        actual = self.get_tree_layout(tree)
 
144
        if self.entries and isinstance(self.entries[0], basestring):
 
145
            actual = [path for (path, fileid) in actual]
 
146
        return Equals(actual).match(self.entries)