135
133
rev_info = spec.in_history(branch)
136
134
self.assertEqual(rev_info, (None, 'A'))
138
def test_invalid_revno(self):
139
self.build_tree(['branch1/', 'branch1/file'])
140
wt = self.make_branch_and_tree('branch1')
142
wt.commit('first commit', rev_id='r1')
143
wt.commit('second commit', rev_id='r2')
145
# In the future -20 will probably just fall back to 0
146
# but for now, we want to make sure it raises the right error
147
self.assertRaises(errors.InvalidRevisionSpec,
148
RevisionSpec('-20').in_history, wt.branch)
149
self.assertRaises(errors.InvalidRevisionSpec,
150
RevisionSpec('10').in_history, wt.branch)
152
self.assertRaises(errors.InvalidRevisionSpec,
153
RevisionSpec('revno:-20').in_history, wt.branch)
154
self.assertRaises(errors.InvalidRevisionSpec,
155
RevisionSpec('revno:10').in_history, wt.branch)
156
self.assertRaises(errors.InvalidRevisionSpec,
157
RevisionSpec('revno:a').in_history, wt.branch)
160
# Basic class, which just creates a really basic set of revisions
161
class TestRevisionSpec(TestCaseWithTransport):
164
super(TestRevisionSpec, self).setUp()
166
self.tree = self.make_branch_and_tree('tree')
167
self.build_tree(['tree/a'])
169
self.tree.commit('a', rev_id='r1')
171
self.tree2 = self.tree.bzrdir.sprout('tree2').open_workingtree()
172
self.tree2.commit('alt', rev_id='alt_r2')
174
self.tree.branch.repository.fetch(self.tree2.branch.repository,
175
revision_id='alt_r2')
176
self.tree.set_pending_merges(['alt_r2'])
177
self.tree.commit('second', rev_id='r2')
179
def get_in_history(self, revision_spec):
180
return RevisionSpec(revision_spec).in_history(self.tree.branch)
182
def assertInHistoryIs(self, exp_revno, exp_revision_id, revision_spec):
183
rev_info = self.get_in_history(revision_spec)
184
self.assertEqual(exp_revno, rev_info.revno,
185
'Revision spec: %s returned wrong revno: %s != %s'
186
% (revision_spec, exp_revno, rev_info.revno))
187
self.assertEqual(exp_revision_id, rev_info.rev_id,
188
'Revision spec: %s returned wrong revision id:'
190
% (revision_spec, exp_revision_id, rev_info.rev_id))
192
def assertInvalid(self, revision_spec, extra='', real_spec=None):
193
if real_spec is None:
194
real_spec = revision_spec
196
self.get_in_history(revision_spec)
197
except errors.InvalidRevisionSpec, e:
198
self.assertEqual(real_spec, e.spec)
199
self.assertEqual(extra, e.extra)
201
self.fail('Expected InvalidRevisionSpec to be raised for %s'
205
class TestRevisionSpec_int(TestRevisionSpec):
207
def test_positive(self):
208
self.assertInHistoryIs(0, None, '0')
209
self.assertInHistoryIs(1, 'r1', '1')
210
self.assertInHistoryIs(2, 'r2', '2')
212
self.assertInvalid('3', real_spec=3)
214
def test_negative(self):
215
self.assertInHistoryIs(2, 'r2', '-1')
216
self.assertInHistoryIs(1, 'r1', '-2')
218
# XXX: This is probably bogus, and will change to Invalid in the future
219
self.assertInHistoryIs(0, None, '-3')
222
# TODO: In the future, a negative number that is too large
223
# may be translated into the first revision
224
self.assertInvalid('-4', real_spec=-4)
227
class TestRevisionSpec_revno(TestRevisionSpec):
229
def test_positive(self):
230
self.assertInHistoryIs(0, None, 'revno:0')
231
self.assertInHistoryIs(1, 'r1', 'revno:1')
232
self.assertInHistoryIs(2, 'r2', 'revno:2')
234
self.assertInvalid('revno:3')
236
def test_negative(self):
237
self.assertInHistoryIs(2, 'r2', 'revno:-1')
238
self.assertInHistoryIs(1, 'r1', 'revno:-2')
240
# XXX: This is probably bogus, and will change to Invalid in the future
241
self.assertInHistoryIs(0, None, 'revno:-3')
243
# TODO: In the future, a negative number that is too large
244
# may be translated into the first revision
245
self.assertInvalid('revno:-4')
247
def test_invalid_number(self):
248
# Get the right exception text
251
except ValueError, e:
253
self.assertInvalid('revno:X', extra='; ' + str(e))
255
def test_missing_number_and_branch(self):
256
self.assertInvalid('revno::',
257
extra='; cannot have an empty revno and no branch')
259
def test_invalid_number_with_branch(self):
262
except ValueError, e:
264
self.assertInvalid('revno:X:tree2', extra='; ' + str(e))
266
def test_with_branch(self):
267
# Passing a URL overrides the supplied branch path
268
revinfo = self.get_in_history('revno:2:tree2')
269
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
270
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
271
self.assertEqual(2, revinfo.revno)
272
self.assertEqual('alt_r2', revinfo.rev_id)
274
def test_with_url(self):
275
url = self.get_url() + '/tree2'
276
revinfo = self.get_in_history('revno:2:%s' % (url,))
277
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
278
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
279
self.assertEqual(2, revinfo.revno)
280
self.assertEqual('alt_r2', revinfo.rev_id)
282
def test_negative_with_url(self):
283
url = self.get_url() + '/tree2'
284
revinfo = self.get_in_history('revno:-1:%s' % (url,))
285
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
286
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
287
self.assertEqual(2, revinfo.revno)
288
self.assertEqual('alt_r2', revinfo.rev_id)
290
def test_invalid_branch(self):
291
self.assertRaises(errors.NotBranchError,
292
self.get_in_history, 'revno:-1:tree3')
294
def test_invalid_revno_in_branch(self):
295
self.tree.commit('three', rev_id='r3')
296
self.assertInvalid('revno:3:tree2')
299
class TestRevisionSpec_revid(TestRevisionSpec):
301
def test_in_history(self):
302
# We should be able to access revisions that are directly
304
self.assertInHistoryIs(1, 'r1', 'revid:r1')
305
self.assertInHistoryIs(2, 'r2', 'revid:r2')
307
def test_missing(self):
308
self.assertInvalid('revid:r3')
310
def test_merged(self):
311
"""We can reach revisions in the ancestry"""
312
self.assertInHistoryIs(None, 'alt_r2', 'revid:alt_r2')
314
def test_not_here(self):
315
self.tree2.commit('alt third', rev_id='alt_r3')
316
# It exists in tree2, but not in tree
317
self.assertInvalid('revid:alt_r3')
319
def test_in_repository(self):
320
"""We can get any revision id in the repository"""
321
# XXX: This may change in the future, but for now, it is true
322
self.tree2.commit('alt third', rev_id='alt_r3')
323
self.tree.branch.repository.fetch(self.tree2.branch.repository,
324
revision_id='alt_r3')
325
self.assertInHistoryIs(None, 'alt_r3', 'revid:alt_r3')
328
class TestRevisionSpec_last(TestRevisionSpec):
330
def test_positive(self):
331
self.assertInHistoryIs(2, 'r2', 'last:1')
332
self.assertInHistoryIs(1, 'r1', 'last:2')
333
self.assertInHistoryIs(0, None, 'last:3')
335
def test_empty(self):
336
self.assertInHistoryIs(2, 'r2', 'last:')
338
def test_negative(self):
339
self.assertInvalid('last:-1',
340
extra='; you must supply a positive value')
342
def test_missing(self):
343
self.assertInvalid('last:4')
345
def test_no_history(self):
346
tree = self.make_branch_and_tree('tree3')
348
self.assertRaises(errors.NoCommits,
349
RevisionSpec('last:').in_history, tree.branch)
351
def test_not_a_number(self):
354
except ValueError, e:
356
self.assertInvalid('last:Y', extra='; ' + str(e))
359
class TestRevisionSpec_before(TestRevisionSpec):
362
self.assertInHistoryIs(1, 'r1', 'before:2')
363
self.assertInHistoryIs(1, 'r1', 'before:-1')
365
def test_before_one(self):
366
self.assertInHistoryIs(0, None, 'before:1')
368
def test_before_none(self):
369
# before: will stop at None
370
self.assertInHistoryIs(0, None, 'before:0')
372
def test_revid(self):
373
self.assertInHistoryIs(1, 'r1', 'before:revid:r2')
376
self.assertInHistoryIs(1, 'r1', 'before:last:1')
378
def test_alt_revid(self):
379
# XXX: before will return entries from other histories, but not
380
# the entry previous to them. Is this intentional, it seems like a bug?
381
self.assertInHistoryIs(None, 'alt_r2', 'before:revid:alt_r2')
384
class TestRevisionSpec_tag(TestRevisionSpec):
386
def test_invalid(self):
387
self.assertInvalid('tag:foo', extra='; tag: namespace registered,'
388
' but not implemented')