74
67
def describe(self):
75
68
return "%s is locked" % self.lockable_thing
78
class _AncestryMismatch(Mismatch):
79
"""Ancestry matching mismatch."""
81
def __init__(self, tip_revision, got, expected):
82
self.tip_revision = tip_revision
84
self.expected = expected
87
return "mismatched ancestry for revision %r was %r, expected %r" % (
88
self.tip_revision, self.got, self.expected)
91
class MatchesAncestry(Matcher):
92
"""A matcher that checks the ancestry of a particular revision.
94
:ivar graph: Graph in which to check the ancestry
95
:ivar revision_id: Revision id of the revision
98
def __init__(self, repository, revision_id):
99
Matcher.__init__(self)
100
self.repository = repository
101
self.revision_id = revision_id
104
return ('MatchesAncestry(repository=%r, revision_id=%r)' % (
105
self.repository, self.revision_id))
107
def match(self, expected):
108
self.repository.lock_read()
110
graph = self.repository.get_graph()
111
got = [r for r, p in graph.iter_ancestry([self.revision_id])]
112
if _mod_revision.NULL_REVISION in got:
113
got.remove(_mod_revision.NULL_REVISION)
115
self.repository.unlock()
116
if sorted(got) != sorted(expected):
117
return _AncestryMismatch(self.revision_id, sorted(got),
121
class HasLayout(Matcher):
122
"""A matcher that checks if a tree has a specific layout.
124
:ivar entries: List of expected entries, as (path, file_id) pairs.
127
def __init__(self, entries):
128
Matcher.__init__(self)
129
self.entries = entries
131
def get_tree_layout(self, tree):
132
"""Get the (path, file_id) pairs for the current tree."""
135
for path, ie in tree.iter_entries_by_dir():
136
if ie.parent_id is None:
137
yield (u"", ie.file_id)
139
yield (path+ie.kind_character(), ie.file_id)
144
def _strip_unreferenced_directories(entries):
145
"""Strip all directories that don't (in)directly contain any files.
147
:param entries: List of path strings or (path, ie) tuples to process
150
for entry in entries:
151
if isinstance(entry, basestring):
155
if not path or path[-1] == "/":
157
directories.append((path, entry))
159
# Yield the referenced parent directories
160
for dirpath, direntry in directories:
161
if osutils.is_inside(dirpath, path):
167
return 'HasLayout(%r)' % self.entries
169
def match(self, tree):
170
actual = list(self.get_tree_layout(tree))
171
if self.entries and isinstance(self.entries[0], basestring):
172
actual = [path for (path, fileid) in actual]
173
if not tree.has_versioned_directories():
174
entries = list(self._strip_unreferenced_directories(self.entries))
176
entries = self.entries
177
return Equals(entries).match(actual)