Merge lp:~jelmer/bzr/fix-version-info-revision into lp:bzr

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Martin Packman
Approved revision: no longer in the source branch.
Merged at revision: 6418
Proposed branch: lp:~jelmer/bzr/fix-version-info-revision
Merge into: lp:bzr
Diff against target: 510 lines (+156/-117)
4 files modified
bzrlib/cmd_version_info.py (+1/-1)
bzrlib/tests/blackbox/test_version_info.py (+4/-4)
bzrlib/tests/test_version_info.py (+139/-103)
bzrlib/version_info_formats/__init__.py (+12/-9)
To merge this branch: bzr merge lp:~jelmer/bzr/fix-version-info-revision
Reviewer Review Type Date Requested Status
Martin Packman (community) Approve
Review via email: mp+87135@code.launchpad.net

Commit message

Fix -r argument for 'bzr version-info' to actually use specified tree everywhere.

Description of the change

Follow up to one of my earlier patches, which introduced a -r argument to "bzr version-info". This makes us not mix the working tree with the tree from the -r revision.

Split up version info tests into smaller tests.

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Fix looks sensible, as do test refactorings which pass locally.

+ builder = RioVersionInfoBuilder(wt.branch, working_tree=wt,
+ **kwargs)

Would fit on one line now it's dedented.

+ builder = RioVersionInfoBuilder(wt.branch, working_tree=wt,
+ **kwargs)

Likewise.

+ new_stanzas = list(read_stanzas(
+ StringIO(stanza[key].encode('utf8'))))

This would too, or at least should be slightly less oddly offset.

review: Approve
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/cmd_version_info.py'
2--- bzrlib/cmd_version_info.py 2011-12-19 13:23:58 +0000
3+++ bzrlib/cmd_version_info.py 2012-01-03 13:16:29 +0000
4@@ -107,11 +107,11 @@
5 if format is None:
6 format = version_info_formats.format_registry.get()
7
8- wt = None
9 try:
10 wt = workingtree.WorkingTree.open_containing(location)[0]
11 except errors.NoWorkingTree:
12 b = branch.Branch.open(location)
13+ wt = None
14 else:
15 b = wt.branch
16
17
18=== modified file 'bzrlib/tests/blackbox/test_version_info.py'
19--- bzrlib/tests/blackbox/test_version_info.py 2011-10-31 15:49:35 +0000
20+++ bzrlib/tests/blackbox/test_version_info.py 2012-01-03 13:16:29 +0000
21@@ -18,10 +18,10 @@
22
23 import os
24
25-from bzrlib.revision import NULL_REVISION
26 from bzrlib.tests import TestCaseWithTransport
27 from bzrlib.version_info_formats import VersionInfoBuilder
28
29+
30 class TestVersionInfo(TestCaseWithTransport):
31
32 def test_invalid_format(self):
33@@ -163,16 +163,16 @@
34
35 def test_non_ascii(self):
36 """Test that we can output non-ascii data"""
37-
38+
39 commit_message = u'Non-ascii message with character not in latin-1: \u1234'
40-
41+
42 tree = self.make_branch_and_tree('.')
43 self.build_tree(['a_file'])
44 tree.add('a_file')
45 tree.commit(commit_message)
46 out, err = self.run_bzr(
47 ['version-info', '--include-history'], encoding='latin-1')
48-
49+
50 self.assertContainsString(out, commit_message.encode('utf-8'))
51
52 def test_revision(self):
53
54=== modified file 'bzrlib/tests/test_version_info.py'
55--- bzrlib/tests/test_version_info.py 2011-06-14 17:01:15 +0000
56+++ bzrlib/tests/test_version_info.py 2012-01-03 13:16:29 +0000
57@@ -35,7 +35,7 @@
58 from bzrlib.version_info_formats.format_python import PythonVersionInfoBuilder
59
60
61-class TestVersionInfo(TestCaseWithTransport):
62+class VersionInfoTestCase(TestCaseWithTransport):
63
64 def create_branch(self):
65 wt = self.make_branch_and_tree('branch')
66@@ -72,6 +72,9 @@
67
68 return wt
69
70+
71+class TestVersionInfoRio(VersionInfoTestCase):
72+
73 def test_rio_null(self):
74 wt = self.make_branch_and_tree('branch')
75
76@@ -91,32 +94,37 @@
77 val = sio.getvalue()
78 self.assertContainsRe(val, 'revno: 1.1.1')
79
80- def test_rio_version_text(self):
81+ def regen_text(self, wt, **kwargs):
82+ sio = StringIO()
83+ builder = RioVersionInfoBuilder(wt.branch, working_tree=wt, **kwargs)
84+ builder.generate(sio)
85+ val = sio.getvalue()
86+ return val
87+
88+ def test_simple(self):
89 wt = self.create_branch()
90
91- def regen(**kwargs):
92- sio = StringIO()
93- builder = RioVersionInfoBuilder(wt.branch, working_tree=wt,
94- **kwargs)
95- builder.generate(sio)
96- val = sio.getvalue()
97- return val
98-
99- val = regen()
100+ val = self.regen_text(wt)
101 self.assertContainsRe(val, 'build-date:')
102 self.assertContainsRe(val, 'date:')
103 self.assertContainsRe(val, 'revno: 3')
104 self.assertContainsRe(val, 'revision-id: r3')
105
106- val = regen(check_for_clean=True)
107+ def test_clean(self):
108+ wt = self.create_branch()
109+ val = self.regen_text(wt, check_for_clean=True)
110 self.assertContainsRe(val, 'clean: True')
111
112+ def test_no_clean(self):
113+ wt = self.create_branch()
114 self.build_tree(['branch/c'])
115- val = regen(check_for_clean=True)
116+ val = self.regen_text(wt, check_for_clean=True)
117 self.assertContainsRe(val, 'clean: False')
118- os.remove('branch/c')
119-
120- val = regen(include_revision_history=True)
121+
122+ def test_history(self):
123+ wt = self.create_branch()
124+
125+ val = self.regen_text(wt, include_revision_history=True)
126 self.assertContainsRe(val, 'id: r1')
127 self.assertContainsRe(val, 'message: a')
128 self.assertContainsRe(val, 'id: r2')
129@@ -124,6 +132,15 @@
130 self.assertContainsRe(val, 'id: r3')
131 self.assertContainsRe(val, 'message: \xc3\xa52') # utf8 encoding '\xe5'
132
133+ def regen(self, wt, **kwargs):
134+ sio = StringIO()
135+ builder = RioVersionInfoBuilder(wt.branch, working_tree=wt, **kwargs)
136+ builder.generate(sio)
137+ sio.seek(0)
138+ stanzas = list(read_stanzas(sio))
139+ self.assertEqual(1, len(stanzas))
140+ return stanzas[0]
141+
142 def test_rio_version_hook(self):
143 def update_stanza(rev, stanza):
144 stanza.add('bla', 'bloe')
145@@ -131,86 +148,93 @@
146 'revision', update_stanza, None)
147 wt = self.create_branch()
148
149- def regen(**kwargs):
150- sio = StringIO()
151- builder = RioVersionInfoBuilder(wt.branch, working_tree=wt,
152- **kwargs)
153- builder.generate(sio)
154- sio.seek(0)
155- stanzas = list(read_stanzas(sio))
156- self.assertEqual(1, len(stanzas))
157- return stanzas[0]
158-
159- stanza = regen()
160+ stanza = self.regen(wt)
161 self.assertEqual(['bloe'], stanza.get_all('bla'))
162
163- def test_rio_version(self):
164+ def get_one_stanza(self, stanza, key):
165+ new_stanzas = list(read_stanzas(StringIO(stanza[key].encode('utf8'))))
166+ self.assertEqual(1, len(new_stanzas))
167+ return new_stanzas[0]
168+
169+ def test_build_date(self):
170 wt = self.create_branch()
171-
172- def regen(**kwargs):
173- sio = StringIO()
174- builder = RioVersionInfoBuilder(wt.branch, working_tree=wt,
175- **kwargs)
176- builder.generate(sio)
177- sio.seek(0)
178- stanzas = list(read_stanzas(sio))
179- self.assertEqual(1, len(stanzas))
180- return stanzas[0]
181-
182- def get_one_stanza(stanza, key):
183- new_stanzas = list(read_stanzas(
184- StringIO(stanza[key].encode('utf8'))))
185- self.assertEqual(1, len(new_stanzas))
186- return new_stanzas[0]
187-
188- stanza = regen()
189+ stanza = self.regen(wt)
190 self.assertTrue('date' in stanza)
191 self.assertTrue('build-date' in stanza)
192 self.assertEqual(['3'], stanza.get_all('revno'))
193 self.assertEqual(['r3'], stanza.get_all('revision-id'))
194
195- stanza = regen(check_for_clean=True)
196- self.assertEqual(['True'], stanza.get_all('clean'))
197-
198+ def test_not_clean(self):
199+ wt = self.create_branch()
200 self.build_tree(['branch/c'])
201- stanza = regen(check_for_clean=True, include_file_revisions=True)
202+ stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
203 self.assertEqual(['False'], stanza.get_all('clean'))
204
205+ def test_file_revisions(self):
206+ wt = self.create_branch()
207+ self.build_tree(['branch/c'])
208+ stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
209 # This assumes it's being run against a tree that does not update the
210 # root revision on every commit.
211- file_rev_stanza = get_one_stanza(stanza, 'file-revisions')
212+ file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
213 self.assertEqual(['', 'a', 'b', 'c'], file_rev_stanza.get_all('path'))
214 self.assertEqual(['r1', 'r3', 'r2', 'unversioned'],
215 file_rev_stanza.get_all('revision'))
216- os.remove('branch/c')
217
218- stanza = regen(include_revision_history=True)
219- revision_stanza = get_one_stanza(stanza, 'revisions')
220+ def test_revision_history(self):
221+ wt = self.create_branch()
222+ stanza = self.regen(wt, include_revision_history=True)
223+ revision_stanza = self.get_one_stanza(stanza, 'revisions')
224 self.assertEqual(['r1', 'r2', 'r3'], revision_stanza.get_all('id'))
225 self.assertEqual(['a', 'b', u'\xe52'], revision_stanza.get_all('message'))
226 self.assertEqual(3, len(revision_stanza.get_all('date')))
227
228+ def test_file_revisions_with_rename(self):
229 # a was modified, so it should show up modified again
230+ wt = self.create_branch()
231 self.build_tree(['branch/a', 'branch/c'])
232 wt.add('c')
233 wt.rename_one('b', 'd')
234- stanza = regen(check_for_clean=True, include_file_revisions=True)
235- file_rev_stanza = get_one_stanza(stanza, 'file-revisions')
236+ stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
237+ file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
238 self.assertEqual(['', 'a', 'b', 'c', 'd'],
239 file_rev_stanza.get_all('path'))
240 self.assertEqual(['r1', 'modified', 'renamed to d', 'new',
241 'renamed from b'],
242 file_rev_stanza.get_all('revision'))
243
244+ def test_file_revisions_with_removal(self):
245+ wt = self.create_branch()
246+ self.build_tree(['branch/a', 'branch/c'])
247+ wt.add('c')
248+ wt.rename_one('b', 'd')
249+
250 wt.commit('modified', rev_id='r4')
251+
252 wt.remove(['c', 'd'])
253 os.remove('branch/d')
254- stanza = regen(check_for_clean=True, include_file_revisions=True)
255- file_rev_stanza = get_one_stanza(stanza, 'file-revisions')
256+ stanza = self.regen(wt, check_for_clean=True, include_file_revisions=True)
257+ file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
258 self.assertEqual(['', 'a', 'c', 'd'], file_rev_stanza.get_all('path'))
259 self.assertEqual(['r1', 'r4', 'unversioned', 'removed'],
260 file_rev_stanza.get_all('revision'))
261
262+ def test_revision(self):
263+ wt = self.create_branch()
264+ self.build_tree(['branch/a', 'branch/c'])
265+ wt.add('c')
266+ wt.rename_one('b', 'd')
267+
268+ stanza = self.regen(wt, check_for_clean=True,
269+ include_file_revisions=True, revision_id=wt.last_revision())
270+ file_rev_stanza = self.get_one_stanza(stanza, 'file-revisions')
271+ self.assertEqual(['', 'a', 'b'], file_rev_stanza.get_all('path'))
272+ self.assertEqual(['r1', 'r3', 'r2'],
273+ file_rev_stanza.get_all('revision'))
274+
275+
276+class PythonVersionInfoTests(VersionInfoTestCase):
277+
278 def test_python_null(self):
279 wt = self.make_branch_and_tree('branch')
280
281@@ -231,45 +255,45 @@
282 val = sio.getvalue()
283 self.assertContainsRe(val, "'revno': '1.1.1'")
284
285+ def regen(self, wt, **kwargs):
286+ """Create a test module, import and return it"""
287+ outf = open('test_version_information.py', 'wb')
288+ try:
289+ builder = PythonVersionInfoBuilder(wt.branch, working_tree=wt,
290+ **kwargs)
291+ builder.generate(outf)
292+ finally:
293+ outf.close()
294+ module_info = imp.find_module('test_version_information',
295+ [os.getcwdu()])
296+ tvi = imp.load_module('tvi', *module_info)
297+ # Make sure the module isn't cached
298+ sys.modules.pop('tvi', None)
299+ sys.modules.pop('test_version_information', None)
300+ # Delete the compiled versions, because we are generating
301+ # a new file fast enough that python doesn't detect it
302+ # needs to recompile, and using sleep() just makes the
303+ # test slow
304+ if os.path.exists('test_version_information.pyc'):
305+ os.remove('test_version_information.pyc')
306+ if os.path.exists('test_version_information.pyo'):
307+ os.remove('test_version_information.pyo')
308+ return tvi
309+
310 def test_python_version(self):
311 wt = self.create_branch()
312
313- def regen(**kwargs):
314- """Create a test module, import and return it"""
315- outf = open('test_version_information.py', 'wb')
316- try:
317- builder = PythonVersionInfoBuilder(wt.branch, working_tree=wt,
318- **kwargs)
319- builder.generate(outf)
320- finally:
321- outf.close()
322- module_info = imp.find_module('test_version_information',
323- [os.getcwdu()])
324- tvi = imp.load_module('tvi', *module_info)
325- # Make sure the module isn't cached
326- sys.modules.pop('tvi', None)
327- sys.modules.pop('test_version_information', None)
328- # Delete the compiled versions, because we are generating
329- # a new file fast enough that python doesn't detect it
330- # needs to recompile, and using sleep() just makes the
331- # test slow
332- if os.path.exists('test_version_information.pyc'):
333- os.remove('test_version_information.pyc')
334- if os.path.exists('test_version_information.pyo'):
335- os.remove('test_version_information.pyo')
336- return tvi
337-
338- tvi = regen()
339+ tvi = self.regen(wt)
340 self.assertEqual('3', tvi.version_info['revno'])
341 self.assertEqual('r3', tvi.version_info['revision_id'])
342 self.assertTrue(tvi.version_info.has_key('date'))
343 self.assertEqual(None, tvi.version_info['clean'])
344
345- tvi = regen(check_for_clean=True)
346+ tvi = self.regen(wt, check_for_clean=True)
347 self.assertEqual(True, tvi.version_info['clean'])
348
349 self.build_tree(['branch/c'])
350- tvi = regen(check_for_clean=True, include_file_revisions=True)
351+ tvi = self.regen(wt, check_for_clean=True, include_file_revisions=True)
352 self.assertEqual(False, tvi.version_info['clean'])
353 self.assertEqual(['', 'a', 'b', 'c'],
354 sorted(tvi.file_revisions.keys()))
355@@ -278,7 +302,7 @@
356 self.assertEqual('unversioned', tvi.file_revisions['c'])
357 os.remove('branch/c')
358
359- tvi = regen(include_revision_history=True)
360+ tvi = self.regen(wt, include_revision_history=True)
361
362 rev_info = [(rev, message) for rev, message, timestamp, timezone
363 in tvi.revisions]
364@@ -288,7 +312,7 @@
365 self.build_tree(['branch/a', 'branch/c'])
366 wt.add('c')
367 wt.rename_one('b', 'd')
368- tvi = regen(check_for_clean=True, include_file_revisions=True)
369+ tvi = self.regen(wt, check_for_clean=True, include_file_revisions=True)
370 self.assertEqual(['', 'a', 'b', 'c', 'd'],
371 sorted(tvi.file_revisions.keys()))
372 self.assertEqual('modified', tvi.file_revisions['a'])
373@@ -299,13 +323,16 @@
374 wt.commit('modified', rev_id='r4')
375 wt.remove(['c', 'd'])
376 os.remove('branch/d')
377- tvi = regen(check_for_clean=True, include_file_revisions=True)
378+ tvi = self.regen(wt, check_for_clean=True, include_file_revisions=True)
379 self.assertEqual(['', 'a', 'c', 'd'],
380 sorted(tvi.file_revisions.keys()))
381 self.assertEqual('r4', tvi.file_revisions['a'])
382 self.assertEqual('unversioned', tvi.file_revisions['c'])
383 self.assertEqual('removed', tvi.file_revisions['d'])
384
385+
386+class CustomVersionInfoTests(VersionInfoTestCase):
387+
388 def test_custom_null(self):
389 sio = StringIO()
390 wt = self.make_branch_and_tree('branch')
391@@ -328,32 +355,41 @@
392 builder.generate(sio)
393 self.assertEquals("1.1.1 revid: o2", sio.getvalue())
394
395- def test_custom_version_text(self):
396+ def regen(self, wt, tpl, **kwargs):
397+ sio = StringIO()
398+ builder = CustomVersionInfoBuilder(wt.branch, working_tree=wt,
399+ template=tpl, **kwargs)
400+ builder.generate(sio)
401+ val = sio.getvalue()
402+ return val
403+
404+ def test_build_date(self):
405 wt = self.create_branch()
406
407- def regen(tpl, **kwargs):
408- sio = StringIO()
409- builder = CustomVersionInfoBuilder(wt.branch, working_tree=wt,
410- template=tpl, **kwargs)
411- builder.generate(sio)
412- val = sio.getvalue()
413- return val
414-
415- val = regen('build-date: "{build_date}"\ndate: "{date}"')
416+ val = self.regen(wt, 'build-date: "{build_date}"\ndate: "{date}"')
417 self.assertContainsRe(val, 'build-date: "[0-9-+: ]+"')
418 self.assertContainsRe(val, 'date: "[0-9-+: ]+"')
419
420- val = regen('revno: {revno}')
421+ def test_revno(self):
422+ wt = self.create_branch()
423+ val = self.regen(wt, 'revno: {revno}')
424 self.assertEqual(val, 'revno: 3')
425
426- val = regen('revision-id: {revision_id}')
427+ def test_revision_id(self):
428+ wt = self.create_branch()
429+ val = self.regen(wt, 'revision-id: {revision_id}')
430 self.assertEqual(val, 'revision-id: r3')
431
432- val = regen('clean: {clean}', check_for_clean=True)
433+ def test_clean(self):
434+ wt = self.create_branch()
435+ val = self.regen(wt, 'clean: {clean}', check_for_clean=True)
436 self.assertEqual(val, 'clean: 1')
437
438+ def test_not_clean(self):
439+ wt = self.create_branch()
440+
441 self.build_tree(['branch/c'])
442- val = regen('clean: {clean}', check_for_clean=True)
443+ val = self.regen(wt, 'clean: {clean}', check_for_clean=True)
444 self.assertEqual(val, 'clean: 0')
445 os.remove('branch/c')
446
447
448=== modified file 'bzrlib/version_info_formats/__init__.py'
449--- bzrlib/version_info_formats/__init__.py 2011-12-19 13:23:58 +0000
450+++ bzrlib/version_info_formats/__init__.py 2012-01-03 13:16:29 +0000
451@@ -70,7 +70,6 @@
452 :param revision_id: Revision id to print version for (optional)
453 """
454 self._branch = branch
455- self._working_tree = working_tree
456 self._check = check_for_clean
457 self._include_history = include_revision_history
458 self._include_file_revs = include_file_revisions
459@@ -80,19 +79,27 @@
460 self._file_revisions = {}
461 self._revision_id = revision_id
462
463+ if self._revision_id is None:
464+ self._tree = working_tree
465+ self._working_tree = working_tree
466+ else:
467+ self._tree = self._branch.repository.revision_tree(self._revision_id)
468+ # the working tree is not relevant if an explicit revision was specified
469+ self._working_tree = None
470+
471 def _extract_file_revisions(self):
472 """Extract the working revisions for all files"""
473
474 # Things seem clean if we never look :)
475 self._clean = True
476
477- if self._working_tree is not None:
478+ if self._working_tree is self._tree:
479 basis_tree = self._working_tree.basis_tree()
480 # TODO: jam 20070215 The working tree should actually be locked at
481 # a higher level, but this will do for now.
482 self._working_tree.lock_read()
483 else:
484- basis_tree = self._branch.basis_tree()
485+ basis_tree = self._branch.repository.revision_tree(self._revision_id)
486
487 basis_tree.lock_read()
488 try:
489@@ -100,7 +107,7 @@
490 for info in basis_tree.list_files(include_root=True):
491 self._file_revisions[info[0]] = info[-1].revision
492
493- if not self._check or self._working_tree is None:
494+ if not self._check or self._working_tree is not self._tree:
495 return
496
497 delta = self._working_tree.changes_from(basis_tree,
498@@ -140,11 +147,7 @@
499 def _iter_revision_history(self):
500 """Find the messages for all revisions in history."""
501
502- # Unfortunately, there is no WorkingTree.revision_history
503- if self._working_tree is not None:
504- last_rev = self._working_tree.last_revision()
505- else:
506- last_rev = self._branch.last_revision()
507+ last_rev = self._get_revision_id()
508
509 repository = self._branch.repository
510 repository.lock_read()