gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / dulwich / tests / test_walk.py @ 959
History | View | Annotate | Download (21.7 KB)
1 |
# test_walk.py -- Tests for commit walking functionality.
|
---|---|
2 |
# Copyright (C) 2010 Google, Inc.
|
3 |
#
|
4 |
# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
|
5 |
# General Public License as public by the Free Software Foundation; version 2.0
|
6 |
# or (at your option) any later version. You can redistribute it and/or
|
7 |
# modify it under the terms of either of these two licenses.
|
8 |
#
|
9 |
# Unless required by applicable law or agreed to in writing, software
|
10 |
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
# See the License for the specific language governing permissions and
|
13 |
# limitations under the License.
|
14 |
#
|
15 |
# You should have received a copy of the licenses; if not, see
|
16 |
# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
|
17 |
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
|
18 |
# License, Version 2.0.
|
19 |
#
|
20 |
|
21 |
"""Tests for commit walking functionality."""
|
22 |
|
23 |
from itertools import ( |
24 |
permutations, |
25 |
) |
26 |
|
27 |
from dulwich.diff_tree import ( |
28 |
CHANGE_ADD, |
29 |
CHANGE_MODIFY, |
30 |
CHANGE_RENAME, |
31 |
TreeChange, |
32 |
RenameDetector, |
33 |
) |
34 |
from dulwich.errors import ( |
35 |
MissingCommitError, |
36 |
) |
37 |
from dulwich.object_store import ( |
38 |
MemoryObjectStore, |
39 |
) |
40 |
from dulwich.objects import ( |
41 |
Commit, |
42 |
Blob, |
43 |
) |
44 |
from dulwich.walk import ( |
45 |
ORDER_TOPO, |
46 |
WalkEntry, |
47 |
Walker, |
48 |
_topo_reorder |
49 |
) |
50 |
from dulwich.tests import TestCase |
51 |
from dulwich.tests.utils import ( |
52 |
F, |
53 |
make_object, |
54 |
build_commit_graph, |
55 |
) |
56 |
|
57 |
|
58 |
class TestWalkEntry(object): |
59 |
|
60 |
def __init__(self, commit, changes): |
61 |
self.commit = commit
|
62 |
self.changes = changes
|
63 |
|
64 |
def __repr__(self): |
65 |
return '<TestWalkEntry commit=%s, changes=%r>' % ( |
66 |
self.commit.id, self.changes) |
67 |
|
68 |
def __eq__(self, other): |
69 |
if not isinstance(other, WalkEntry) or self.commit != other.commit: |
70 |
return False |
71 |
if self.changes is None: |
72 |
return True |
73 |
return self.changes == other.changes() |
74 |
|
75 |
|
76 |
class WalkerTest(TestCase): |
77 |
|
78 |
def setUp(self): |
79 |
super(WalkerTest, self).setUp() |
80 |
self.store = MemoryObjectStore()
|
81 |
|
82 |
def make_commits(self, commit_spec, **kwargs): |
83 |
times = kwargs.pop('times', [])
|
84 |
attrs = kwargs.pop('attrs', {})
|
85 |
for i, t in enumerate(times): |
86 |
attrs.setdefault(i + 1, {})['commit_time'] = t |
87 |
return build_commit_graph(self.store, commit_spec, attrs=attrs, |
88 |
**kwargs) |
89 |
|
90 |
def make_linear_commits(self, num_commits, **kwargs): |
91 |
commit_spec = [] |
92 |
for i in range(1, num_commits + 1): |
93 |
c = [i] |
94 |
if i > 1: |
95 |
c.append(i - 1)
|
96 |
commit_spec.append(c) |
97 |
return self.make_commits(commit_spec, **kwargs) |
98 |
|
99 |
def assertWalkYields(self, expected, *args, **kwargs): |
100 |
walker = Walker(self.store, *args, **kwargs)
|
101 |
expected = list(expected)
|
102 |
for i, entry in enumerate(expected): |
103 |
if isinstance(entry, Commit): |
104 |
expected[i] = TestWalkEntry(entry, None)
|
105 |
actual = list(walker)
|
106 |
self.assertEqual(expected, actual)
|
107 |
|
108 |
def test_linear(self): |
109 |
c1, c2, c3 = self.make_linear_commits(3) |
110 |
self.assertWalkYields([c1], [c1.id])
|
111 |
self.assertWalkYields([c2, c1], [c2.id])
|
112 |
self.assertWalkYields([c3, c2, c1], [c3.id])
|
113 |
self.assertWalkYields([c3, c2, c1], [c3.id, c1.id])
|
114 |
self.assertWalkYields([c3, c2], [c3.id], exclude=[c1.id])
|
115 |
self.assertWalkYields([c3, c2], [c3.id, c1.id], exclude=[c1.id])
|
116 |
self.assertWalkYields([c3], [c3.id, c1.id], exclude=[c2.id])
|
117 |
|
118 |
def test_missing(self): |
119 |
cs = list(reversed(self.make_linear_commits(20))) |
120 |
self.assertWalkYields(cs, [cs[0].id]) |
121 |
|
122 |
# Exactly how close we can get to a missing commit depends on our
|
123 |
# implementation (in particular the choice of _MAX_EXTRA_COMMITS), but
|
124 |
# we should at least be able to walk some history in a broken repo.
|
125 |
del self.store[cs[-1].id] |
126 |
for i in range(1, 11): |
127 |
self.assertWalkYields(cs[:i], [cs[0].id], max_entries=i) |
128 |
self.assertRaises(MissingCommitError, Walker, self.store, [cs[-1].id]) |
129 |
|
130 |
def test_branch(self): |
131 |
c1, x2, x3, y4 = self.make_commits([[1], [2, 1], [3, 2], [4, 1]]) |
132 |
self.assertWalkYields([x3, x2, c1], [x3.id])
|
133 |
self.assertWalkYields([y4, c1], [y4.id])
|
134 |
self.assertWalkYields([y4, x2, c1], [y4.id, x2.id])
|
135 |
self.assertWalkYields([y4, x2], [y4.id, x2.id], exclude=[c1.id])
|
136 |
self.assertWalkYields([y4, x3], [y4.id, x3.id], exclude=[x2.id])
|
137 |
self.assertWalkYields([y4], [y4.id], exclude=[x3.id])
|
138 |
self.assertWalkYields([x3, x2], [x3.id], exclude=[y4.id])
|
139 |
|
140 |
def test_merge(self): |
141 |
c1, c2, c3, c4 = self.make_commits([[1], [2, 1], [3, 1], [4, 2, 3]]) |
142 |
self.assertWalkYields([c4, c3, c2, c1], [c4.id])
|
143 |
self.assertWalkYields([c3, c1], [c3.id])
|
144 |
self.assertWalkYields([c2, c1], [c2.id])
|
145 |
self.assertWalkYields([c4, c3], [c4.id], exclude=[c2.id])
|
146 |
self.assertWalkYields([c4, c2], [c4.id], exclude=[c3.id])
|
147 |
|
148 |
def test_reverse(self): |
149 |
c1, c2, c3 = self.make_linear_commits(3) |
150 |
self.assertWalkYields([c1, c2, c3], [c3.id], reverse=True) |
151 |
|
152 |
def test_max_entries(self): |
153 |
c1, c2, c3 = self.make_linear_commits(3) |
154 |
self.assertWalkYields([c3, c2, c1], [c3.id], max_entries=3) |
155 |
self.assertWalkYields([c3, c2], [c3.id], max_entries=2) |
156 |
self.assertWalkYields([c3], [c3.id], max_entries=1) |
157 |
|
158 |
def test_reverse_after_max_entries(self): |
159 |
c1, c2, c3 = self.make_linear_commits(3) |
160 |
self.assertWalkYields([c1, c2, c3], [c3.id], max_entries=3, |
161 |
reverse=True)
|
162 |
self.assertWalkYields([c2, c3], [c3.id], max_entries=2, reverse=True) |
163 |
self.assertWalkYields([c3], [c3.id], max_entries=1, reverse=True) |
164 |
|
165 |
def test_changes_one_parent(self): |
166 |
blob_a1 = make_object(Blob, data=b'a1')
|
167 |
blob_a2 = make_object(Blob, data=b'a2')
|
168 |
blob_b2 = make_object(Blob, data=b'b2')
|
169 |
c1, c2 = self.make_linear_commits(
|
170 |
2, trees={1: [(b'a', blob_a1)], |
171 |
2: [(b'a', blob_a2), (b'b', blob_b2)]}) |
172 |
e1 = TestWalkEntry(c1, [TreeChange.add((b'a', F, blob_a1.id))])
|
173 |
e2 = TestWalkEntry(c2, [TreeChange(CHANGE_MODIFY, (b'a', F, blob_a1.id),
|
174 |
(b'a', F, blob_a2.id)),
|
175 |
TreeChange.add((b'b', F, blob_b2.id))])
|
176 |
self.assertWalkYields([e2, e1], [c2.id])
|
177 |
|
178 |
def test_changes_multiple_parents(self): |
179 |
blob_a1 = make_object(Blob, data=b'a1')
|
180 |
blob_b2 = make_object(Blob, data=b'b2')
|
181 |
blob_a3 = make_object(Blob, data=b'a3')
|
182 |
c1, c2, c3 = self.make_commits(
|
183 |
[[1], [2], [3, 1, 2]], |
184 |
trees={1: [(b'a', blob_a1)], 2: [(b'b', blob_b2)], |
185 |
3: [(b'a', blob_a3), (b'b', blob_b2)]}) |
186 |
# a is a modify/add conflict and b is not conflicted.
|
187 |
changes = [[ |
188 |
TreeChange(CHANGE_MODIFY, (b'a', F, blob_a1.id), (b'a', F, blob_a3.id)), |
189 |
TreeChange.add((b'a', F, blob_a3.id)),
|
190 |
]] |
191 |
self.assertWalkYields([TestWalkEntry(c3, changes)], [c3.id],
|
192 |
exclude=[c1.id, c2.id]) |
193 |
|
194 |
def test_path_matches(self): |
195 |
walker = Walker(None, [], paths=[b'foo', b'bar', b'baz/quux']) |
196 |
self.assertTrue(walker._path_matches(b'foo')) |
197 |
self.assertTrue(walker._path_matches(b'foo/a')) |
198 |
self.assertTrue(walker._path_matches(b'foo/a/b')) |
199 |
self.assertTrue(walker._path_matches(b'bar')) |
200 |
self.assertTrue(walker._path_matches(b'baz/quux')) |
201 |
self.assertTrue(walker._path_matches(b'baz/quux/a')) |
202 |
|
203 |
self.assertFalse(walker._path_matches(None)) |
204 |
self.assertFalse(walker._path_matches(b'oops')) |
205 |
self.assertFalse(walker._path_matches(b'fool')) |
206 |
self.assertFalse(walker._path_matches(b'baz')) |
207 |
self.assertFalse(walker._path_matches(b'baz/quu')) |
208 |
|
209 |
def test_paths(self): |
210 |
blob_a1 = make_object(Blob, data=b'a1')
|
211 |
blob_b2 = make_object(Blob, data=b'b2')
|
212 |
blob_a3 = make_object(Blob, data=b'a3')
|
213 |
blob_b3 = make_object(Blob, data=b'b3')
|
214 |
c1, c2, c3 = self.make_linear_commits(
|
215 |
3, trees={1: [(b'a', blob_a1)], |
216 |
2: [(b'a', blob_a1), (b'x/b', blob_b2)], |
217 |
3: [(b'a', blob_a3), (b'x/b', blob_b3)]}) |
218 |
|
219 |
self.assertWalkYields([c3, c2, c1], [c3.id])
|
220 |
self.assertWalkYields([c3, c1], [c3.id], paths=[b'a']) |
221 |
self.assertWalkYields([c3, c2], [c3.id], paths=[b'x/b']) |
222 |
|
223 |
# All changes are included, not just for requested paths.
|
224 |
changes = [ |
225 |
TreeChange(CHANGE_MODIFY, (b'a', F, blob_a1.id),
|
226 |
(b'a', F, blob_a3.id)),
|
227 |
TreeChange(CHANGE_MODIFY, (b'x/b', F, blob_b2.id),
|
228 |
(b'x/b', F, blob_b3.id)),
|
229 |
] |
230 |
self.assertWalkYields([TestWalkEntry(c3, changes)], [c3.id],
|
231 |
max_entries=1, paths=[b'a']) |
232 |
|
233 |
def test_paths_subtree(self): |
234 |
blob_a = make_object(Blob, data=b'a')
|
235 |
blob_b = make_object(Blob, data=b'b')
|
236 |
c1, c2, c3 = self.make_linear_commits(
|
237 |
3, trees={1: [(b'x/a', blob_a)], |
238 |
2: [(b'b', blob_b), (b'x/a', blob_a)], |
239 |
3: [(b'b', blob_b), (b'x/a', blob_a), (b'x/b', blob_b)]}) |
240 |
self.assertWalkYields([c2], [c3.id], paths=[b'b']) |
241 |
self.assertWalkYields([c3, c1], [c3.id], paths=[b'x']) |
242 |
|
243 |
def test_paths_max_entries(self): |
244 |
blob_a = make_object(Blob, data=b'a')
|
245 |
blob_b = make_object(Blob, data=b'b')
|
246 |
c1, c2 = self.make_linear_commits(
|
247 |
2, trees={1: [(b'a', blob_a)], |
248 |
2: [(b'a', blob_a), (b'b', blob_b)]}) |
249 |
self.assertWalkYields([c2], [c2.id], paths=[b'b'], max_entries=1) |
250 |
self.assertWalkYields([c1], [c1.id], paths=[b'a'], max_entries=1) |
251 |
|
252 |
def test_paths_merge(self): |
253 |
blob_a1 = make_object(Blob, data=b'a1')
|
254 |
blob_a2 = make_object(Blob, data=b'a2')
|
255 |
blob_a3 = make_object(Blob, data=b'a3')
|
256 |
x1, y2, m3, m4 = self.make_commits(
|
257 |
[[1], [2], [3, 1, 2], [4, 1, 2]], |
258 |
trees={1: [(b'a', blob_a1)], |
259 |
2: [(b'a', blob_a2)], |
260 |
3: [(b'a', blob_a3)], |
261 |
4: [(b'a', blob_a1)]}) # Non-conflicting |
262 |
self.assertWalkYields([m3, y2, x1], [m3.id], paths=[b'a']) |
263 |
self.assertWalkYields([y2, x1], [m4.id], paths=[b'a']) |
264 |
|
265 |
def test_changes_with_renames(self): |
266 |
blob = make_object(Blob, data=b'blob')
|
267 |
c1, c2 = self.make_linear_commits(
|
268 |
2, trees={1: [(b'a', blob)], 2: [(b'b', blob)]}) |
269 |
entry_a = (b'a', F, blob.id)
|
270 |
entry_b = (b'b', F, blob.id)
|
271 |
changes_without_renames = [TreeChange.delete(entry_a), |
272 |
TreeChange.add(entry_b)] |
273 |
changes_with_renames = [TreeChange(CHANGE_RENAME, entry_a, entry_b)] |
274 |
self.assertWalkYields(
|
275 |
[TestWalkEntry(c2, changes_without_renames)], [c2.id], max_entries=1)
|
276 |
detector = RenameDetector(self.store)
|
277 |
self.assertWalkYields(
|
278 |
[TestWalkEntry(c2, changes_with_renames)], [c2.id], max_entries=1,
|
279 |
rename_detector=detector) |
280 |
|
281 |
def test_follow_rename(self): |
282 |
blob = make_object(Blob, data=b'blob')
|
283 |
names = [b'a', b'a', b'b', b'b', b'c', b'c'] |
284 |
|
285 |
trees = dict((i + 1, [(n, blob, F)]) for i, n in enumerate(names)) |
286 |
c1, c2, c3, c4, c5, c6 = self.make_linear_commits(6, trees=trees) |
287 |
self.assertWalkYields([c5], [c6.id], paths=[b'c']) |
288 |
|
289 |
e = lambda n: (n, F, blob.id)
|
290 |
self.assertWalkYields(
|
291 |
[TestWalkEntry(c5, [TreeChange(CHANGE_RENAME, e(b'b'), e(b'c'))]), |
292 |
TestWalkEntry(c3, [TreeChange(CHANGE_RENAME, e(b'a'), e(b'b'))]), |
293 |
TestWalkEntry(c1, [TreeChange.add(e(b'a'))])],
|
294 |
[c6.id], paths=[b'c'], follow=True) |
295 |
|
296 |
def test_follow_rename_remove_path(self): |
297 |
blob = make_object(Blob, data=b'blob')
|
298 |
_, _, _, c4, c5, c6 = self.make_linear_commits(
|
299 |
6, trees={1: [(b'a', blob), (b'c', blob)], |
300 |
2: [],
|
301 |
3: [],
|
302 |
4: [(b'b', blob)], |
303 |
5: [(b'a', blob)], |
304 |
6: [(b'c', blob)]}) |
305 |
|
306 |
e = lambda n: (n, F, blob.id)
|
307 |
# Once the path changes to b, we aren't interested in a or c anymore.
|
308 |
self.assertWalkYields(
|
309 |
[TestWalkEntry(c6, [TreeChange(CHANGE_RENAME, e(b'a'), e(b'c'))]), |
310 |
TestWalkEntry(c5, [TreeChange(CHANGE_RENAME, e(b'b'), e(b'a'))]), |
311 |
TestWalkEntry(c4, [TreeChange.add(e(b'b'))])],
|
312 |
[c6.id], paths=[b'c'], follow=True) |
313 |
|
314 |
def test_since(self): |
315 |
c1, c2, c3 = self.make_linear_commits(3) |
316 |
self.assertWalkYields([c3, c2, c1], [c3.id], since=-1) |
317 |
self.assertWalkYields([c3, c2, c1], [c3.id], since=0) |
318 |
self.assertWalkYields([c3, c2], [c3.id], since=1) |
319 |
self.assertWalkYields([c3, c2], [c3.id], since=99) |
320 |
self.assertWalkYields([c3, c2], [c3.id], since=100) |
321 |
self.assertWalkYields([c3], [c3.id], since=101) |
322 |
self.assertWalkYields([c3], [c3.id], since=199) |
323 |
self.assertWalkYields([c3], [c3.id], since=200) |
324 |
self.assertWalkYields([], [c3.id], since=201) |
325 |
self.assertWalkYields([], [c3.id], since=300) |
326 |
|
327 |
def test_until(self): |
328 |
c1, c2, c3 = self.make_linear_commits(3) |
329 |
self.assertWalkYields([], [c3.id], until=-1) |
330 |
self.assertWalkYields([c1], [c3.id], until=0) |
331 |
self.assertWalkYields([c1], [c3.id], until=1) |
332 |
self.assertWalkYields([c1], [c3.id], until=99) |
333 |
self.assertWalkYields([c2, c1], [c3.id], until=100) |
334 |
self.assertWalkYields([c2, c1], [c3.id], until=101) |
335 |
self.assertWalkYields([c2, c1], [c3.id], until=199) |
336 |
self.assertWalkYields([c3, c2, c1], [c3.id], until=200) |
337 |
self.assertWalkYields([c3, c2, c1], [c3.id], until=201) |
338 |
self.assertWalkYields([c3, c2, c1], [c3.id], until=300) |
339 |
|
340 |
def test_since_until(self): |
341 |
c1, c2, c3 = self.make_linear_commits(3) |
342 |
self.assertWalkYields([], [c3.id], since=100, until=99) |
343 |
self.assertWalkYields([c3, c2, c1], [c3.id], since=-1, until=201) |
344 |
self.assertWalkYields([c2], [c3.id], since=100, until=100) |
345 |
self.assertWalkYields([c2], [c3.id], since=50, until=150) |
346 |
|
347 |
def test_since_over_scan(self): |
348 |
commits = self.make_linear_commits(
|
349 |
11, times=[9, 0, 1, 2, 3, 4, 5, 8, 6, 7, 9]) |
350 |
c8, _, c10, c11 = commits[-4:]
|
351 |
del self.store[commits[0].id] |
352 |
# c9 is older than we want to walk, but is out of order with its parent,
|
353 |
# so we need to walk past it to get to c8.
|
354 |
# c1 would also match, but we've deleted it, and it should get pruned
|
355 |
# even with over-scanning.
|
356 |
self.assertWalkYields([c11, c10, c8], [c11.id], since=7) |
357 |
|
358 |
def assertTopoOrderEqual(self, expected_commits, commits): |
359 |
entries = [TestWalkEntry(c, None) for c in commits] |
360 |
actual_ids = [e.commit.id for e in list(_topo_reorder(entries))] |
361 |
self.assertEqual([c.id for c in expected_commits], actual_ids) |
362 |
|
363 |
def test_topo_reorder_linear(self): |
364 |
commits = self.make_linear_commits(5) |
365 |
commits.reverse() |
366 |
for perm in permutations(commits): |
367 |
self.assertTopoOrderEqual(commits, perm)
|
368 |
|
369 |
def test_topo_reorder_multiple_parents(self): |
370 |
c1, c2, c3 = self.make_commits([[1], [2], [3, 1, 2]]) |
371 |
# Already sorted, so totally FIFO.
|
372 |
self.assertTopoOrderEqual([c3, c2, c1], [c3, c2, c1])
|
373 |
self.assertTopoOrderEqual([c3, c1, c2], [c3, c1, c2])
|
374 |
|
375 |
# c3 causes one parent to be yielded.
|
376 |
self.assertTopoOrderEqual([c3, c2, c1], [c2, c3, c1])
|
377 |
self.assertTopoOrderEqual([c3, c1, c2], [c1, c3, c2])
|
378 |
|
379 |
# c3 causes both parents to be yielded.
|
380 |
self.assertTopoOrderEqual([c3, c2, c1], [c1, c2, c3])
|
381 |
self.assertTopoOrderEqual([c3, c2, c1], [c2, c1, c3])
|
382 |
|
383 |
def test_topo_reorder_multiple_children(self): |
384 |
c1, c2, c3 = self.make_commits([[1], [2, 1], [3, 1]]) |
385 |
|
386 |
# c2 and c3 are FIFO but c1 moves to the end.
|
387 |
self.assertTopoOrderEqual([c3, c2, c1], [c3, c2, c1])
|
388 |
self.assertTopoOrderEqual([c3, c2, c1], [c3, c1, c2])
|
389 |
self.assertTopoOrderEqual([c3, c2, c1], [c1, c3, c2])
|
390 |
|
391 |
self.assertTopoOrderEqual([c2, c3, c1], [c2, c3, c1])
|
392 |
self.assertTopoOrderEqual([c2, c3, c1], [c2, c1, c3])
|
393 |
self.assertTopoOrderEqual([c2, c3, c1], [c1, c2, c3])
|
394 |
|
395 |
def test_out_of_order_children(self): |
396 |
c1, c2, c3, c4, c5 = self.make_commits(
|
397 |
[[1], [2, 1], [3, 2], [4, 1], [5, 3, 4]], |
398 |
times=[2, 1, 3, 4, 5]) |
399 |
self.assertWalkYields([c5, c4, c3, c1, c2], [c5.id])
|
400 |
self.assertWalkYields([c5, c4, c3, c2, c1], [c5.id], order=ORDER_TOPO)
|
401 |
|
402 |
def test_out_of_order_with_exclude(self): |
403 |
# Create the following graph:
|
404 |
# c1-------x2---m6
|
405 |
# \ /
|
406 |
# \-y3--y4-/--y5
|
407 |
# Due to skew, y5 is the oldest commit.
|
408 |
c1, x2, y3, y4, y5, m6 = self.make_commits(
|
409 |
[[1], [2, 1], [3, 1], [4, 3], [5, 4], [6, 2, 4]], |
410 |
times=[2, 3, 4, 5, 1, 6]) |
411 |
self.assertWalkYields([m6, y4, y3, x2, c1], [m6.id])
|
412 |
# Ensure that c1..y4 get excluded even though they're popped from the
|
413 |
# priority queue long before y5.
|
414 |
self.assertWalkYields([m6, x2], [m6.id], exclude=[y5.id])
|
415 |
|
416 |
def test_empty_walk(self): |
417 |
c1, c2, c3 = self.make_linear_commits(3) |
418 |
self.assertWalkYields([], [c3.id], exclude=[c3.id])
|
419 |
|
420 |
|
421 |
class WalkEntryTest(TestCase): |
422 |
|
423 |
def setUp(self): |
424 |
super(WalkEntryTest, self).setUp() |
425 |
self.store = MemoryObjectStore()
|
426 |
|
427 |
def make_commits(self, commit_spec, **kwargs): |
428 |
times = kwargs.pop('times', [])
|
429 |
attrs = kwargs.pop('attrs', {})
|
430 |
for i, t in enumerate(times): |
431 |
attrs.setdefault(i + 1, {})['commit_time'] = t |
432 |
return build_commit_graph(self.store, commit_spec, attrs=attrs, |
433 |
**kwargs) |
434 |
|
435 |
def make_linear_commits(self, num_commits, **kwargs): |
436 |
commit_spec = [] |
437 |
for i in range(1, num_commits + 1): |
438 |
c = [i] |
439 |
if i > 1: |
440 |
c.append(i - 1)
|
441 |
commit_spec.append(c) |
442 |
return self.make_commits(commit_spec, **kwargs) |
443 |
|
444 |
def test_all_changes(self): |
445 |
# Construct a commit with 2 files in different subdirectories.
|
446 |
blob_a = make_object(Blob, data=b'a')
|
447 |
blob_b = make_object(Blob, data=b'b')
|
448 |
c1 = self.make_linear_commits(
|
449 |
1,
|
450 |
trees={1: [(b'x/a', blob_a), (b'y/b', blob_b)]}, |
451 |
)[0]
|
452 |
|
453 |
# Get the WalkEntry for the commit.
|
454 |
walker = Walker(self.store, c1.id)
|
455 |
walker_entry = list(walker)[0] |
456 |
changes = walker_entry.changes() |
457 |
|
458 |
# Compare the changes with the expected values.
|
459 |
entry_a = (b'x/a', F, blob_a.id)
|
460 |
entry_b = (b'y/b', F, blob_b.id)
|
461 |
self.assertEqual(
|
462 |
[TreeChange.add(entry_a), |
463 |
TreeChange.add(entry_b)], |
464 |
changes, |
465 |
) |
466 |
|
467 |
def test_all_with_merge(self): |
468 |
blob_a = make_object(Blob, data=b'a')
|
469 |
blob_a2 = make_object(Blob, data=b'a2')
|
470 |
blob_b = make_object(Blob, data=b'b')
|
471 |
blob_b2 = make_object(Blob, data=b'b2')
|
472 |
x1, y2, m3 = self.make_commits(
|
473 |
[[1], [2], [3, 1, 2]], |
474 |
trees={1: [(b'x/a', blob_a)], |
475 |
2: [(b'y/b', blob_b)], |
476 |
3: [(b'x/a', blob_a2), (b'y/b', blob_b2)]}) |
477 |
|
478 |
# Get the WalkEntry for the merge commit.
|
479 |
walker = Walker(self.store, m3.id)
|
480 |
entries = list(walker)
|
481 |
walker_entry = entries[0]
|
482 |
self.assertEqual(walker_entry.commit.id, m3.id)
|
483 |
changes = walker_entry.changes() |
484 |
self.assertEqual(2, len(changes)) |
485 |
|
486 |
entry_a = (b'x/a', F, blob_a.id)
|
487 |
entry_a2 = (b'x/a', F, blob_a2.id)
|
488 |
entry_b = (b'y/b', F, blob_b.id)
|
489 |
entry_b2 = (b'y/b', F, blob_b2.id)
|
490 |
self.assertEqual(
|
491 |
[[TreeChange(CHANGE_MODIFY, entry_a, entry_a2), |
492 |
TreeChange.add(entry_a2)], |
493 |
[TreeChange.add(entry_b2), |
494 |
TreeChange(CHANGE_MODIFY, entry_b, entry_b2)]], |
495 |
changes, |
496 |
) |
497 |
|
498 |
def test_filter_changes(self): |
499 |
# Construct a commit with 2 files in different subdirectories.
|
500 |
blob_a = make_object(Blob, data=b'a')
|
501 |
blob_b = make_object(Blob, data=b'b')
|
502 |
c1 = self.make_linear_commits(
|
503 |
1,
|
504 |
trees={1: [(b'x/a', blob_a), (b'y/b', blob_b)]}, |
505 |
)[0]
|
506 |
|
507 |
# Get the WalkEntry for the commit.
|
508 |
walker = Walker(self.store, c1.id)
|
509 |
walker_entry = list(walker)[0] |
510 |
changes = walker_entry.changes(path_prefix=b'x')
|
511 |
|
512 |
# Compare the changes with the expected values.
|
513 |
entry_a = (b'a', F, blob_a.id)
|
514 |
self.assertEqual(
|
515 |
[TreeChange.add(entry_a)], |
516 |
changes, |
517 |
) |
518 |
|
519 |
def test_filter_with_merge(self): |
520 |
blob_a = make_object(Blob, data=b'a')
|
521 |
blob_a2 = make_object(Blob, data=b'a2')
|
522 |
blob_b = make_object(Blob, data=b'b')
|
523 |
blob_b2 = make_object(Blob, data=b'b2')
|
524 |
x1, y2, m3 = self.make_commits(
|
525 |
[[1], [2], [3, 1, 2]], |
526 |
trees={1: [(b'x/a', blob_a)], |
527 |
2: [(b'y/b', blob_b)], |
528 |
3: [(b'x/a', blob_a2), (b'y/b', blob_b2)]}) |
529 |
|
530 |
# Get the WalkEntry for the merge commit.
|
531 |
walker = Walker(self.store, m3.id)
|
532 |
entries = list(walker)
|
533 |
walker_entry = entries[0]
|
534 |
self.assertEqual(walker_entry.commit.id, m3.id)
|
535 |
changes = walker_entry.changes(b'x')
|
536 |
self.assertEqual(1, len(changes)) |
537 |
|
538 |
entry_a = (b'a', F, blob_a.id)
|
539 |
entry_a2 = (b'a', F, blob_a2.id)
|
540 |
self.assertEqual(
|
541 |
[[TreeChange(CHANGE_MODIFY, entry_a, entry_a2)]], |
542 |
changes, |
543 |
) |