Rev 4476: merge trunk again in file:///home/vila/src/bzr/bugs/206577-send-strict/

Vincent Ladeuil v.ladeuil+lp at free.fr
Wed Jul 1 09:38:13 BST 2009


At file:///home/vila/src/bzr/bugs/206577-send-strict/

------------------------------------------------------------
revno: 4476 [merge]
revision-id: v.ladeuil+lp at free.fr-20090701083812-9p6w0aim50nk22em
parent: v.ladeuil+lp at free.fr-20090701072036-z0v9p3wk5hwsu480
parent: pqm at pqm.ubuntu.com-20090701083204-fzy3czqk0ifjyri2
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 206577-send-strict
timestamp: Wed 2009-07-01 10:38:12 +0200
message:
  merge trunk again
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
  bzrlib/revision.py             revision.py-20050309040759-e77802c08f3999d5
  bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
  bzrlib/tests/blackbox/test_revision_info.py test_revision_info.py-20050917162600-21dab3877aa348d7
  bzrlib/tests/blackbox/test_revno.py test_revno.py-20051204214528-2f0bf83a71b7656a
  bzrlib/tests/test_revision.py  testrevision.py-20050804210559-46f5e1eb67b01289
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS	2009-06-30 12:35:25 +0000
+++ b/NEWS	2009-07-01 08:38:12 +0000
@@ -26,6 +26,10 @@
   speified. The configuration option ``push_strict`` can be used to set the
   default for this behavior.  (Vincent Ladeuil, #284038, #322808, #65286)
 
+* ``bzr revno`` and ``bzr revision-info`` now have a ``--tree`` option to
+  show revision info for the working tree instead of the branch.
+  (Matthew Fuller, John Arbash Meinel)
+
 * ``bzr send`` now aborts if uncommitted changes (including pending merges)
   are present in the working tree and no revision is specified. The
   configuration option ``send_strict`` can be used to set the default for this
@@ -141,6 +145,11 @@
   or ``bzr+ssh://`` is now much faster and involves no VFS operations.
   This speeds up commands like ``bzr pull -r 123``.  (Andrew Bennetts)
 
+* ``revision-info`` now properly aligns the revnos/revids in the output
+  and doesn't traceback when given revisions not in the current branch.
+  Performance is also significantly improved when requesting multiple revs
+  at once.  (Matthew Fuller, John Arbash Meinel)
+
 Documentation
 *************
 

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2009-07-01 07:20:36 +0000
+++ b/bzrlib/builtins.py	2009-07-01 08:38:12 +0000
@@ -474,11 +474,36 @@
 
     _see_also = ['info']
     takes_args = ['location?']
+    takes_options = [
+        Option('tree', help='Show revno of working tree'),
+        ]
 
     @display_command
-    def run(self, location=u'.'):
-        self.outf.write(str(Branch.open_containing(location)[0].revno()))
-        self.outf.write('\n')
+    def run(self, tree=False, location=u'.'):
+        if tree:
+            try:
+                wt = WorkingTree.open_containing(location)[0]
+                wt.lock_read()
+            except (errors.NoWorkingTree, errors.NotLocalUrl):
+                raise errors.NoWorkingTree(location)
+            try:
+                revid = wt.last_revision()
+                try:
+                    revno_t = wt.branch.revision_id_to_dotted_revno(revid)
+                except errors.NoSuchRevision:
+                    revno_t = ('???',)
+                revno = ".".join(str(n) for n in revno_t)
+            finally:
+                wt.unlock()
+        else:
+            b = Branch.open_containing(location)[0]
+            b.lock_read()
+            try:
+                revno = b.revno()
+            finally:
+                b.unlock()
+
+        self.outf.write(str(revno) + '\n')
 
 
 class cmd_revision_info(Command):
@@ -494,31 +519,56 @@
             short_name='d',
             type=unicode,
             ),
+        Option('tree', help='Show revno of working tree'),
         ]
 
     @display_command
-    def run(self, revision=None, directory=u'.', revision_info_list=[]):
-
-        revs = []
-        if revision is not None:
-            revs.extend(revision)
-        if revision_info_list is not None:
-            for rev in revision_info_list:
-                revs.append(RevisionSpec.from_string(rev))
-
-        b = Branch.open_containing(directory)[0]
-
-        if len(revs) == 0:
-            revs.append(RevisionSpec.from_string('-1'))
-
-        for rev in revs:
-            revision_id = rev.as_revision_id(b)
-            try:
-                revno = '%4d' % (b.revision_id_to_revno(revision_id))
-            except errors.NoSuchRevision:
-                dotted_map = b.get_revision_id_to_revno_map()
-                revno = '.'.join(str(i) for i in dotted_map[revision_id])
-            print '%s %s' % (revno, revision_id)
+    def run(self, revision=None, directory=u'.', tree=False,
+            revision_info_list=[]):
+
+        try:
+            wt = WorkingTree.open_containing(directory)[0]
+            b = wt.branch
+            wt.lock_read()
+        except (errors.NoWorkingTree, errors.NotLocalUrl):
+            wt = None
+            b = Branch.open_containing(directory)[0]
+            b.lock_read()
+        try:
+            revision_ids = []
+            if revision is not None:
+                revision_ids.extend(rev.as_revision_id(b) for rev in revision)
+            if revision_info_list is not None:
+                for rev_str in revision_info_list:
+                    rev_spec = RevisionSpec.from_string(rev_str)
+                    revision_ids.append(rev_spec.as_revision_id(b))
+            # No arguments supplied, default to the last revision
+            if len(revision_ids) == 0:
+                if tree:
+                    if wt is None:
+                        raise errors.NoWorkingTree(directory)
+                    revision_ids.append(wt.last_revision())
+                else:
+                    revision_ids.append(b.last_revision())
+
+            revinfos = []
+            maxlen = 0
+            for revision_id in revision_ids:
+                try:
+                    dotted_revno = b.revision_id_to_dotted_revno(revision_id)
+                    revno = '.'.join(str(i) for i in dotted_revno)
+                except errors.NoSuchRevision:
+                    revno = '???'
+                maxlen = max(maxlen, len(revno))
+                revinfos.append([revno, revision_id])
+        finally:
+            if wt is None:
+                b.unlock()
+            else:
+                wt.unlock()
+
+        for ri in revinfos:
+            self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
 
 
 class cmd_add(Command):
@@ -1067,7 +1117,14 @@
             and (strict is None or strict)): # Default to True:
             changes = tree.changes_from(tree.basis_tree())
             if changes.has_changed() or len(tree.get_parent_ids()) > 1:
-                raise errors.UncommittedChanges(tree)
+                raise errors.UncommittedChanges(
+                    tree, more='Use --no-strict to force the push.')
+            if tree.last_revision() != tree.branch.last_revision():
+                # The tree has lost sync with its branch, there is little
+                # chance that the user is aware of it but he can still force
+                # the push with --no-strict
+                raise errors.OutOfDateTree(
+                    tree, more='Use --no-strict to force the push.')
 
         # Get the stacked_on branch, if any
         if stacked_on is not None:

=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py	2009-06-30 08:06:35 +0000
+++ b/bzrlib/errors.py	2009-06-30 15:54:23 +0000
@@ -2093,11 +2093,16 @@
 
 class OutOfDateTree(BzrError):
 
-    _fmt = "Working tree is out of date, please run 'bzr update'."
+    _fmt = "Working tree is out of date, please run 'bzr update'.%(more)s"
 
-    def __init__(self, tree):
+    def __init__(self, tree, more=None):
+        if more is None:
+            more = ''
+        else:
+            more = ' ' + more
         BzrError.__init__(self)
         self.tree = tree
+        self.more = more
 
 
 class PublicBranchOutOfDate(BzrError):
@@ -2779,13 +2784,17 @@
 class UncommittedChanges(BzrError):
 
     _fmt = ('Working tree "%(display_url)s" has uncommitted changes'
-            ' (See bzr status).')
+            ' (See bzr status).%(more)s')
 
-    def __init__(self, tree):
+    def __init__(self, tree, more=None):
+        if more is None:
+            more = ''
+        else:
+            more = ' ' + more
         import bzrlib.urlutils as urlutils
         display_url = urlutils.unescape_for_display(
             tree.bzrdir.root_transport.base, 'ascii')
-        BzrError.__init__(self, tree=tree, display_url=display_url)
+        BzrError.__init__(self, tree=tree, display_url=display_url, more=more)
 
 
 class MissingTemplateVariable(BzrError):

=== modified file 'bzrlib/revision.py'
--- a/bzrlib/revision.py	2009-06-19 03:47:11 +0000
+++ b/bzrlib/revision.py	2009-06-30 16:16:55 +0000
@@ -111,8 +111,13 @@
 
     def get_summary(self):
         """Get the first line of the log message for this revision.
+
+        Return an empty string if message is None.
         """
-        return self.message.lstrip().split('\n', 1)[0]
+        if self.message:
+            return self.message.lstrip().split('\n', 1)[0]
+        else:
+            return ''
 
     @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((1, 13, 0)))
     def get_apparent_author(self):

=== modified file 'bzrlib/tests/blackbox/test_push.py'
--- a/bzrlib/tests/blackbox/test_push.py	2009-06-30 09:19:06 +0000
+++ b/bzrlib/tests/blackbox/test_push.py	2009-06-30 15:54:23 +0000
@@ -47,8 +47,10 @@
     changes_scenarios = [
         ('uncommitted',
          dict(_changes_type= '_uncommitted_changes')),
-        ('pending_merges',
+        ('pending-merges',
          dict(_changes_type= '_pending_merges')),
+        ('out-of-sync-trees',
+         dict(_changes_type= '_out_of_sync_trees')),
         ]
     tests.multiply_tests(changes_tests, changes_scenarios, result)
     # No parametrization for the remaining tests
@@ -588,7 +590,7 @@
         self.assertEqual('', out)
 
 
-class TestPushStrict(tests.TestCaseWithTransport):
+class TestPushStrictMixin(object):
 
     def make_local_branch_and_tree(self):
         self.tree = self.make_branch_and_tree('local')
@@ -604,17 +606,21 @@
         conf = self.tree.branch.get_config()
         conf.set_user_option('push_strict', value)
 
+    _default_command = ['push', '../to']
+    _default_wd = 'local'
+    _default_errors = ['Working tree ".*/local/" has uncommitted '
+                       'changes \(See bzr status\)\.',]
+    _default_pushed_revid = 'modified'
+
     def assertPushFails(self, args):
-        self.run_bzr_error(['Working tree ".*/local/"'
-                            ' has uncommitted changes \(See bzr status\)\.',],
-                           ['push', '../to'] + args,
-                           working_dir='local', retcode=3)
+        self.run_bzr_error(self._default_errors, self._default_command + args,
+                           working_dir=self._default_wd, retcode=3)
 
     def assertPushSucceeds(self, args, pushed_revid=None):
-        self.run_bzr(['push', '../to'] + args,
-                     working_dir='local')
+        self.run_bzr(self._default_command + args,
+                     working_dir=self._default_wd)
         if pushed_revid is None:
-            pushed_revid = 'modified'
+            pushed_revid = self._default_pushed_revid
         tree_to = workingtree.WorkingTree.open('to')
         repo_to = tree_to.branch.repository
         self.assertTrue(repo_to.has_revision(pushed_revid))
@@ -622,7 +628,8 @@
 
 
 
-class TestPushStrictWithoutChanges(TestPushStrict):
+class TestPushStrictWithoutChanges(tests.TestCaseWithTransport,
+                                   TestPushStrictMixin):
 
     def setUp(self):
         super(TestPushStrictWithoutChanges, self).setUp()
@@ -646,7 +653,8 @@
         self.assertPushSucceeds([])
 
 
-class TestPushStrictWithChanges(TestPushStrict):
+class TestPushStrictWithChanges(tests.TestCaseWithTransport,
+                                TestPushStrictMixin):
 
     _changes_type = None # Set by load_tests
 
@@ -671,6 +679,18 @@
         self.tree.merge_from_branch(other_tree.branch)
         self.tree.revert(filenames=['other-file'], backups=False)
 
+    def _out_of_sync_trees(self):
+        self.make_local_branch_and_tree()
+        self.run_bzr(['checkout', '--lightweight', 'local', 'checkout'])
+        # Make a change and commit it
+        self.build_tree_contents([('local/file', 'modified in local')])
+        self.tree.commit('modify file', rev_id='modified-in-local')
+        # Exercise commands from the checkout directory
+        self._default_wd = 'checkout'
+        self._default_errors = ["Working tree is out of date, please run"
+                                " 'bzr update'\.",]
+        self._default_pushed_revid = 'modified-in-local'
+
     def test_push_default(self):
         self.assertPushFails([])
 

=== modified file 'bzrlib/tests/blackbox/test_revision_info.py'
--- a/bzrlib/tests/blackbox/test_revision_info.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/blackbox/test_revision_info.py	2009-06-30 16:59:21 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2005 Canonical Ltd
+# Copyright (C) 2004, 2005, 2009 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
@@ -47,9 +47,9 @@
 
         # Expected return values
         values = {
-            '1'    : '   1 a at r-0-1\n',
+            '1'    : '1 a at r-0-1\n',
             '1.1.1': '1.1.1 a at r-0-1.1.1\n',
-            '2'    : '   2 a at r-0-2\n'
+            '2'    : '2 a at r-0-2\n'
         }
 
         # Make sure with no arg it defaults to the head
@@ -60,7 +60,9 @@
         self.check_output(values['1.1.1'], 'revision-info 1.1.1')
         self.check_output(values['2'], 'revision-info 2')
         self.check_output(values['1']+values['2'], 'revision-info 1 2')
-        self.check_output(values['1']+values['1.1.1']+values['2'],
+        self.check_output('    '+values['1']+
+                                 values['1.1.1']+
+                          '    '+values['2'],
                           'revision-info 1 1.1.1 2')
         self.check_output(values['2']+values['1'], 'revision-info 2 1')
 
@@ -70,7 +72,9 @@
         self.check_output(values['1.1.1'], 'revision-info --revision 1.1.1')
         self.check_output(values['2'], 'revision-info -r 2')
         self.check_output(values['1']+values['2'], 'revision-info -r 1..2')
-        self.check_output(values['1']+values['1.1.1']+values['2'],
+        self.check_output('    '+values['1']+
+                                 values['1.1.1']+
+                          '    '+values['2'],
                           'revision-info -r 1..1.1.1..2')
         self.check_output(values['2']+values['1'], 'revision-info -r 2..1')
 
@@ -85,4 +89,40 @@
         wt = self.make_branch_and_tree('branch')
 
         wt.commit('Commit one', rev_id='a at r-0-1')
-        self.check_output('   1 a at r-0-1\n', 'revision-info -d branch')
+        self.check_output('1 a at r-0-1\n', 'revision-info -d branch')
+
+    def test_revision_info_tree(self):
+        # Make branch and checkout
+        wt = self.make_branch_and_tree('branch')
+        wt.commit('Commit one', rev_id='a at r-0-1')
+
+        # Make checkout and move the branch forward
+        wt.branch.create_checkout('checkout', lightweight=True)
+        wt.commit('Commit two', rev_id='a at r-0-2')
+
+        # Make sure the checkout gives the right answer for branch and
+        # tree
+        self.check_output('2 a at r-0-2\n', 'revision-info -d checkout')
+        self.check_output('1 a at r-0-1\n', 'revision-info --tree -d checkout')
+
+    def test_revision_info_tree_no_working_tree(self):
+        # Make branch with no tree
+        b = self.make_branch('branch')
+
+        # Try getting the --tree revision-info
+        out,err = self.run_bzr('revision-info --tree -d branch', retcode=3)
+        self.assertEqual('', out)
+        self.assertEqual('bzr: ERROR: No WorkingTree exists for "branch".\n',
+            err)
+
+    def test_revision_info_not_in_history(self):
+        builder = self.make_branch_builder('branch')
+        builder.start_series()
+        builder.build_snapshot('A-id', None, [
+            ('add', ('', 'root-id', 'directory', None))])
+        builder.build_snapshot('B-id', ['A-id'], [])
+        builder.build_snapshot('C-id', ['A-id'], [])
+        builder.finish_series()
+        self.check_output('  1 A-id\n??? B-id\n  2 C-id\n',
+                          'revision-info -d branch'
+                          ' revid:A-id revid:B-id revid:C-id')

=== modified file 'bzrlib/tests/blackbox/test_revno.py'
--- a/bzrlib/tests/blackbox/test_revno.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/blackbox/test_revno.py	2009-06-30 16:59:21 +0000
@@ -1,5 +1,4 @@
-# Copyright (C) 2005 Canonical Ltd
-# -*- coding: utf-8 -*-
+# Copyright (C) 2005, 2006, 2007, 2009 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
@@ -21,10 +20,9 @@
 
 import os
 
-from bzrlib.branch import Branch
-from bzrlib.tests import TestCaseInTempDir
+from bzrlib import tests
 
-class TestRevno(TestCaseInTempDir):
+class TestRevno(tests.TestCaseWithTransport):
 
     def test_revno(self):
 
@@ -50,4 +48,72 @@
         self.assertEquals(int(bzr('revno a')), 2)
         self.assertEquals(int(bzr('revno a/baz')), 2)
 
-
+    def test_revno_tree(self):
+        # Make branch and checkout
+        wt = self.make_branch_and_tree('branch')
+        checkout = wt.branch.create_checkout('checkout', lightweight=True)
+
+        # Get the checkout out of date
+        self.build_tree(['branch/file'])
+        wt.add(['file'])
+        wt.commit('mkfile')
+
+        # Make sure revno says we're on 1
+        out,err = self.run_bzr('revno checkout')
+        self.assertEqual('', err)
+        self.assertEqual('1\n', out)
+
+        # Make sure --tree knows it's still on 0
+        out,err = self.run_bzr('revno --tree checkout')
+        self.assertEqual('', err)
+        self.assertEqual('0\n', out)
+
+    def test_revno_tree_no_tree(self):
+        # Make treeless branch
+        b = self.make_branch('branch')
+
+        # Try getting it's --tree revno
+        out,err = self.run_bzr('revno --tree branch', retcode=3)
+        self.assertEqual('', out)
+        self.assertEqual('bzr: ERROR: No WorkingTree exists for "branch".\n',
+            err)
+
+    def test_dotted_revno_tree(self):
+        builder = self.make_branch_builder('branch')
+        builder.start_series()
+        builder.build_snapshot('A-id', None, [
+            ('add', ('', 'root-id', 'directory', None)),
+            ('add', ('file', 'file-id', 'file', 'content\n'))])
+        builder.build_snapshot('B-id', ['A-id'], [])
+        builder.build_snapshot('C-id', ['A-id', 'B-id'], [])
+        builder.finish_series()
+        b = builder.get_branch()
+        co_b = b.create_checkout('checkout_b', lightweight=True,
+                                 revision_id='B-id')
+        out, err = self.run_bzr('revno checkout_b')
+        self.assertEqual('', err)
+        self.assertEqual('2\n', out)
+        out, err = self.run_bzr('revno --tree checkout_b')
+        self.assertEqual('', err)
+        self.assertEqual('1.1.1\n', out)
+
+    def test_stale_revno_tree(self):
+        builder = self.make_branch_builder('branch')
+        builder.start_series()
+        builder.build_snapshot('A-id', None, [
+            ('add', ('', 'root-id', 'directory', None)),
+            ('add', ('file', 'file-id', 'file', 'content\n'))])
+        builder.build_snapshot('B-id', ['A-id'], [])
+        builder.build_snapshot('C-id', ['A-id'], [])
+        builder.finish_series()
+        b = builder.get_branch()
+        # The branch is now at "C-id", but the checkout is still at "B-id"
+        # which is no longer in the history
+        co_b = b.create_checkout('checkout_b', lightweight=True,
+                                 revision_id='B-id')
+        out, err = self.run_bzr('revno checkout_b')
+        self.assertEqual('', err)
+        self.assertEqual('2\n', out)
+        out, err = self.run_bzr('revno --tree checkout_b')
+        self.assertEqual('', err)
+        self.assertEqual('???\n', out)

=== modified file 'bzrlib/tests/test_revision.py'
--- a/bzrlib/tests/test_revision.py	2009-04-09 23:59:02 +0000
+++ b/bzrlib/tests/test_revision.py	2009-06-03 10:24:28 +0000
@@ -208,6 +208,8 @@
         self.assertEqual('a', r.get_summary())
         r.message = '\na\nb'
         self.assertEqual('a', r.get_summary())
+        r.message = None
+        self.assertEqual('', r.get_summary())
 
     def test_get_apparent_author(self):
         r = revision.Revision('1')



More information about the bazaar-commits mailing list