1# Copyright (C) 2006-2012, 2016 Canonical Ltd 2# 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 2 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program; if not, write to the Free Software 15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 16 17 18"""Tests for the info command of bzr.""" 19 20import shutil 21import sys 22 23from breezy import ( 24 branch, 25 controldir, 26 errors, 27 info, 28 osutils, 29 tests, 30 upgrade, 31 urlutils, 32 ) 33from breezy.bzr import ( 34 bzrdir, 35 ) 36from breezy.transport import memory 37 38 39class TestInfo(tests.TestCaseWithTransport): 40 41 def setUp(self): 42 super(TestInfo, self).setUp() 43 self._repo_strings = "2a" 44 45 def test_info_non_existing(self): 46 self.vfs_transport_factory = memory.MemoryServer 47 location = self.get_url() 48 out, err = self.run_bzr('info ' + location, retcode=3) 49 self.assertEqual(out, '') 50 self.assertEqual(err, 'brz: ERROR: Not a branch: "%s".\n' % location) 51 52 def test_info_empty_controldir(self): 53 self.make_controldir('ctrl') 54 out, err = self.run_bzr('info ctrl') 55 self.assertEqual(out, 56 'Empty control directory (format: 2a)\n' 57 'Location:\n' 58 ' control directory: ctrl\n') 59 self.assertEqual(err, '') 60 61 def test_info_empty_controldir_verbose(self): 62 self.make_controldir('ctrl') 63 out, err = self.run_bzr('info -v ctrl') 64 self.assertEqualDiff(out, 65 'Empty control directory (format: 2a)\n' 66 'Location:\n' 67 ' control directory: ctrl\n\n' 68 'Format:\n' 69 ' control: Meta directory format 1\n\n' 70 'Control directory:\n' 71 ' 0 branches\n') 72 self.assertEqual(err, '') 73 74 def test_info_dangling_branch_reference(self): 75 br = self.make_branch('target') 76 br.create_checkout('from', lightweight=True) 77 shutil.rmtree('target') 78 out, err = self.run_bzr('info from') 79 self.assertEqual(out, 80 'Dangling branch reference (format: 2a)\n' 81 'Location:\n' 82 ' control directory: from\n' 83 ' checkout of branch: target\n') 84 self.assertEqual(err, '') 85 86 def test_info_colocated(self): 87 br = self.make_branch_and_tree('target', format='development-colo') 88 target = br.controldir.create_branch(name='dichtbij') 89 br.controldir.set_branch_reference(target) 90 out, err = self.run_bzr('info target') 91 self.assertEqual(out, 92 'Standalone tree (format: development-colo)\n' 93 'Location:\n' 94 ' light checkout root: target\n' 95 ' checkout of co-located branch: dichtbij\n') 96 self.assertEqual(err, '') 97 98 def test_info_standalone(self): 99 transport = self.get_transport() 100 101 # Create initial standalone branch 102 tree1 = self.make_branch_and_tree('standalone', 'knit') 103 self.build_tree(['standalone/a']) 104 tree1.add('a') 105 branch1 = tree1.branch 106 107 out, err = self.run_bzr('info standalone') 108 self.assertEqualDiff( 109 """Standalone tree (format: knit) 110Location: 111 branch root: standalone 112""", out) 113 self.assertEqual('', err) 114 115 # Standalone branch - verbose mode 116 out, err = self.run_bzr('info standalone -v') 117 self.assertEqualDiff( 118 """Standalone tree (format: knit) 119Location: 120 branch root: standalone 121 122Format: 123 control: Meta directory format 1 124 working tree: Working tree format 3 125 branch: Branch format 5 126 repository: Knit repository format 1 127 128Control directory: 129 1 branches 130 131In the working tree: 132 0 unchanged 133 0 modified 134 1 added 135 0 removed 136 0 renamed 137 0 copied 138 0 unknown 139 0 ignored 140 0 versioned subdirectories 141 142Branch history: 143 0 revisions 144 145Repository: 146 0 revisions 147""", out) 148 self.assertEqual('', err) 149 150 # Standalone branch - really verbose mode 151 out, err = self.run_bzr('info standalone -vv') 152 self.assertEqualDiff( 153 """Standalone tree (format: knit) 154Location: 155 branch root: standalone 156 157Format: 158 control: Meta directory format 1 159 working tree: Working tree format 3 160 branch: Branch format 5 161 repository: Knit repository format 1 162 163Control directory: 164 1 branches 165 166In the working tree: 167 0 unchanged 168 0 modified 169 1 added 170 0 removed 171 0 renamed 172 0 copied 173 0 unknown 174 0 ignored 175 0 versioned subdirectories 176 177Branch history: 178 0 revisions 179 0 committers 180 181Repository: 182 0 revisions 183""", out) 184 self.assertEqual('', err) 185 tree1.commit('commit one') 186 rev = branch1.repository.get_revision(branch1.last_revision()) 187 datestring_first = osutils.format_date(rev.timestamp, rev.timezone) 188 189 # Branch standalone with push location 190 branch2 = branch1.controldir.sprout('branch').open_branch() 191 branch2.set_push_location(branch1.controldir.root_transport.base) 192 193 out, err = self.run_bzr('info branch') 194 self.assertEqualDiff( 195 """Standalone tree (format: knit) 196Location: 197 branch root: branch 198 199Related branches: 200 push branch: standalone 201 parent branch: standalone 202""", out) 203 self.assertEqual('', err) 204 205 out, err = self.run_bzr('info branch --verbose') 206 self.assertEqualDiff( 207 """Standalone tree (format: knit) 208Location: 209 branch root: branch 210 211Related branches: 212 push branch: standalone 213 parent branch: standalone 214 215Format: 216 control: Meta directory format 1 217 working tree: Working tree format 3 218 branch: Branch format 5 219 repository: Knit repository format 1 220 221Control directory: 222 1 branches 223 224In the working tree: 225 1 unchanged 226 0 modified 227 0 added 228 0 removed 229 0 renamed 230 0 copied 231 0 unknown 232 0 ignored 233 0 versioned subdirectories 234 235Branch history: 236 1 revision 237 0 days old 238 first revision: %s 239 latest revision: %s 240 241Repository: 242 1 revision 243""" % (datestring_first, datestring_first, 244 ), out) 245 self.assertEqual('', err) 246 247 # Branch and bind to standalone, needs upgrade to metadir 248 # (creates backup as unknown) 249 branch1.controldir.sprout('bound') 250 knit1_format = controldir.format_registry.make_controldir('knit') 251 upgrade.upgrade('bound', knit1_format) 252 branch3 = controldir.ControlDir.open('bound').open_branch() 253 branch3.bind(branch1) 254 bound_tree = branch3.controldir.open_workingtree() 255 out, err = self.run_bzr('info -v bound') 256 self.assertEqualDiff( 257 """Checkout (format: knit) 258Location: 259 checkout root: bound 260 checkout of branch: standalone 261 262Related branches: 263 parent branch: standalone 264 265Format: 266 control: Meta directory format 1 267 working tree: %s 268 branch: %s 269 repository: %s 270 271Control directory: 272 1 branches 273 274In the working tree: 275 1 unchanged 276 0 modified 277 0 added 278 0 removed 279 0 renamed 280 0 copied 281 0 unknown 282 0 ignored 283 0 versioned subdirectories 284 285Branch history: 286 1 revision 287 0 days old 288 first revision: %s 289 latest revision: %s 290 291Repository: 292 1 revision 293""" % (bound_tree._format.get_format_description(), 294 branch3._format.get_format_description(), 295 branch3.repository._format.get_format_description(), 296 datestring_first, datestring_first, 297 ), out) 298 self.assertEqual('', err) 299 300 # Checkout standalone (same as above, but does not have parent set) 301 branch4 = controldir.ControlDir.create_branch_convenience('checkout', 302 format=knit1_format) 303 branch4.bind(branch1) 304 branch4.controldir.open_workingtree().update() 305 out, err = self.run_bzr('info checkout --verbose') 306 self.assertEqualDiff( 307 """Checkout (format: knit) 308Location: 309 checkout root: checkout 310 checkout of branch: standalone 311 312Format: 313 control: Meta directory format 1 314 working tree: Working tree format 3 315 branch: Branch format 5 316 repository: %s 317 318Control directory: 319 1 branches 320 321In the working tree: 322 1 unchanged 323 0 modified 324 0 added 325 0 removed 326 0 renamed 327 0 copied 328 0 unknown 329 0 ignored 330 0 versioned subdirectories 331 332Branch history: 333 1 revision 334 0 days old 335 first revision: %s 336 latest revision: %s 337 338Repository: 339 1 revision 340""" % (branch4.repository._format.get_format_description(), 341 datestring_first, datestring_first, 342 ), out) 343 self.assertEqual('', err) 344 345 # Lightweight checkout (same as above, different branch and repository) 346 tree5 = branch1.create_checkout('lightcheckout', lightweight=True) 347 branch5 = tree5.branch 348 out, err = self.run_bzr('info -v lightcheckout') 349 if "metaweave" in controldir.format_registry: 350 format_description = "knit or metaweave" 351 else: 352 format_description = "knit" 353 self.assertEqualDiff( 354 """Lightweight checkout (format: %s) 355Location: 356 light checkout root: lightcheckout 357 checkout of branch: standalone 358 359Format: 360 control: Meta directory format 1 361 working tree: Working tree format 3 362 branch: Branch format 5 363 repository: Knit repository format 1 364 365Control directory: 366 1 branches 367 368In the working tree: 369 1 unchanged 370 0 modified 371 0 added 372 0 removed 373 0 renamed 374 0 copied 375 0 unknown 376 0 ignored 377 0 versioned subdirectories 378 379Branch history: 380 1 revision 381 0 days old 382 first revision: %s 383 latest revision: %s 384 385Repository: 386 1 revision 387""" % (format_description, datestring_first, datestring_first,), out) 388 self.assertEqual('', err) 389 390 # Update initial standalone branch 391 self.build_tree(['standalone/b']) 392 tree1.add('b') 393 tree1.commit('commit two') 394 rev = branch1.repository.get_revision(branch1.last_revision()) 395 datestring_last = osutils.format_date(rev.timestamp, rev.timezone) 396 397 # Out of date branched standalone branch will not be detected 398 out, err = self.run_bzr('info -v branch') 399 self.assertEqualDiff( 400 """Standalone tree (format: knit) 401Location: 402 branch root: branch 403 404Related branches: 405 push branch: standalone 406 parent branch: standalone 407 408Format: 409 control: Meta directory format 1 410 working tree: Working tree format 3 411 branch: Branch format 5 412 repository: Knit repository format 1 413 414Control directory: 415 1 branches 416 417In the working tree: 418 1 unchanged 419 0 modified 420 0 added 421 0 removed 422 0 renamed 423 0 copied 424 0 unknown 425 0 ignored 426 0 versioned subdirectories 427 428Branch history: 429 1 revision 430 0 days old 431 first revision: %s 432 latest revision: %s 433 434Repository: 435 1 revision 436""" % (datestring_first, datestring_first, 437 ), out) 438 self.assertEqual('', err) 439 440 # Out of date bound branch 441 out, err = self.run_bzr('info -v bound') 442 self.assertEqualDiff( 443 """Checkout (format: knit) 444Location: 445 checkout root: bound 446 checkout of branch: standalone 447 448Related branches: 449 parent branch: standalone 450 451Format: 452 control: Meta directory format 1 453 working tree: Working tree format 3 454 branch: Branch format 5 455 repository: %s 456 457Control directory: 458 1 branches 459 460Branch is out of date: missing 1 revision. 461 462In the working tree: 463 1 unchanged 464 0 modified 465 0 added 466 0 removed 467 0 renamed 468 0 copied 469 0 unknown 470 0 ignored 471 0 versioned subdirectories 472 473Branch history: 474 1 revision 475 0 days old 476 first revision: %s 477 latest revision: %s 478 479Repository: 480 1 revision 481""" % (branch3.repository._format.get_format_description(), 482 datestring_first, datestring_first, 483 ), out) 484 self.assertEqual('', err) 485 486 # Out of date checkout 487 out, err = self.run_bzr('info -v checkout') 488 self.assertEqualDiff( 489 """Checkout (format: knit) 490Location: 491 checkout root: checkout 492 checkout of branch: standalone 493 494Format: 495 control: Meta directory format 1 496 working tree: Working tree format 3 497 branch: Branch format 5 498 repository: %s 499 500Control directory: 501 1 branches 502 503Branch is out of date: missing 1 revision. 504 505In the working tree: 506 1 unchanged 507 0 modified 508 0 added 509 0 removed 510 0 renamed 511 0 copied 512 0 unknown 513 0 ignored 514 0 versioned subdirectories 515 516Branch history: 517 1 revision 518 0 days old 519 first revision: %s 520 latest revision: %s 521 522Repository: 523 1 revision 524""" % (branch4.repository._format.get_format_description(), 525 datestring_first, datestring_first, 526 ), out) 527 self.assertEqual('', err) 528 529 # Out of date lightweight checkout 530 out, err = self.run_bzr('info lightcheckout --verbose') 531 self.assertEqualDiff( 532 """Lightweight checkout (format: %s) 533Location: 534 light checkout root: lightcheckout 535 checkout of branch: standalone 536 537Format: 538 control: Meta directory format 1 539 working tree: Working tree format 3 540 branch: Branch format 5 541 repository: Knit repository format 1 542 543Control directory: 544 1 branches 545 546Working tree is out of date: missing 1 revision. 547 548In the working tree: 549 1 unchanged 550 0 modified 551 0 added 552 0 removed 553 0 renamed 554 0 copied 555 0 unknown 556 0 ignored 557 0 versioned subdirectories 558 559Branch history: 560 2 revisions 561 0 days old 562 first revision: %s 563 latest revision: %s 564 565Repository: 566 2 revisions 567""" % (format_description, datestring_first, datestring_last,), out) 568 self.assertEqual('', err) 569 570 def test_info_standalone_no_tree(self): 571 # create standalone branch without a working tree 572 format = controldir.format_registry.make_controldir('default') 573 branch = self.make_branch('branch') 574 repo = branch.repository 575 out, err = self.run_bzr('info branch -v') 576 self.assertEqualDiff( 577 """Standalone branch (format: %s) 578Location: 579 branch root: branch 580 581Format: 582 control: Meta directory format 1 583 branch: %s 584 repository: %s 585 586Control directory: 587 1 branches 588 589Branch history: 590 0 revisions 591 592Repository: 593 0 revisions 594""" % (info.describe_format(repo.controldir, repo, branch, None), 595 format.get_branch_format().get_format_description(), 596 format.repository_format.get_format_description(), 597 ), out) 598 self.assertEqual('', err) 599 600 def test_info_shared_repository(self): 601 format = controldir.format_registry.make_controldir('knit') 602 transport = self.get_transport() 603 604 # Create shared repository 605 repo = self.make_repository('repo', shared=True, format=format) 606 repo.set_make_working_trees(False) 607 out, err = self.run_bzr('info -v repo') 608 self.assertEqualDiff( 609 """Shared repository (format: dirstate or dirstate-tags or knit) 610Location: 611 shared repository: %s 612 613Format: 614 control: Meta directory format 1 615 repository: %s 616 617Control directory: 618 0 branches 619 620Repository: 621 0 revisions 622""" % ('repo', format.repository_format.get_format_description(), 623 ), out) 624 self.assertEqual('', err) 625 626 # Create branch inside shared repository 627 repo.controldir.root_transport.mkdir('branch') 628 branch1 = controldir.ControlDir.create_branch_convenience( 629 'repo/branch', format=format) 630 out, err = self.run_bzr('info -v repo/branch') 631 self.assertEqualDiff( 632 """Repository branch (format: dirstate or knit) 633Location: 634 shared repository: repo 635 repository branch: repo/branch 636 637Format: 638 control: Meta directory format 1 639 branch: %s 640 repository: %s 641 642Control directory: 643 1 branches 644 645Branch history: 646 0 revisions 647 648Repository: 649 0 revisions 650""" % (format.get_branch_format().get_format_description(), 651 format.repository_format.get_format_description(), 652 ), out) 653 self.assertEqual('', err) 654 655 # Create lightweight checkout 656 transport.mkdir('tree') 657 transport.mkdir('tree/lightcheckout') 658 tree2 = branch1.create_checkout('tree/lightcheckout', 659 lightweight=True) 660 branch2 = tree2.branch 661 self.assertCheckoutStatusOutput('-v tree/lightcheckout', tree2, 662 shared_repo=repo, repo_branch=branch1, verbose=True) 663 664 # Create normal checkout 665 tree3 = branch1.create_checkout('tree/checkout') 666 self.assertCheckoutStatusOutput('tree/checkout --verbose', tree3, 667 verbose=True, 668 light_checkout=False, repo_branch=branch1) 669 # Update lightweight checkout 670 self.build_tree(['tree/lightcheckout/a']) 671 tree2.add('a') 672 tree2.commit('commit one') 673 rev = repo.get_revision(branch2.last_revision()) 674 datestring_first = osutils.format_date(rev.timestamp, rev.timezone) 675 out, err = self.run_bzr('info tree/lightcheckout --verbose') 676 self.assertEqualDiff( 677 """Lightweight checkout (format: %s) 678Location: 679 light checkout root: tree/lightcheckout 680 checkout of branch: repo/branch 681 shared repository: repo 682 683Format: 684 control: Meta directory format 1 685 working tree: Working tree format 6 686 branch: %s 687 repository: %s 688 689Control directory: 690 1 branches 691 692In the working tree: 693 1 unchanged 694 0 modified 695 0 added 696 0 removed 697 0 renamed 698 0 copied 699 0 unknown 700 0 ignored 701 0 versioned subdirectories 702 703Branch history: 704 1 revision 705 0 days old 706 first revision: %s 707 latest revision: %s 708 709Repository: 710 1 revision 711""" % (self._repo_strings, format.get_branch_format().get_format_description(), 712 format.repository_format.get_format_description(), 713 datestring_first, datestring_first, 714 ), out) 715 self.assertEqual('', err) 716 717 # Out of date checkout 718 out, err = self.run_bzr('info -v tree/checkout') 719 self.assertEqualDiff( 720 """Checkout (format: unnamed) 721Location: 722 checkout root: tree/checkout 723 checkout of branch: repo/branch 724 725Format: 726 control: Meta directory format 1 727 working tree: Working tree format 6 728 branch: %s 729 repository: %s 730 731Control directory: 732 1 branches 733 734Branch is out of date: missing 1 revision. 735 736In the working tree: 737 0 unchanged 738 0 modified 739 0 added 740 0 removed 741 0 renamed 742 0 copied 743 0 unknown 744 0 ignored 745 0 versioned subdirectories 746 747Branch history: 748 0 revisions 749 750Repository: 751 0 revisions 752""" % (format.get_branch_format().get_format_description(), 753 format.repository_format.get_format_description(), 754 ), out) 755 self.assertEqual('', err) 756 757 # Update checkout 758 tree3.update() 759 self.build_tree(['tree/checkout/b']) 760 tree3.add('b') 761 out, err = self.run_bzr('info tree/checkout --verbose') 762 self.assertEqualDiff( 763 """Checkout (format: unnamed) 764Location: 765 checkout root: tree/checkout 766 checkout of branch: repo/branch 767 768Format: 769 control: Meta directory format 1 770 working tree: Working tree format 6 771 branch: %s 772 repository: %s 773 774Control directory: 775 1 branches 776 777In the working tree: 778 1 unchanged 779 0 modified 780 1 added 781 0 removed 782 0 renamed 783 0 copied 784 0 unknown 785 0 ignored 786 0 versioned subdirectories 787 788Branch history: 789 1 revision 790 0 days old 791 first revision: %s 792 latest revision: %s 793 794Repository: 795 1 revision 796""" % (format.get_branch_format().get_format_description(), 797 format.repository_format.get_format_description(), 798 datestring_first, datestring_first, 799 ), out) 800 self.assertEqual('', err) 801 tree3.commit('commit two') 802 803 # Out of date lightweight checkout 804 rev = repo.get_revision(branch1.last_revision()) 805 datestring_last = osutils.format_date(rev.timestamp, rev.timezone) 806 out, err = self.run_bzr('info tree/lightcheckout --verbose') 807 self.assertEqualDiff( 808 """Lightweight checkout (format: %s) 809Location: 810 light checkout root: tree/lightcheckout 811 checkout of branch: repo/branch 812 shared repository: repo 813 814Format: 815 control: Meta directory format 1 816 working tree: Working tree format 6 817 branch: %s 818 repository: %s 819 820Control directory: 821 1 branches 822 823Working tree is out of date: missing 1 revision. 824 825In the working tree: 826 1 unchanged 827 0 modified 828 0 added 829 0 removed 830 0 renamed 831 0 copied 832 0 unknown 833 0 ignored 834 0 versioned subdirectories 835 836Branch history: 837 2 revisions 838 0 days old 839 first revision: %s 840 latest revision: %s 841 842Repository: 843 2 revisions 844""" % (self._repo_strings, format.get_branch_format().get_format_description(), 845 format.repository_format.get_format_description(), 846 datestring_first, datestring_last, 847 ), out) 848 self.assertEqual('', err) 849 850 # Show info about shared branch 851 out, err = self.run_bzr('info repo/branch --verbose') 852 self.assertEqualDiff( 853 """Repository branch (format: dirstate or knit) 854Location: 855 shared repository: repo 856 repository branch: repo/branch 857 858Format: 859 control: Meta directory format 1 860 branch: %s 861 repository: %s 862 863Control directory: 864 1 branches 865 866Branch history: 867 2 revisions 868 0 days old 869 first revision: %s 870 latest revision: %s 871 872Repository: 873 2 revisions 874""" % (format.get_branch_format().get_format_description(), 875 format.repository_format.get_format_description(), 876 datestring_first, datestring_last, 877 ), out) 878 self.assertEqual('', err) 879 880 # Show info about repository with revisions 881 out, err = self.run_bzr('info -v repo') 882 self.assertEqualDiff( 883 """Shared repository (format: dirstate or dirstate-tags or knit) 884Location: 885 shared repository: repo 886 887Format: 888 control: Meta directory format 1 889 repository: %s 890 891Control directory: 892 0 branches 893 894Repository: 895 2 revisions 896""" % (format.repository_format.get_format_description(), 897 ), out) 898 self.assertEqual('', err) 899 900 def test_info_shared_repository_with_trees(self): 901 format = controldir.format_registry.make_controldir('knit') 902 transport = self.get_transport() 903 904 # Create shared repository with working trees 905 repo = self.make_repository('repo', shared=True, format=format) 906 repo.set_make_working_trees(True) 907 out, err = self.run_bzr('info -v repo') 908 self.assertEqualDiff( 909 """Shared repository with trees (format: dirstate or dirstate-tags or knit) 910Location: 911 shared repository: repo 912 913Format: 914 control: Meta directory format 1 915 repository: %s 916 917Control directory: 918 0 branches 919 920Create working tree for new branches inside the repository. 921 922Repository: 923 0 revisions 924""" % (format.repository_format.get_format_description(), 925 ), out) 926 self.assertEqual('', err) 927 928 # Create two branches 929 repo.controldir.root_transport.mkdir('branch1') 930 branch1 = controldir.ControlDir.create_branch_convenience('repo/branch1', 931 format=format) 932 branch2 = branch1.controldir.sprout('repo/branch2').open_branch() 933 934 # Empty first branch 935 out, err = self.run_bzr('info repo/branch1 --verbose') 936 self.assertEqualDiff( 937 """Repository tree (format: knit) 938Location: 939 shared repository: repo 940 repository branch: repo/branch1 941 942Format: 943 control: Meta directory format 1 944 working tree: Working tree format 3 945 branch: %s 946 repository: %s 947 948Control directory: 949 1 branches 950 951In the working tree: 952 0 unchanged 953 0 modified 954 0 added 955 0 removed 956 0 renamed 957 0 copied 958 0 unknown 959 0 ignored 960 0 versioned subdirectories 961 962Branch history: 963 0 revisions 964 965Repository: 966 0 revisions 967""" % (format.get_branch_format().get_format_description(), 968 format.repository_format.get_format_description(), 969 ), out) 970 self.assertEqual('', err) 971 972 # Update first branch 973 self.build_tree(['repo/branch1/a']) 974 tree1 = branch1.controldir.open_workingtree() 975 tree1.add('a') 976 tree1.commit('commit one') 977 rev = repo.get_revision(branch1.last_revision()) 978 datestring_first = osutils.format_date(rev.timestamp, rev.timezone) 979 out, err = self.run_bzr('info -v repo/branch1') 980 self.assertEqualDiff( 981 """Repository tree (format: knit) 982Location: 983 shared repository: repo 984 repository branch: repo/branch1 985 986Format: 987 control: Meta directory format 1 988 working tree: Working tree format 3 989 branch: %s 990 repository: %s 991 992Control directory: 993 1 branches 994 995In the working tree: 996 1 unchanged 997 0 modified 998 0 added 999 0 removed 1000 0 renamed 1001 0 copied 1002 0 unknown 1003 0 ignored 1004 0 versioned subdirectories 1005 1006Branch history: 1007 1 revision 1008 0 days old 1009 first revision: %s 1010 latest revision: %s 1011 1012Repository: 1013 1 revision 1014""" % (format.get_branch_format().get_format_description(), 1015 format.repository_format.get_format_description(), 1016 datestring_first, datestring_first, 1017 ), out) 1018 self.assertEqual('', err) 1019 1020 # Out of date second branch 1021 out, err = self.run_bzr('info repo/branch2 --verbose') 1022 self.assertEqualDiff( 1023 """Repository tree (format: knit) 1024Location: 1025 shared repository: repo 1026 repository branch: repo/branch2 1027 1028Related branches: 1029 parent branch: repo/branch1 1030 1031Format: 1032 control: Meta directory format 1 1033 working tree: Working tree format 3 1034 branch: %s 1035 repository: %s 1036 1037Control directory: 1038 1 branches 1039 1040In the working tree: 1041 0 unchanged 1042 0 modified 1043 0 added 1044 0 removed 1045 0 renamed 1046 0 copied 1047 0 unknown 1048 0 ignored 1049 0 versioned subdirectories 1050 1051Branch history: 1052 0 revisions 1053 1054Repository: 1055 1 revision 1056""" % (format.get_branch_format().get_format_description(), 1057 format.repository_format.get_format_description(), 1058 ), out) 1059 self.assertEqual('', err) 1060 1061 # Update second branch 1062 tree2 = branch2.controldir.open_workingtree() 1063 tree2.pull(branch1) 1064 out, err = self.run_bzr('info -v repo/branch2') 1065 self.assertEqualDiff( 1066 """Repository tree (format: knit) 1067Location: 1068 shared repository: repo 1069 repository branch: repo/branch2 1070 1071Related branches: 1072 parent branch: repo/branch1 1073 1074Format: 1075 control: Meta directory format 1 1076 working tree: Working tree format 3 1077 branch: %s 1078 repository: %s 1079 1080Control directory: 1081 1 branches 1082 1083In the working tree: 1084 1 unchanged 1085 0 modified 1086 0 added 1087 0 removed 1088 0 renamed 1089 0 copied 1090 0 unknown 1091 0 ignored 1092 0 versioned subdirectories 1093 1094Branch history: 1095 1 revision 1096 0 days old 1097 first revision: %s 1098 latest revision: %s 1099 1100Repository: 1101 1 revision 1102""" % (format.get_branch_format().get_format_description(), 1103 format.repository_format.get_format_description(), 1104 datestring_first, datestring_first, 1105 ), out) 1106 self.assertEqual('', err) 1107 1108 # Show info about repository with revisions 1109 out, err = self.run_bzr('info -v repo') 1110 self.assertEqualDiff( 1111 """Shared repository with trees (format: dirstate or dirstate-tags or knit) 1112Location: 1113 shared repository: repo 1114 1115Format: 1116 control: Meta directory format 1 1117 repository: %s 1118 1119Control directory: 1120 0 branches 1121 1122Create working tree for new branches inside the repository. 1123 1124Repository: 1125 1 revision 1126""" % (format.repository_format.get_format_description(), 1127 ), 1128 out) 1129 self.assertEqual('', err) 1130 1131 def test_info_shared_repository_with_tree_in_root(self): 1132 format = controldir.format_registry.make_controldir('knit') 1133 transport = self.get_transport() 1134 1135 # Create shared repository with working trees 1136 repo = self.make_repository('repo', shared=True, format=format) 1137 repo.set_make_working_trees(True) 1138 out, err = self.run_bzr('info -v repo') 1139 self.assertEqualDiff( 1140 """Shared repository with trees (format: dirstate or dirstate-tags or knit) 1141Location: 1142 shared repository: repo 1143 1144Format: 1145 control: Meta directory format 1 1146 repository: %s 1147 1148Control directory: 1149 0 branches 1150 1151Create working tree for new branches inside the repository. 1152 1153Repository: 1154 0 revisions 1155""" % (format.repository_format.get_format_description(), 1156 ), out) 1157 self.assertEqual('', err) 1158 1159 # Create branch in root of repository 1160 control = repo.controldir 1161 branch = control.create_branch() 1162 control.create_workingtree() 1163 out, err = self.run_bzr('info -v repo') 1164 self.assertEqualDiff( 1165 """Repository tree (format: knit) 1166Location: 1167 shared repository: repo 1168 repository branch: repo 1169 1170Format: 1171 control: Meta directory format 1 1172 working tree: Working tree format 3 1173 branch: %s 1174 repository: %s 1175 1176Control directory: 1177 1 branches 1178 1179In the working tree: 1180 0 unchanged 1181 0 modified 1182 0 added 1183 0 removed 1184 0 renamed 1185 0 copied 1186 0 unknown 1187 0 ignored 1188 0 versioned subdirectories 1189 1190Branch history: 1191 0 revisions 1192 1193Repository: 1194 0 revisions 1195""" % (format.get_branch_format().get_format_description(), 1196 format.repository_format.get_format_description(), 1197 ), out) 1198 self.assertEqual('', err) 1199 1200 def test_info_repository_hook(self): 1201 format = controldir.format_registry.make_controldir('knit') 1202 1203 def repo_info(repo, stats, outf): 1204 outf.write(u"more info\n") 1205 info.hooks.install_named_hook('repository', repo_info, None) 1206 # Create shared repository with working trees 1207 repo = self.make_repository('repo', shared=True, format=format) 1208 out, err = self.run_bzr('info -v repo') 1209 self.assertEqualDiff( 1210 """Shared repository with trees (format: dirstate or dirstate-tags or knit) 1211Location: 1212 shared repository: repo 1213 1214Format: 1215 control: Meta directory format 1 1216 repository: %s 1217 1218Control directory: 1219 0 branches 1220 1221Create working tree for new branches inside the repository. 1222 1223Repository: 1224 0 revisions 1225more info 1226""" % (format.repository_format.get_format_description(), 1227 ), out) 1228 self.assertEqual('', err) 1229 1230 def test_info_unshared_repository_with_colocated_branches(self): 1231 format = controldir.format_registry.make_controldir('development-colo') 1232 transport = self.get_transport() 1233 1234 # Create unshared repository 1235 repo = self.make_repository('repo', shared=False, format=format) 1236 repo.set_make_working_trees(True) 1237 repo.controldir.create_branch(name='foo') 1238 out, err = self.run_bzr('info repo') 1239 self.assertEqualDiff( 1240 """Unshared repository with trees and colocated branches (format: development-colo) 1241Location: 1242 repository: repo 1243""", out) 1244 self.assertEqual('', err) 1245 1246 def assertCheckoutStatusOutput(self, 1247 command_string, lco_tree, shared_repo=None, 1248 repo_branch=None, 1249 tree_locked=False, 1250 branch_locked=False, repo_locked=False, 1251 verbose=False, 1252 light_checkout=True, 1253 checkout_root=None): 1254 """Check the output of info in a checkout. 1255 1256 This is not quite a mirror of the info code: rather than using the 1257 tree being examined to predict output, it uses a bunch of flags which 1258 allow us, the test writers, to document what *should* be present in 1259 the output. Removing this separation would remove the value of the 1260 tests. 1261 1262 :param path: the path to the light checkout. 1263 :param lco_tree: the tree object for the light checkout. 1264 :param shared_repo: A shared repository is in use, expect that in 1265 the output. 1266 :param repo_branch: A branch in a shared repository for non light 1267 checkouts. 1268 :param tree_locked: If true, expect the tree to be locked. 1269 :param branch_locked: If true, expect the branch to be locked. 1270 :param repo_locked: If true, expect the repository to be locked. 1271 Note that the lco_tree.branch.repository is inspected, and if is not 1272 actually locked then this parameter is overridden. This is because 1273 pack repositories do not have any public API for obtaining an 1274 exclusive repository wide lock. 1275 :param verbose: verbosity level: 2 or higher to show committers 1276 """ 1277 def friendly_location(url): 1278 path = urlutils.unescape_for_display(url, 'ascii') 1279 try: 1280 return osutils.relpath(osutils.getcwd(), path) 1281 except errors.PathNotChild: 1282 return path 1283 1284 if tree_locked: 1285 # We expect this to fail because of locking errors. 1286 # (A write-locked file cannot be read-locked 1287 # in the different process -- either on win32 or on linux). 1288 # This should be removed when the locking errors are fixed. 1289 self.expectFailure('OS locks are exclusive ' 1290 'for different processes (Bug #174055)', 1291 self.run_bzr_subprocess, 1292 'info ' + command_string) 1293 out, err = self.run_bzr('info %s' % command_string) 1294 description = { 1295 (True, True): 'Lightweight checkout', 1296 (True, False): 'Repository checkout', 1297 (False, True): 'Lightweight checkout', 1298 (False, False): 'Checkout', 1299 }[(shared_repo is not None, light_checkout)] 1300 format = {True: self._repo_strings, 1301 False: 'unnamed'}[light_checkout] 1302 if repo_locked: 1303 repo_locked = lco_tree.branch.repository.get_physical_lock_status() 1304 if repo_locked or branch_locked or tree_locked: 1305 def locked_message(a_bool): 1306 if a_bool: 1307 return 'locked' 1308 else: 1309 return 'unlocked' 1310 expected_lock_output = ( 1311 "\n" 1312 "Lock status:\n" 1313 " working tree: %s\n" 1314 " branch: %s\n" 1315 " repository: %s\n" % ( 1316 locked_message(tree_locked), 1317 locked_message(branch_locked), 1318 locked_message(repo_locked))) 1319 else: 1320 expected_lock_output = '' 1321 tree_data = '' 1322 extra_space = '' 1323 if light_checkout: 1324 tree_data = (" light checkout root: %s\n" % 1325 friendly_location(lco_tree.controldir.root_transport.base)) 1326 extra_space = ' ' 1327 if lco_tree.branch.get_bound_location() is not None: 1328 tree_data += ("%s checkout root: %s\n" % (extra_space, 1329 friendly_location(lco_tree.branch.controldir.root_transport.base))) 1330 if shared_repo is not None: 1331 branch_data = ( 1332 " checkout of branch: %s\n" 1333 " shared repository: %s\n" % 1334 (friendly_location(repo_branch.controldir.root_transport.base), 1335 friendly_location(shared_repo.controldir.root_transport.base))) 1336 elif repo_branch is not None: 1337 branch_data = ( 1338 "%s checkout of branch: %s\n" % 1339 (extra_space, 1340 friendly_location(repo_branch.controldir.root_transport.base))) 1341 else: 1342 branch_data = (" checkout of branch: %s\n" % 1343 lco_tree.branch.controldir.root_transport.base) 1344 1345 if verbose >= 2: 1346 verbose_info = ' 0 committers\n' 1347 else: 1348 verbose_info = '' 1349 1350 self.assertEqualDiff( 1351 """%s (format: %s) 1352Location: 1353%s%s 1354Format: 1355 control: Meta directory format 1 1356 working tree: %s 1357 branch: %s 1358 repository: %s 1359%s 1360Control directory: 1361 1 branches 1362 1363In the working tree: 1364 0 unchanged 1365 0 modified 1366 0 added 1367 0 removed 1368 0 renamed 1369 0 copied 1370 0 unknown 1371 0 ignored 1372 0 versioned subdirectories 1373 1374Branch history: 1375 0 revisions 1376%s 1377Repository: 1378 0 revisions 1379""" % (description, 1380 format, 1381 tree_data, 1382 branch_data, 1383 lco_tree._format.get_format_description(), 1384 lco_tree.branch._format.get_format_description(), 1385 lco_tree.branch.repository._format.get_format_description(), 1386 expected_lock_output, 1387 verbose_info, 1388 ), out) 1389 self.assertEqual('', err) 1390 1391 def test_info_locking(self): 1392 transport = self.get_transport() 1393 # Create shared repository with a branch 1394 repo = self.make_repository('repo', shared=True, 1395 format=bzrdir.BzrDirMetaFormat1()) 1396 repo.set_make_working_trees(False) 1397 repo.controldir.root_transport.mkdir('branch') 1398 repo_branch = controldir.ControlDir.create_branch_convenience( 1399 'repo/branch', format=bzrdir.BzrDirMetaFormat1()) 1400 # Do a heavy checkout 1401 transport.mkdir('tree') 1402 transport.mkdir('tree/checkout') 1403 co_branch = controldir.ControlDir.create_branch_convenience( 1404 'tree/checkout', format=bzrdir.BzrDirMetaFormat1()) 1405 co_branch.bind(repo_branch) 1406 # Do a light checkout of the heavy one 1407 transport.mkdir('tree/lightcheckout') 1408 lco_dir = bzrdir.BzrDirMetaFormat1().initialize('tree/lightcheckout') 1409 lco_dir.set_branch_reference(co_branch) 1410 lco_dir.create_workingtree() 1411 lco_tree = lco_dir.open_workingtree() 1412 1413 # Test all permutations of locking the working tree, branch and repository 1414 # W B R 1415 1416 # U U U 1417 self.assertCheckoutStatusOutput('-v tree/lightcheckout', lco_tree, 1418 repo_branch=repo_branch, 1419 verbose=True, light_checkout=True) 1420 # U U L 1421 with lco_tree.branch.repository.lock_write(): 1422 self.assertCheckoutStatusOutput('-v tree/lightcheckout', 1423 lco_tree, repo_branch=repo_branch, 1424 repo_locked=True, verbose=True, light_checkout=True) 1425 # U L L 1426 with lco_tree.branch.lock_write(): 1427 self.assertCheckoutStatusOutput('-v tree/lightcheckout', 1428 lco_tree, 1429 branch_locked=True, 1430 repo_locked=True, 1431 repo_branch=repo_branch, 1432 verbose=True) 1433 # L L L 1434 with lco_tree.lock_write(): 1435 self.assertCheckoutStatusOutput('-v tree/lightcheckout', 1436 lco_tree, repo_branch=repo_branch, 1437 tree_locked=True, 1438 branch_locked=True, 1439 repo_locked=True, 1440 verbose=True) 1441 # L L U 1442 with lco_tree.lock_write(), lco_tree.branch.repository.unlock(): 1443 self.assertCheckoutStatusOutput('-v tree/lightcheckout', 1444 lco_tree, repo_branch=repo_branch, 1445 tree_locked=True, 1446 branch_locked=True, 1447 verbose=True) 1448 # L U U 1449 with lco_tree.lock_write(), lco_tree.branch.unlock(): 1450 self.assertCheckoutStatusOutput('-v tree/lightcheckout', 1451 lco_tree, repo_branch=repo_branch, 1452 tree_locked=True, 1453 verbose=True) 1454 # L U L 1455 with lco_tree.lock_write(), lco_tree.branch.unlock(), \ 1456 lco_tree.branch.repository.lock_write(): 1457 self.assertCheckoutStatusOutput('-v tree/lightcheckout', 1458 lco_tree, repo_branch=repo_branch, 1459 tree_locked=True, 1460 repo_locked=True, 1461 verbose=True) 1462 # U L U 1463 with lco_tree.branch.lock_write(), lco_tree.branch.repository.unlock(): 1464 self.assertCheckoutStatusOutput('-v tree/lightcheckout', 1465 lco_tree, repo_branch=repo_branch, 1466 branch_locked=True, 1467 verbose=True) 1468 1469 if sys.platform == 'win32': 1470 self.knownFailure('Win32 cannot run "brz info"' 1471 ' when the tree is locked.') 1472 1473 def test_info_stacked(self): 1474 # We have a mainline 1475 trunk_tree = self.make_branch_and_tree('mainline', 1476 format='1.6') 1477 trunk_tree.commit('mainline') 1478 # and a branch from it which is stacked 1479 new_dir = trunk_tree.controldir.sprout('newbranch', stacked=True) 1480 out, err = self.run_bzr('info newbranch') 1481 self.assertEqual( 1482 """Standalone tree (format: 1.6) 1483Location: 1484 branch root: newbranch 1485 1486Related branches: 1487 parent branch: mainline 1488 stacked on: mainline 1489""", out) 1490 self.assertEqual("", err) 1491 1492 def test_info_revinfo_optional(self): 1493 tree = self.make_branch_and_tree('.') 1494 1495 def last_revision_info(self): 1496 raise errors.UnsupportedOperation(last_revision_info, self) 1497 self.overrideAttr( 1498 branch.Branch, "last_revision_info", last_revision_info) 1499 out, err = self.run_bzr('info -v .') 1500 self.assertEqual( 1501 """Standalone tree (format: 2a) 1502Location: 1503 branch root: . 1504 1505Format: 1506 control: Meta directory format 1 1507 working tree: Working tree format 6 1508 branch: Branch format 7 1509 repository: Repository format 2a - rich roots, group compression and chk inventories 1510 1511Control directory: 1512 1 branches 1513 1514In the working tree: 1515 0 unchanged 1516 0 modified 1517 0 added 1518 0 removed 1519 0 renamed 1520 0 copied 1521 0 unknown 1522 0 ignored 1523 0 versioned subdirectories 1524""", out) 1525 self.assertEqual("", err) 1526 1527 def test_info_shows_colocated_branches(self): 1528 bzrdir = self.make_branch('.', format='development-colo').controldir 1529 bzrdir.create_branch(name="colo1") 1530 bzrdir.create_branch(name="colo2") 1531 bzrdir.create_branch(name="colo3") 1532 out, err = self.run_bzr('info -v .') 1533 self.assertEqualDiff( 1534 """Standalone branch (format: development-colo) 1535Location: 1536 branch root: . 1537 1538Format: 1539 control: Meta directory format 1 with support for colocated branches 1540 branch: Branch format 7 1541 repository: Repository format 2a - rich roots, group compression and chk inventories 1542 1543Control directory: 1544 4 branches 1545 1546Branch history: 1547 0 revisions 1548 1549Repository: 1550 0 revisions 1551""", out) 1552 self.assertEqual("", err) 1553