diff options
Diffstat (limited to 'bzrlib/tests/blackbox/test_info.py')
-rw-r--r-- | bzrlib/tests/blackbox/test_info.py | 1583 |
1 files changed, 1583 insertions, 0 deletions
diff --git a/bzrlib/tests/blackbox/test_info.py b/bzrlib/tests/blackbox/test_info.py new file mode 100644 index 0000000..12d0000 --- /dev/null +++ b/bzrlib/tests/blackbox/test_info.py @@ -0,0 +1,1583 @@ +# Copyright (C) 2006-2012 Canonical Ltd +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +"""Tests for the info command of bzr.""" + +import shutil +import sys + +from bzrlib import ( + branch, + bzrdir, + controldir, + errors, + info, + osutils, + tests, + upgrade, + urlutils, + ) +from bzrlib.tests.matchers import ContainsNoVfsCalls +from bzrlib.transport import memory + + +class TestInfo(tests.TestCaseWithTransport): + + def setUp(self): + super(TestInfo, self).setUp() + self._repo_strings = "2a" + + def test_info_non_existing(self): + self.vfs_transport_factory = memory.MemoryServer + location = self.get_url() + out, err = self.run_bzr('info '+location, retcode=3) + self.assertEqual(out, '') + self.assertEqual(err, 'bzr: ERROR: Not a branch: "%s".\n' % location) + + def test_info_empty_controldir(self): + self.make_bzrdir('ctrl') + out, err = self.run_bzr('info ctrl') + self.assertEquals(out, + 'Empty control directory (format: 2a or pack-0.92)\n' + 'Location:\n' + ' control directory: ctrl\n') + self.assertEquals(err, '') + + def test_info_empty_controldir_verbose(self): + self.make_bzrdir('ctrl') + out, err = self.run_bzr('info -v ctrl') + self.assertEqualDiff(out, + 'Empty control directory (format: 2a or pack-0.92)\n' + 'Location:\n' + ' control directory: ctrl\n\n' + 'Format:\n' + ' control: Meta directory format 1\n\n' + 'Control directory:\n' + ' 0 branches\n') + self.assertEquals(err, '') + + def test_info_dangling_branch_reference(self): + br = self.make_branch('target') + br.create_checkout('from', lightweight=True) + shutil.rmtree('target') + out, err = self.run_bzr('info from') + self.assertEquals(out, + 'Dangling branch reference (format: 2a or pack-0.92)\n' + 'Location:\n' + ' control directory: from\n' + ' checkout of branch: target\n') + self.assertEquals(err, '') + + def test_info_standalone(self): + transport = self.get_transport() + + # Create initial standalone branch + tree1 = self.make_branch_and_tree('standalone', 'knit') + self.build_tree(['standalone/a']) + tree1.add('a') + branch1 = tree1.branch + + out, err = self.run_bzr('info standalone') + self.assertEqualDiff( +"""Standalone tree (format: knit) +Location: + branch root: standalone +""", out) + self.assertEqual('', err) + + # Standalone branch - verbose mode + out, err = self.run_bzr('info standalone -v') + self.assertEqualDiff( +"""Standalone tree (format: knit) +Location: + branch root: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: Knit repository format 1 + +Control directory: + 1 branches + +In the working tree: + 0 unchanged + 0 modified + 1 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 0 revisions + +Repository: + 0 revisions +""", out) + self.assertEqual('', err) + + # Standalone branch - really verbose mode + out, err = self.run_bzr('info standalone -vv') + self.assertEqualDiff( +"""Standalone tree (format: knit) +Location: + branch root: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: Knit repository format 1 + +Control directory: + 1 branches + +In the working tree: + 0 unchanged + 0 modified + 1 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 0 revisions + 0 committers + +Repository: + 0 revisions +""", out) + self.assertEqual('', err) + tree1.commit('commit one') + rev = branch1.repository.get_revision(branch1.last_revision()) + datestring_first = osutils.format_date(rev.timestamp, rev.timezone) + + # Branch standalone with push location + branch2 = branch1.bzrdir.sprout('branch').open_branch() + branch2.set_push_location(branch1.bzrdir.root_transport.base) + + out, err = self.run_bzr('info branch') + self.assertEqualDiff( +"""Standalone tree (format: knit) +Location: + branch root: branch + +Related branches: + push branch: standalone + parent branch: standalone +""", out) + self.assertEqual('', err) + + out, err = self.run_bzr('info branch --verbose') + self.assertEqualDiff( +"""Standalone tree (format: knit) +Location: + branch root: branch + +Related branches: + push branch: standalone + parent branch: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: Knit repository format 1 + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Branch and bind to standalone, needs upgrade to metadir + # (creates backup as unknown) + branch1.bzrdir.sprout('bound') + knit1_format = controldir.format_registry.make_bzrdir('knit') + upgrade.upgrade('bound', knit1_format) + branch3 = controldir.ControlDir.open('bound').open_branch() + branch3.bind(branch1) + bound_tree = branch3.bzrdir.open_workingtree() + out, err = self.run_bzr('info -v bound') + self.assertEqualDiff( +"""Checkout (format: knit) +Location: + checkout root: bound + checkout of branch: standalone + +Related branches: + parent branch: standalone + +Format: + control: Meta directory format 1 + working tree: %s + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (bound_tree._format.get_format_description(), + branch3._format.get_format_description(), + branch3.repository._format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Checkout standalone (same as above, but does not have parent set) + branch4 = controldir.ControlDir.create_branch_convenience('checkout', + format=knit1_format) + branch4.bind(branch1) + branch4.bzrdir.open_workingtree().update() + out, err = self.run_bzr('info checkout --verbose') + self.assertEqualDiff( +"""Checkout (format: knit) +Location: + checkout root: checkout + checkout of branch: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: %s + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (branch4.repository._format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Lightweight checkout (same as above, different branch and repository) + tree5 = branch1.create_checkout('lightcheckout', lightweight=True) + branch5 = tree5.branch + out, err = self.run_bzr('info -v lightcheckout') + if "metaweave" in controldir.format_registry: + format_description = "knit or metaweave" + else: + format_description = "knit" + self.assertEqualDiff( +"""Lightweight checkout (format: %s) +Location: + light checkout root: lightcheckout + checkout of branch: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: Knit repository format 1 + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (format_description, datestring_first, datestring_first,), out) + self.assertEqual('', err) + + # Update initial standalone branch + self.build_tree(['standalone/b']) + tree1.add('b') + tree1.commit('commit two') + rev = branch1.repository.get_revision(branch1.last_revision()) + datestring_last = osutils.format_date(rev.timestamp, rev.timezone) + + # Out of date branched standalone branch will not be detected + out, err = self.run_bzr('info -v branch') + self.assertEqualDiff( +"""Standalone tree (format: knit) +Location: + branch root: branch + +Related branches: + push branch: standalone + parent branch: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: Knit repository format 1 + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Out of date bound branch + out, err = self.run_bzr('info -v bound') + self.assertEqualDiff( +"""Checkout (format: knit) +Location: + checkout root: bound + checkout of branch: standalone + +Related branches: + parent branch: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: %s + +Control directory: + 1 branches + +Branch is out of date: missing 1 revision. + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (branch3.repository._format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Out of date checkout + out, err = self.run_bzr('info -v checkout') + self.assertEqualDiff( +"""Checkout (format: knit) +Location: + checkout root: checkout + checkout of branch: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: %s + +Control directory: + 1 branches + +Branch is out of date: missing 1 revision. + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (branch4.repository._format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Out of date lightweight checkout + out, err = self.run_bzr('info lightcheckout --verbose') + self.assertEqualDiff( +"""Lightweight checkout (format: %s) +Location: + light checkout root: lightcheckout + checkout of branch: standalone + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: Branch format 5 + repository: Knit repository format 1 + +Control directory: + 1 branches + +Working tree is out of date: missing 1 revision. + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 2 revisions + 0 days old + first revision: %s + latest revision: %s + +Repository: + 2 revisions +""" % (format_description, datestring_first, datestring_last,), out) + self.assertEqual('', err) + + def test_info_standalone_no_tree(self): + # create standalone branch without a working tree + format = controldir.format_registry.make_bzrdir('default') + branch = self.make_branch('branch') + repo = branch.repository + out, err = self.run_bzr('info branch -v') + self.assertEqualDiff( +"""Standalone branch (format: %s) +Location: + branch root: branch + +Format: + control: Meta directory format 1 + branch: %s + repository: %s + +Control directory: + 1 branches + +Branch history: + 0 revisions + +Repository: + 0 revisions +""" % (info.describe_format(repo.bzrdir, repo, branch, None), + format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + def test_info_shared_repository(self): + format = controldir.format_registry.make_bzrdir('knit') + transport = self.get_transport() + + # Create shared repository + repo = self.make_repository('repo', shared=True, format=format) + repo.set_make_working_trees(False) + out, err = self.run_bzr('info -v repo') + self.assertEqualDiff( +"""Shared repository (format: dirstate or dirstate-tags or knit) +Location: + shared repository: %s + +Format: + control: Meta directory format 1 + repository: %s + +Control directory: + 0 branches + +Repository: + 0 revisions +""" % ('repo', format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + # Create branch inside shared repository + repo.bzrdir.root_transport.mkdir('branch') + branch1 = controldir.ControlDir.create_branch_convenience( + 'repo/branch', format=format) + out, err = self.run_bzr('info -v repo/branch') + self.assertEqualDiff( +"""Repository branch (format: dirstate or knit) +Location: + shared repository: repo + repository branch: repo/branch + +Format: + control: Meta directory format 1 + branch: %s + repository: %s + +Control directory: + 1 branches + +Branch history: + 0 revisions + +Repository: + 0 revisions +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + # Create lightweight checkout + transport.mkdir('tree') + transport.mkdir('tree/lightcheckout') + tree2 = branch1.create_checkout('tree/lightcheckout', + lightweight=True) + branch2 = tree2.branch + self.assertCheckoutStatusOutput('-v tree/lightcheckout', tree2, + shared_repo=repo, repo_branch=branch1, verbose=True) + + # Create normal checkout + tree3 = branch1.create_checkout('tree/checkout') + self.assertCheckoutStatusOutput('tree/checkout --verbose', tree3, + verbose=True, + light_checkout=False, repo_branch=branch1) + # Update lightweight checkout + self.build_tree(['tree/lightcheckout/a']) + tree2.add('a') + tree2.commit('commit one') + rev = repo.get_revision(branch2.last_revision()) + datestring_first = osutils.format_date(rev.timestamp, rev.timezone) + out, err = self.run_bzr('info tree/lightcheckout --verbose') + self.assertEqualDiff( +"""Lightweight checkout (format: %s) +Location: + light checkout root: tree/lightcheckout + checkout of branch: repo/branch + shared repository: repo + +Format: + control: Meta directory format 1 + working tree: Working tree format 6 + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (self._repo_strings, format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Out of date checkout + out, err = self.run_bzr('info -v tree/checkout') + self.assertEqualDiff( +"""Checkout (format: unnamed) +Location: + checkout root: tree/checkout + checkout of branch: repo/branch + +Format: + control: Meta directory format 1 + working tree: Working tree format 6 + branch: %s + repository: %s + +Control directory: + 1 branches + +Branch is out of date: missing 1 revision. + +In the working tree: + 0 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 0 revisions + +Repository: + 0 revisions +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + # Update checkout + tree3.update() + self.build_tree(['tree/checkout/b']) + tree3.add('b') + out, err = self.run_bzr('info tree/checkout --verbose') + self.assertEqualDiff( +"""Checkout (format: unnamed) +Location: + checkout root: tree/checkout + checkout of branch: repo/branch + +Format: + control: Meta directory format 1 + working tree: Working tree format 6 + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 1 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + tree3.commit('commit two') + + # Out of date lightweight checkout + rev = repo.get_revision(branch1.last_revision()) + datestring_last = osutils.format_date(rev.timestamp, rev.timezone) + out, err = self.run_bzr('info tree/lightcheckout --verbose') + self.assertEqualDiff( +"""Lightweight checkout (format: %s) +Location: + light checkout root: tree/lightcheckout + checkout of branch: repo/branch + shared repository: repo + +Format: + control: Meta directory format 1 + working tree: Working tree format 6 + branch: %s + repository: %s + +Control directory: + 1 branches + +Working tree is out of date: missing 1 revision. + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 2 revisions + 0 days old + first revision: %s + latest revision: %s + +Repository: + 2 revisions +""" % (self._repo_strings, format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + datestring_first, datestring_last, + ), out) + self.assertEqual('', err) + + # Show info about shared branch + out, err = self.run_bzr('info repo/branch --verbose') + self.assertEqualDiff( +"""Repository branch (format: dirstate or knit) +Location: + shared repository: repo + repository branch: repo/branch + +Format: + control: Meta directory format 1 + branch: %s + repository: %s + +Control directory: + 1 branches + +Branch history: + 2 revisions + 0 days old + first revision: %s + latest revision: %s + +Repository: + 2 revisions +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + datestring_first, datestring_last, + ), out) + self.assertEqual('', err) + + # Show info about repository with revisions + out, err = self.run_bzr('info -v repo') + self.assertEqualDiff( +"""Shared repository (format: dirstate or dirstate-tags or knit) +Location: + shared repository: repo + +Format: + control: Meta directory format 1 + repository: %s + +Control directory: + 0 branches + +Repository: + 2 revisions +""" % (format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + def test_info_shared_repository_with_trees(self): + format = controldir.format_registry.make_bzrdir('knit') + transport = self.get_transport() + + # Create shared repository with working trees + repo = self.make_repository('repo', shared=True, format=format) + repo.set_make_working_trees(True) + out, err = self.run_bzr('info -v repo') + self.assertEqualDiff( +"""Shared repository with trees (format: dirstate or dirstate-tags or knit) +Location: + shared repository: repo + +Format: + control: Meta directory format 1 + repository: %s + +Control directory: + 0 branches + +Create working tree for new branches inside the repository. + +Repository: + 0 revisions +""" % (format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + # Create two branches + repo.bzrdir.root_transport.mkdir('branch1') + branch1 = controldir.ControlDir.create_branch_convenience('repo/branch1', + format=format) + branch2 = branch1.bzrdir.sprout('repo/branch2').open_branch() + + # Empty first branch + out, err = self.run_bzr('info repo/branch1 --verbose') + self.assertEqualDiff( +"""Repository tree (format: knit) +Location: + shared repository: repo + repository branch: repo/branch1 + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 0 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 0 revisions + +Repository: + 0 revisions +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + # Update first branch + self.build_tree(['repo/branch1/a']) + tree1 = branch1.bzrdir.open_workingtree() + tree1.add('a') + tree1.commit('commit one') + rev = repo.get_revision(branch1.last_revision()) + datestring_first = osutils.format_date(rev.timestamp, rev.timezone) + out, err = self.run_bzr('info -v repo/branch1') + self.assertEqualDiff( +"""Repository tree (format: knit) +Location: + shared repository: repo + repository branch: repo/branch1 + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Out of date second branch + out, err = self.run_bzr('info repo/branch2 --verbose') + self.assertEqualDiff( +"""Repository tree (format: knit) +Location: + shared repository: repo + repository branch: repo/branch2 + +Related branches: + parent branch: repo/branch1 + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 0 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 0 revisions + +Repository: + 1 revision +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + # Update second branch + tree2 = branch2.bzrdir.open_workingtree() + tree2.pull(branch1) + out, err = self.run_bzr('info -v repo/branch2') + self.assertEqualDiff( +"""Repository tree (format: knit) +Location: + shared repository: repo + repository branch: repo/branch2 + +Related branches: + parent branch: repo/branch1 + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 1 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 1 revision + 0 days old + first revision: %s + latest revision: %s + +Repository: + 1 revision +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + datestring_first, datestring_first, + ), out) + self.assertEqual('', err) + + # Show info about repository with revisions + out, err = self.run_bzr('info -v repo') + self.assertEqualDiff( +"""Shared repository with trees (format: dirstate or dirstate-tags or knit) +Location: + shared repository: repo + +Format: + control: Meta directory format 1 + repository: %s + +Control directory: + 0 branches + +Create working tree for new branches inside the repository. + +Repository: + 1 revision +""" % (format.repository_format.get_format_description(), + ), + out) + self.assertEqual('', err) + + def test_info_shared_repository_with_tree_in_root(self): + format = controldir.format_registry.make_bzrdir('knit') + transport = self.get_transport() + + # Create shared repository with working trees + repo = self.make_repository('repo', shared=True, format=format) + repo.set_make_working_trees(True) + out, err = self.run_bzr('info -v repo') + self.assertEqualDiff( +"""Shared repository with trees (format: dirstate or dirstate-tags or knit) +Location: + shared repository: repo + +Format: + control: Meta directory format 1 + repository: %s + +Control directory: + 0 branches + +Create working tree for new branches inside the repository. + +Repository: + 0 revisions +""" % (format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + # Create branch in root of repository + control = repo.bzrdir + branch = control.create_branch() + control.create_workingtree() + out, err = self.run_bzr('info -v repo') + self.assertEqualDiff( +"""Repository tree (format: knit) +Location: + shared repository: repo + repository branch: repo + +Format: + control: Meta directory format 1 + working tree: Working tree format 3 + branch: %s + repository: %s + +Control directory: + 1 branches + +In the working tree: + 0 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 0 revisions + +Repository: + 0 revisions +""" % (format.get_branch_format().get_format_description(), + format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + def test_info_repository_hook(self): + format = controldir.format_registry.make_bzrdir('knit') + def repo_info(repo, stats, outf): + outf.write("more info\n") + info.hooks.install_named_hook('repository', repo_info, None) + # Create shared repository with working trees + repo = self.make_repository('repo', shared=True, format=format) + out, err = self.run_bzr('info -v repo') + self.assertEqualDiff( +"""Shared repository with trees (format: dirstate or dirstate-tags or knit) +Location: + shared repository: repo + +Format: + control: Meta directory format 1 + repository: %s + +Control directory: + 0 branches + +Create working tree for new branches inside the repository. + +Repository: + 0 revisions +more info +""" % (format.repository_format.get_format_description(), + ), out) + self.assertEqual('', err) + + def test_info_unshared_repository_with_colocated_branches(self): + format = controldir.format_registry.make_bzrdir('development-colo') + transport = self.get_transport() + + # Create unshared repository + repo = self.make_repository('repo', shared=False, format=format) + repo.set_make_working_trees(True) + repo.bzrdir.create_branch(name='foo') + out, err = self.run_bzr('info repo') + self.assertEqualDiff( +"""Unshared repository with trees and colocated branches (format: development-colo) +Location: + repository: repo +""", out) + self.assertEqual('', err) + + def assertCheckoutStatusOutput(self, + command_string, lco_tree, shared_repo=None, + repo_branch=None, + tree_locked=False, + branch_locked=False, repo_locked=False, + verbose=False, + light_checkout=True, + checkout_root=None): + """Check the output of info in a checkout. + + This is not quite a mirror of the info code: rather than using the + tree being examined to predict output, it uses a bunch of flags which + allow us, the test writers, to document what *should* be present in + the output. Removing this separation would remove the value of the + tests. + + :param path: the path to the light checkout. + :param lco_tree: the tree object for the light checkout. + :param shared_repo: A shared repository is in use, expect that in + the output. + :param repo_branch: A branch in a shared repository for non light + checkouts. + :param tree_locked: If true, expect the tree to be locked. + :param branch_locked: If true, expect the branch to be locked. + :param repo_locked: If true, expect the repository to be locked. + Note that the lco_tree.branch.repository is inspected, and if is not + actually locked then this parameter is overridden. This is because + pack repositories do not have any public API for obtaining an + exclusive repository wide lock. + :param verbose: verbosity level: 2 or higher to show committers + """ + def friendly_location(url): + path = urlutils.unescape_for_display(url, 'ascii') + try: + return osutils.relpath(osutils.getcwd(), path) + except errors.PathNotChild: + return path + + if tree_locked: + # We expect this to fail because of locking errors. + # (A write-locked file cannot be read-locked + # in the different process -- either on win32 or on linux). + # This should be removed when the locking errors are fixed. + self.expectFailure('OS locks are exclusive ' + 'for different processes (Bug #174055)', + self.run_bzr_subprocess, + 'info ' + command_string) + out, err = self.run_bzr('info %s' % command_string) + description = { + (True, True): 'Lightweight checkout', + (True, False): 'Repository checkout', + (False, True): 'Lightweight checkout', + (False, False): 'Checkout', + }[(shared_repo is not None, light_checkout)] + format = {True: self._repo_strings, + False: 'unnamed'}[light_checkout] + if repo_locked: + repo_locked = lco_tree.branch.repository.get_physical_lock_status() + if repo_locked or branch_locked or tree_locked: + def locked_message(a_bool): + if a_bool: + return 'locked' + else: + return 'unlocked' + expected_lock_output = ( + "\n" + "Lock status:\n" + " working tree: %s\n" + " branch: %s\n" + " repository: %s\n" % ( + locked_message(tree_locked), + locked_message(branch_locked), + locked_message(repo_locked))) + else: + expected_lock_output = '' + tree_data = '' + extra_space = '' + if light_checkout: + tree_data = (" light checkout root: %s\n" % + friendly_location(lco_tree.bzrdir.root_transport.base)) + extra_space = ' ' + if lco_tree.branch.get_bound_location() is not None: + tree_data += ("%s checkout root: %s\n" % (extra_space, + friendly_location(lco_tree.branch.bzrdir.root_transport.base))) + if shared_repo is not None: + branch_data = ( + " checkout of branch: %s\n" + " shared repository: %s\n" % + (friendly_location(repo_branch.bzrdir.root_transport.base), + friendly_location(shared_repo.bzrdir.root_transport.base))) + elif repo_branch is not None: + branch_data = ( + "%s checkout of branch: %s\n" % + (extra_space, + friendly_location(repo_branch.bzrdir.root_transport.base))) + else: + branch_data = (" checkout of branch: %s\n" % + lco_tree.branch.bzrdir.root_transport.base) + + if verbose >= 2: + verbose_info = ' 0 committers\n' + else: + verbose_info = '' + + self.assertEqualDiff( +"""%s (format: %s) +Location: +%s%s +Format: + control: Meta directory format 1 + working tree: %s + branch: %s + repository: %s +%s +Control directory: + 1 branches + +In the working tree: + 0 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories + +Branch history: + 0 revisions +%s +Repository: + 0 revisions +""" % (description, + format, + tree_data, + branch_data, + lco_tree._format.get_format_description(), + lco_tree.branch._format.get_format_description(), + lco_tree.branch.repository._format.get_format_description(), + expected_lock_output, + verbose_info, + ), out) + self.assertEqual('', err) + + def test_info_locking(self): + transport = self.get_transport() + # Create shared repository with a branch + repo = self.make_repository('repo', shared=True, + format=bzrdir.BzrDirMetaFormat1()) + repo.set_make_working_trees(False) + repo.bzrdir.root_transport.mkdir('branch') + repo_branch = controldir.ControlDir.create_branch_convenience( + 'repo/branch', format=bzrdir.BzrDirMetaFormat1()) + # Do a heavy checkout + transport.mkdir('tree') + transport.mkdir('tree/checkout') + co_branch = controldir.ControlDir.create_branch_convenience( + 'tree/checkout', format=bzrdir.BzrDirMetaFormat1()) + co_branch.bind(repo_branch) + # Do a light checkout of the heavy one + transport.mkdir('tree/lightcheckout') + lco_dir = bzrdir.BzrDirMetaFormat1().initialize('tree/lightcheckout') + lco_dir.set_branch_reference(co_branch) + lco_dir.create_workingtree() + lco_tree = lco_dir.open_workingtree() + + # Test all permutations of locking the working tree, branch and repository + # W B R + + # U U U + self.assertCheckoutStatusOutput('-v tree/lightcheckout', lco_tree, + repo_branch=repo_branch, + verbose=True, light_checkout=True) + # U U L + lco_tree.branch.repository.lock_write() + try: + self.assertCheckoutStatusOutput('-v tree/lightcheckout', + lco_tree, repo_branch=repo_branch, + repo_locked=True, verbose=True, light_checkout=True) + finally: + lco_tree.branch.repository.unlock() + # U L L + lco_tree.branch.lock_write() + try: + self.assertCheckoutStatusOutput('-v tree/lightcheckout', + lco_tree, + branch_locked=True, + repo_locked=True, + repo_branch=repo_branch, + verbose=True) + finally: + lco_tree.branch.unlock() + # L L L + lco_tree.lock_write() + try: + self.assertCheckoutStatusOutput('-v tree/lightcheckout', + lco_tree, repo_branch=repo_branch, + tree_locked=True, + branch_locked=True, + repo_locked=True, + verbose=True) + finally: + lco_tree.unlock() + # L L U + lco_tree.lock_write() + lco_tree.branch.repository.unlock() + try: + self.assertCheckoutStatusOutput('-v tree/lightcheckout', + lco_tree, repo_branch=repo_branch, + tree_locked=True, + branch_locked=True, + verbose=True) + finally: + lco_tree.branch.repository.lock_write() + lco_tree.unlock() + # L U U + lco_tree.lock_write() + lco_tree.branch.unlock() + try: + self.assertCheckoutStatusOutput('-v tree/lightcheckout', + lco_tree, repo_branch=repo_branch, + tree_locked=True, + verbose=True) + finally: + lco_tree.branch.lock_write() + lco_tree.unlock() + # L U L + lco_tree.lock_write() + lco_tree.branch.unlock() + lco_tree.branch.repository.lock_write() + try: + self.assertCheckoutStatusOutput('-v tree/lightcheckout', + lco_tree, repo_branch=repo_branch, + tree_locked=True, + repo_locked=True, + verbose=True) + finally: + lco_tree.branch.repository.unlock() + lco_tree.branch.lock_write() + lco_tree.unlock() + # U L U + lco_tree.branch.lock_write() + lco_tree.branch.repository.unlock() + try: + self.assertCheckoutStatusOutput('-v tree/lightcheckout', + lco_tree, repo_branch=repo_branch, + branch_locked=True, + verbose=True) + finally: + lco_tree.branch.repository.lock_write() + lco_tree.branch.unlock() + + if sys.platform == 'win32': + self.knownFailure('Win32 cannot run "bzr info"' + ' when the tree is locked.') + + def test_info_stacked(self): + # We have a mainline + trunk_tree = self.make_branch_and_tree('mainline', + format='1.6') + trunk_tree.commit('mainline') + # and a branch from it which is stacked + new_dir = trunk_tree.bzrdir.sprout('newbranch', stacked=True) + out, err = self.run_bzr('info newbranch') + self.assertEqual( +"""Standalone tree (format: 1.6) +Location: + branch root: newbranch + +Related branches: + parent branch: mainline + stacked on: mainline +""", out) + self.assertEqual("", err) + + def test_info_revinfo_optional(self): + tree = self.make_branch_and_tree('.') + def last_revision_info(self): + raise errors.UnsupportedOperation(last_revision_info, self) + self.overrideAttr( + branch.Branch, "last_revision_info", last_revision_info) + out, err = self.run_bzr('info -v .') + self.assertEqual( +"""Standalone tree (format: 2a) +Location: + branch root: . + +Format: + control: Meta directory format 1 + working tree: Working tree format 6 + branch: Branch format 7 + repository: Repository format 2a - rich roots, group compression and chk inventories + +Control directory: + 1 branches + +In the working tree: + 0 unchanged + 0 modified + 0 added + 0 removed + 0 renamed + 0 unknown + 0 ignored + 0 versioned subdirectories +""", out) + self.assertEqual("", err) + + def test_info_shows_colocated_branches(self): + bzrdir = self.make_branch('.', format='development-colo').bzrdir + bzrdir.create_branch(name="colo1") + bzrdir.create_branch(name="colo2") + bzrdir.create_branch(name="colo3") + out, err = self.run_bzr('info -v .') + self.assertEqualDiff( +"""Standalone branch (format: development-colo) +Location: + branch root: . + +Format: + control: Meta directory format 1 with support for colocated branches + branch: Branch format 7 + repository: Repository format 2a - rich roots, group compression and chk inventories + +Control directory: + 4 branches + +Branch history: + 0 revisions + +Repository: + 0 revisions +""", out) + self.assertEqual("", err) + + +class TestSmartServerInfo(tests.TestCaseWithTransport): + + def test_simple_branch_info(self): + self.setup_smart_server_with_call_log() + t = self.make_branch_and_tree('branch') + self.build_tree_contents([('branch/foo', 'thecontents')]) + t.add("foo") + t.commit("message") + self.reset_smart_call_log() + out, err = self.run_bzr(['info', self.get_url('branch')]) + # This figure represent the amount of work to perform this use case. It + # is entirely ok to reduce this number if a test fails due to rpc_count + # being too low. If rpc_count increases, more network roundtrips have + # become necessary for this use case. Please do not adjust this number + # upwards without agreement from bzr's network support maintainers. + self.assertLength(10, self.hpss_calls) + self.assertLength(1, self.hpss_connections) + self.assertThat(self.hpss_calls, ContainsNoVfsCalls) + + def test_verbose_branch_info(self): + self.setup_smart_server_with_call_log() + t = self.make_branch_and_tree('branch') + self.build_tree_contents([('branch/foo', 'thecontents')]) + t.add("foo") + t.commit("message") + self.reset_smart_call_log() + out, err = self.run_bzr(['info', '-v', self.get_url('branch')]) + # This figure represent the amount of work to perform this use case. It + # is entirely ok to reduce this number if a test fails due to rpc_count + # being too low. If rpc_count increases, more network roundtrips have + # become necessary for this use case. Please do not adjust this number + # upwards without agreement from bzr's network support maintainers. + self.assertLength(14, self.hpss_calls) + self.assertLength(1, self.hpss_connections) + self.assertThat(self.hpss_calls, ContainsNoVfsCalls) |