Rev 2452: (John Arbash Meinel) Add Branch.get_revision_id_to_revno_map in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Apr 24 23:44:31 BST 2007
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 2452
revision-id: pqm at pqm.ubuntu.com-20070424224426-po331pf12jpzmrvk
parent: pqm at pqm.ubuntu.com-20070424141924-i4w482pi1pb95pob
parent: john at arbash-meinel.com-20070424220920-1pamgmk2mo44wlm3
committer: Canonical.com Patch Queue Manager<pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2007-04-24 23:44:26 +0100
message:
(John Arbash Meinel) Add Branch.get_revision_id_to_revno_map
added:
bzrlib/tests/branch_implementations/test_get_revision_id_to_revno_map.py test_get_revision_id-20070417211641-6kcoj1c704gqqopn-1
bzrlib/tests/branch_implementations/test_revision_id_to_revno.py test_revision_id_to_-20070417200738-lo776wkqikhe5goo-1
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/annotate.py annotate.py-20050922133147-7c60541d2614f022
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/memorytree.py memorytree.py-20060906023413-4wlkalbdpsxi2r4y-1
bzrlib/mutabletree.py mutabletree.py-20060906023413-4wlkalbdpsxi2r4y-2
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/revisionspec.py revisionspec.py-20050907152633-17567659fd5c0ddb
bzrlib/tests/branch_implementations/__init__.py __init__.py-20060123013057-b12a52c3f361daf4
bzrlib/tests/branch_implementations/test_branch.py testbranch.py-20050711070244-121d632bc37d7253
------------------------------------------------------------
revno: 2418.5.15
merged: john at arbash-meinel.com-20070424220920-1pamgmk2mo44wlm3
parent: john at arbash-meinel.com-20070424194505-mv5dwjw0mx4tfpfs
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-24 17:09:20 -0500
message:
NEWS
------------------------------------------------------------
revno: 2418.5.14
merged: john at arbash-meinel.com-20070424194505-mv5dwjw0mx4tfpfs
parent: john at arbash-meinel.com-20070424194309-nt3sxw7x4sqwnykh
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-24 14:45:05 -0500
message:
clean up ASCII revision graph art.
------------------------------------------------------------
revno: 2418.5.13
merged: john at arbash-meinel.com-20070424194309-nt3sxw7x4sqwnykh
parent: john at arbash-meinel.com-20070424194013-zjckbpsbq7vff1wh
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-24 14:43:09 -0500
message:
Remove revision_id_to_dotted_revno, because it isn't used.
------------------------------------------------------------
revno: 2418.5.12
merged: john at arbash-meinel.com-20070424194013-zjckbpsbq7vff1wh
parent: john at arbash-meinel.com-20070424032327-w2tz2smz41eco4u1
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-24 14:40:13 -0500
message:
Move functions from BzrBranch to base Branch object.
Fix RemoteBranch to properly clear its cache at the right time.
------------------------------------------------------------
revno: 2418.5.11
merged: john at arbash-meinel.com-20070424032327-w2tz2smz41eco4u1
parent: john at arbash-meinel.com-20070417213150-yf8r9e1ufueedb3q
parent: pqm at pqm.ubuntu.com-20070423170758-qd512ltqglzfo6w9
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Mon 2007-04-23 22:23:27 -0500
message:
[merge] bzr.dev 2447
------------------------------------------------------------
revno: 2418.5.10
merged: john at arbash-meinel.com-20070417213150-yf8r9e1ufueedb3q
parent: john at arbash-meinel.com-20070417212608-84w0sw1e7tiuhgr4
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 16:31:50 -0500
message:
fix typo
------------------------------------------------------------
revno: 2418.5.9
merged: john at arbash-meinel.com-20070417212608-84w0sw1e7tiuhgr4
parent: john at arbash-meinel.com-20070417211929-rchob1jeahy30cj0
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 16:26:08 -0500
message:
Have RevisionSpec_revno() also use the new helper
------------------------------------------------------------
revno: 2418.5.8
merged: john at arbash-meinel.com-20070417211929-rchob1jeahy30cj0
parent: john at arbash-meinel.com-20070417211809-f225hrm1juxoityu
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 16:19:29 -0500
message:
Update annotate.py to use the new helper function.
------------------------------------------------------------
revno: 2418.5.7
merged: john at arbash-meinel.com-20070417211809-f225hrm1juxoityu
parent: john at arbash-meinel.com-20070417210124-rfr3w1llh869058q
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 16:18:09 -0500
message:
Move the revision_id=>map generation to be a public function.
------------------------------------------------------------
revno: 2418.5.6
merged: john at arbash-meinel.com-20070417210124-rfr3w1llh869058q
parent: john at arbash-meinel.com-20070417203323-xbmbi9cyjr6cocuf
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 16:01:24 -0500
message:
Cache the revision_id => revno map as appropriate.
------------------------------------------------------------
revno: 2418.5.5
merged: john at arbash-meinel.com-20070417203323-xbmbi9cyjr6cocuf
parent: john at arbash-meinel.com-20070417202335-0cc0thlj5sy28m9m
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 15:33:23 -0500
message:
Add some tests and an api for revision_id_to_dotted_revno
This should use caching to be fast for multiple calls
but for now it just implements what is needed.
------------------------------------------------------------
revno: 2418.5.4
merged: john at arbash-meinel.com-20070417202335-0cc0thlj5sy28m9m
parent: john at arbash-meinel.com-20070417201836-2bso1f1clhhx7k1a
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 15:23:35 -0500
message:
Included a test for revision_id=None
------------------------------------------------------------
revno: 2418.5.3
merged: john at arbash-meinel.com-20070417201836-2bso1f1clhhx7k1a
parent: john at arbash-meinel.com-20070417201724-5seu77st1h843nie
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 15:18:36 -0500
message:
Use a more straightforward implementation of generating 'tree_with_merge'
------------------------------------------------------------
revno: 2418.5.2
merged: john at arbash-meinel.com-20070417201724-5seu77st1h843nie
parent: john at arbash-meinel.com-20070417201004-1v7sim0tlt19l8o4
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 15:17:24 -0500
message:
Move TestCaseWithBranch into branch_implementations from test_branch.py
------------------------------------------------------------
revno: 2418.5.1
merged: john at arbash-meinel.com-20070417201004-1v7sim0tlt19l8o4
parent: pqm at pqm.ubuntu.com-20070413174100-zpfqleaf5ph9ycx4
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_revision_id_to_revno
timestamp: Tue 2007-04-17 15:10:04 -0500
message:
Make a Branch helper which can create a very basic MemoryTree with history.
This updates MutableTree to include 'set_parent_ids' which is helpful
when setting up simple tests.
It also creates a helper function in branch_implementations..TestCaseWithBranch
so that we can create a Branch which has a simple merge in it.
It also adds a test for revision_id_to_revno which previously did not have any
direct tests.
=== added file 'bzrlib/tests/branch_implementations/test_get_revision_id_to_revno_map.py'
--- a/bzrlib/tests/branch_implementations/test_get_revision_id_to_revno_map.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/branch_implementations/test_get_revision_id_to_revno_map.py 2007-04-24 19:43:09 +0000
@@ -0,0 +1,118 @@
+# Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Tests for Branch.get_revision_id_to_revno_map()"""
+
+from bzrlib import (
+ errors,
+ revision,
+ )
+
+from bzrlib.tests.branch_implementations import TestCaseWithBranch
+
+
+class TestRevisionIdToDottedRevno(TestCaseWithBranch):
+
+ def test_simple_revno(self):
+ tree = self.create_tree_with_merge()
+ the_branch = tree.branch
+
+ self.assertEqual({'rev-1':(1,), 'rev-2':(2,), 'rev-3':(3,),
+ 'rev-1.1.1':(1,1,1)
+ }, tree.branch.get_revision_id_to_revno_map())
+
+
+class TestCaching(TestCaseWithBranch):
+ """Tests for the caching of branches' dotted revno generation.
+
+ When locked, branches should avoid regenerating revision_id=>dotted revno
+ mapping.
+
+ When not locked, obviously the revision_id => dotted revno will need to be
+ regenerated or reread each time.
+
+ We test if revision_history is using the cache by instrumenting the branch's
+ _gen_revno_map method, which is called by get_revision_id_to_revno_map.
+ """
+
+ def get_instrumented_branch(self):
+ """Get a branch and monkey patch it to log calls to _gen_revno_map.
+
+ :returns: a tuple of (the branch, list that calls will be logged to)
+ """
+ tree = self.create_tree_with_merge()
+ calls = []
+ real_func = tree.branch._gen_revno_map
+ def wrapper():
+ calls.append('_gen_revno_map')
+ return real_func()
+ tree.branch._gen_revno_map = wrapper
+ return tree.branch, calls
+
+ def test_unlocked(self):
+ """Repeated calls will call _gen_revno_map each time."""
+ branch, calls = self.get_instrumented_branch()
+ # Repeatedly call revision_history.
+ branch.get_revision_id_to_revno_map()
+ branch.get_revision_id_to_revno_map()
+ branch.get_revision_id_to_revno_map()
+ self.assertEqual(['_gen_revno_map']*3, calls)
+
+ def test_locked(self):
+ """Repeated calls will only call _gen_revno_map once.
+ """
+ branch, calls = self.get_instrumented_branch()
+ # Lock the branch, then repeatedly call revision_history.
+ branch.lock_read()
+ try:
+ branch.get_revision_id_to_revno_map()
+ self.assertEqual(['_gen_revno_map'], calls)
+ finally:
+ branch.unlock()
+
+ def test_set_revision_history_when_locked(self):
+ """Calling set_revision_history should reset the cache."""
+ branch, calls = self.get_instrumented_branch()
+ branch.lock_write()
+ try:
+ self.assertEqual({'rev-1':(1,), 'rev-2':(2,), 'rev-3':(3,),
+ 'rev-1.1.1':(1,1,1)
+ }, branch.get_revision_id_to_revno_map())
+ branch.set_revision_history(['rev-1', 'rev-2'])
+ self.assertEqual({'rev-1':(1,), 'rev-2':(2,)},
+ branch.get_revision_id_to_revno_map())
+ self.assertEqual({'rev-1':(1,), 'rev-2':(2,)},
+ branch.get_revision_id_to_revno_map())
+ self.assertEqual(['_gen_revno_map']*2, calls)
+ finally:
+ branch.unlock()
+
+ def test_set_last_revision_info_when_locked(self):
+ """Calling set_last_revision_info should reset the cache."""
+ branch, calls = self.get_instrumented_branch()
+ branch.lock_write()
+ try:
+ self.assertEqual({'rev-1':(1,), 'rev-2':(2,), 'rev-3':(3,),
+ 'rev-1.1.1':(1,1,1)
+ }, branch.get_revision_id_to_revno_map())
+ branch.set_last_revision_info(2, 'rev-2')
+ self.assertEqual({'rev-1':(1,), 'rev-2':(2,)},
+ branch.get_revision_id_to_revno_map())
+ self.assertEqual({'rev-1':(1,), 'rev-2':(2,)},
+ branch.get_revision_id_to_revno_map())
+ self.assertEqual(['_gen_revno_map']*2, calls)
+ finally:
+ branch.unlock()
=== added file 'bzrlib/tests/branch_implementations/test_revision_id_to_revno.py'
--- a/bzrlib/tests/branch_implementations/test_revision_id_to_revno.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/branch_implementations/test_revision_id_to_revno.py 2007-04-17 20:23:35 +0000
@@ -0,0 +1,41 @@
+# Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Tests for Branch.revision_id_to_revno()"""
+
+from bzrlib import errors
+
+from bzrlib.tests.branch_implementations import TestCaseWithBranch
+
+
+class TestRevisionIdToRevno(TestCaseWithBranch):
+
+ def test_simple_revno(self):
+ tree = self.create_tree_with_merge()
+ the_branch = tree.branch
+
+ self.assertEqual(0, the_branch.revision_id_to_revno(None))
+ self.assertEqual(1, the_branch.revision_id_to_revno('rev-1'))
+ self.assertEqual(2, the_branch.revision_id_to_revno('rev-2'))
+ self.assertEqual(3, the_branch.revision_id_to_revno('rev-3'))
+
+ self.assertRaises(errors.NoSuchRevision,
+ the_branch.revision_id_to_revno, 'rev-none')
+ # revision_id_to_revno is defined as returning only integer revision
+ # numbers, so non-mainline revisions get NoSuchRevision raised
+ self.assertRaises(errors.NoSuchRevision,
+ the_branch.revision_id_to_revno, 'rev-1.1.1')
+
=== modified file 'NEWS'
--- a/NEWS 2007-04-24 05:02:04 +0000
+++ b/NEWS 2007-04-24 22:44:26 +0000
@@ -140,6 +140,12 @@
* New class 'TransportListRegistry', derived from the Registry class, which
simplifies tracking the available Transports. (Goffredo Baroncelli)
+ * New function ``Branch.get_revision_id_to_revno_map`` which will
+ return a dictionary mapping revision ids to dotted revnos. Since
+ dotted revnos are defined in the context of the branch tip, it makes
+ sense to generate them from a ``Branch`` object.
+ (John Arbash Meinel)
+
BUGFIXES:
* Don't fail bundle selftest if email has 'two' embedded.
=== modified file 'bzrlib/annotate.py'
--- a/bzrlib/annotate.py 2007-02-02 09:17:23 +0000
+++ b/bzrlib/annotate.py 2007-04-17 21:19:29 +0000
@@ -89,16 +89,7 @@
This includes detailed information, such as the committer name, and
date string for the commit, rather than just the revision id.
"""
- branch_last_revision = branch.last_revision()
- revision_graph = branch.repository.get_revision_graph(branch_last_revision)
- merge_sorted_revisions = tsort.merge_sort(
- revision_graph,
- branch_last_revision,
- None,
- generate_revno=True)
- revision_id_to_revno = dict((rev_id, revno)
- for seq_num, rev_id, depth, revno, end_of_merge
- in merge_sorted_revisions)
+ revision_id_to_revno = branch.get_revision_id_to_revno_map()
w = branch.repository.weave_store.get_weave(file_id,
branch.repository.get_transaction())
last_origin = None
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2007-04-18 05:10:19 +0000
+++ b/bzrlib/branch.py 2007-04-24 19:43:09 +0000
@@ -35,6 +35,7 @@
revision as _mod_revision,
transport,
tree,
+ tsort,
ui,
urlutils,
)
@@ -100,6 +101,7 @@
def __init__(self, *ignored, **ignored_too):
self.tags = self._make_tags()
self._revision_history_cache = None
+ self._revision_id_to_revno_cache = None
def break_lock(self):
"""Break a lock if one is present from another instance.
@@ -195,6 +197,48 @@
def get_physical_lock_status(self):
raise NotImplementedError(self.get_physical_lock_status)
+ @needs_read_lock
+ def get_revision_id_to_revno_map(self):
+ """Return the revision_id => dotted revno map.
+
+ This will be regenerated on demand, but will be cached.
+
+ :return: A dictionary mapping revision_id => dotted revno.
+ This dictionary should not be modified by the caller.
+ """
+ if self._revision_id_to_revno_cache is not None:
+ mapping = self._revision_id_to_revno_cache
+ else:
+ mapping = self._gen_revno_map()
+ self._cache_revision_id_to_revno(mapping)
+ # TODO: jam 20070417 Since this is being cached, should we be returning
+ # a copy?
+ # I would rather not, and instead just declare that users should not
+ # modify the return value.
+ return mapping
+
+ def _gen_revno_map(self):
+ """Create a new mapping from revision ids to dotted revnos.
+
+ Dotted revnos are generated based on the current tip in the revision
+ history.
+ This is the worker function for get_revision_id_to_revno_map, which
+ just caches the return value.
+
+ :return: A dictionary mapping revision_id => dotted revno.
+ """
+ last_revision = self.last_revision()
+ revision_graph = self.repository.get_revision_graph(last_revision)
+ merge_sorted_revisions = tsort.merge_sort(
+ revision_graph,
+ last_revision,
+ None,
+ generate_revno=True)
+ revision_id_to_revno = dict((rev_id, revno)
+ for seq_num, rev_id, depth, revno, end_of_merge
+ in merge_sorted_revisions)
+ return revision_id_to_revno
+
def leave_lock_in_place(self):
"""Tell this branch object not to release the physical lock when this
object is unlocked.
@@ -344,6 +388,14 @@
"""
self._revision_history_cache = rev_history
+ def _cache_revision_id_to_revno(self, revision_id_to_revno):
+ """Set the cached revision_id => revno map to revision_id_to_revno.
+
+ This API is semi-public; it only for use by subclasses, all other code
+ should consider it to be private.
+ """
+ self._revision_id_to_revno_cache = revision_id_to_revno
+
def _clear_cached_state(self):
"""Clear any cached data on this branch, e.g. cached revision history.
@@ -354,6 +406,7 @@
should consider it to be private.
"""
self._revision_history_cache = None
+ self._revision_id_to_revno_cache = None
def _gen_revision_history(self):
"""Return sequence of revision hashes on to this branch.
@@ -461,7 +514,7 @@
try:
return history.index(revision_id) + 1
except ValueError:
- raise bzrlib.errors.NoSuchRevision(self, revision_id)
+ raise errors.NoSuchRevision(self, revision_id)
def get_rev_id(self, revno, history=None):
"""Find the revision id of the specified revno."""
@@ -470,7 +523,7 @@
if history is None:
history = self.revision_history()
if revno <= 0 or revno > len(history):
- raise bzrlib.errors.NoSuchRevision(self, revno)
+ raise errors.NoSuchRevision(self, revno)
return history[revno - 1]
def pull(self, source, overwrite=False, stop_revision=None):
@@ -1325,6 +1378,7 @@
def set_revision_history(self, rev_history):
"""See Branch.set_revision_history."""
rev_history = [osutils.safe_revision_id(r) for r in rev_history]
+ self._clear_cached_state()
self._write_revision_history(rev_history)
self._cache_revision_history(rev_history)
for hook in Branch.hooks['set_rh']:
@@ -1542,7 +1596,7 @@
try:
url = url.encode('ascii')
except UnicodeEncodeError:
- raise bzrlib.errors.InvalidURL(url,
+ raise errors.InvalidURL(url,
"Urls must be 7-bit ascii, "
"use bzrlib.urlutils.escape")
url = urlutils.relative_url(self.base, url)
=== modified file 'bzrlib/memorytree.py'
--- a/bzrlib/memorytree.py 2007-02-06 14:52:16 +0000
+++ b/bzrlib/memorytree.py 2007-04-17 20:10:04 +0000
@@ -222,18 +222,29 @@
else:
raise errors.NoSuchId(self, file_id)
+ def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
+ """See MutableTree.set_parent_trees()."""
+ if len(revision_ids) == 0:
+ self._parent_ids = []
+ self._basis_tree = self.branch.repository.revision_tree(None)
+ else:
+ self._parent_ids = revision_ids
+ self._basis_tree = self.branch.repository.revision_tree(
+ revision_ids[0])
+ self._branch_revision_id = revision_ids[0]
+
def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
"""See MutableTree.set_parent_trees()."""
if len(parents_list) == 0:
self._parent_ids = []
- self._basis_tree = self.branch.repository.revisiontree(None)
+ self._basis_tree = self.branch.repository.revision_tree(None)
else:
if parents_list[0][1] is None and not allow_leftmost_as_ghost:
# a ghost in the left most parent
raise errors.GhostRevisionUnusableHere(parents_list[0][0])
self._parent_ids = [parent_id for parent_id, tree in parents_list]
if parents_list[0][1] is None:
- self._basis_tree = self.branch.repository.revisiontree(None)
+ self._basis_tree = self.branch.repository.revision_tree(None)
else:
self._basis_tree = parents_list[0][1]
self._branch_revision_id = parents_list[0][0]
=== modified file 'bzrlib/mutabletree.py'
--- a/bzrlib/mutabletree.py 2007-04-02 17:55:02 +0000
+++ b/bzrlib/mutabletree.py 2007-04-17 20:10:04 +0000
@@ -245,6 +245,13 @@
"""
raise NotImplementedError(self.mkdir)
+ def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
+ """Set the parents ids of the working tree.
+
+ :param revision_ids: A list of revision_ids.
+ """
+ raise NotImplementedError(self.set_parent_ids)
+
def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
"""Set the parents of the working tree.
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2007-04-23 08:30:30 +0000
+++ b/bzrlib/remote.py 2007-04-24 19:40:13 +0000
@@ -901,6 +901,7 @@
rev_id = 'null:'
else:
rev_id = rev_history[-1]
+ self._clear_cached_state()
response = self._client.call('Branch.set_last_revision',
path, self._lock_token, self._repo_lock_token, rev_id)
if response[0] == 'NoSuchRevision':
=== modified file 'bzrlib/revisionspec.py'
--- a/bzrlib/revisionspec.py 2007-03-12 16:29:47 +0000
+++ b/bzrlib/revisionspec.py 2007-04-17 21:26:08 +0000
@@ -321,14 +321,10 @@
if dotted:
branch.lock_read()
try:
- last_rev = branch.last_revision()
- merge_sorted_revisions = tsort.merge_sort(
- branch.repository.get_revision_graph(last_rev),
- last_rev,
- generate_revno=True)
- def match(item):
- return item[3] == match_revno
- revisions = filter(match, merge_sorted_revisions)
+ revision_id_to_revno = branch.get_revision_id_to_revno_map()
+ revisions = [revision_id for revision_id, revno
+ in revision_id_to_revno.iteritems()
+ if revno == match_revno]
finally:
branch.unlock()
if len(revisions) != 1:
@@ -336,7 +332,7 @@
else:
# there is no traditional 'revno' for dotted-decimal revnos.
# so for API compatability we return None.
- return RevisionInfo(branch, None, revisions[0][1])
+ return RevisionInfo(branch, None, revisions[0])
else:
if revno < 0:
# if get_rev_id supported negative revnos, there would not be a
=== modified file 'bzrlib/tests/branch_implementations/__init__.py'
--- a/bzrlib/tests/branch_implementations/__init__.py 2007-04-18 05:38:31 +0000
+++ b/bzrlib/tests/branch_implementations/__init__.py 2007-04-24 19:45:05 +0000
@@ -24,31 +24,91 @@
rather than in tests/branch_implementations/*.py.
"""
+from bzrlib import (
+ errors,
+ tests,
+ )
from bzrlib.branch import (BranchFormat,
BranchTestProviderAdapter,
_legacy_formats,
)
+from bzrlib.remote import RemoteBranchFormat, RemoteBzrDirFormat
from bzrlib.smart.server import (
SmartTCPServer_for_testing,
ReadonlySmartTCPServer_for_testing,
)
-from bzrlib.tests import (
- adapt_modules,
- TestLoader,
- TestSuite,
- )
-from bzrlib.remote import RemoteBranchFormat, RemoteBzrDirFormat
+from bzrlib.tests.bzrdir_implementations.test_bzrdir import TestCaseWithBzrDir
from bzrlib.transport.memory import MemoryServer
+class TestCaseWithBranch(TestCaseWithBzrDir):
+ """This helper will be adapted for each branch_implementation test."""
+
+ def setUp(self):
+ super(TestCaseWithBranch, self).setUp()
+ self.branch = None
+
+ def get_branch(self):
+ if self.branch is None:
+ self.branch = self.make_branch('')
+ return self.branch
+
+ def make_branch(self, relpath, format=None):
+ repo = self.make_repository(relpath, format=format)
+ # fixme RBC 20060210 this isnt necessarily a fixable thing,
+ # Skipped is the wrong exception to raise.
+ try:
+ return self.branch_format.initialize(repo.bzrdir)
+ except errors.UninitializableFormat:
+ raise tests.TestSkipped('Uninitializable branch format')
+
+ def make_repository(self, relpath, shared=False, format=None):
+ made_control = self.make_bzrdir(relpath, format=format)
+ return made_control.create_repository(shared=shared)
+
+ def create_tree_with_merge(self):
+ """Create a branch with a simple ancestry.
+
+ The graph should look like:
+ digraph H {
+ "rev-1" -> "rev-2" -> "rev-3";
+ "rev-1" -> "rev-1.1.1" -> "rev-3";
+ }
+
+ Or in ASCII:
+ 1
+ |\
+ 2 1.1.1
+ |/
+ 3
+ """
+ tree = self.make_branch_and_memory_tree('tree')
+ tree.lock_write()
+ try:
+ tree.add('')
+ tree.commit('first', rev_id='rev-1')
+ tree.commit('second', rev_id='rev-1.1.1')
+ # Uncommit that last commit and switch to the other line
+ tree.branch.set_last_revision_info(1, 'rev-1')
+ tree.set_parent_ids(['rev-1'])
+ tree.commit('alt-second', rev_id='rev-2')
+ tree.set_parent_ids(['rev-2', 'rev-1.1.1'])
+ tree.commit('third', rev_id='rev-3')
+ finally:
+ tree.unlock()
+
+ return tree
+
+
def test_suite():
- result = TestSuite()
+ result = tests.TestSuite()
test_branch_implementations = [
'bzrlib.tests.branch_implementations.test_bound_sftp',
'bzrlib.tests.branch_implementations.test_branch',
'bzrlib.tests.branch_implementations.test_break_lock',
'bzrlib.tests.branch_implementations.test_create_checkout',
'bzrlib.tests.branch_implementations.test_commit',
+ 'bzrlib.tests.branch_implementations.test_get_revision_id_to_revno_map',
'bzrlib.tests.branch_implementations.test_hooks',
'bzrlib.tests.branch_implementations.test_http',
'bzrlib.tests.branch_implementations.test_last_revision_info',
@@ -58,6 +118,7 @@
'bzrlib.tests.branch_implementations.test_pull',
'bzrlib.tests.branch_implementations.test_push',
'bzrlib.tests.branch_implementations.test_revision_history',
+ 'bzrlib.tests.branch_implementations.test_revision_id_to_revno',
'bzrlib.tests.branch_implementations.test_tags',
'bzrlib.tests.branch_implementations.test_uncommit',
'bzrlib.tests.branch_implementations.test_update',
@@ -73,9 +134,8 @@
# by the TestCaseWithTransport.get_readonly_transport method.
None,
combinations)
- loader = TestLoader()
- adapt_modules(test_branch_implementations, adapter, loader, result)
-
+ loader = tests.TestLoader()
+ tests.adapt_modules(test_branch_implementations, adapter, loader, result)
adapt_to_smart_server = BranchTestProviderAdapter(
SmartTCPServer_for_testing,
@@ -83,9 +143,9 @@
[(RemoteBranchFormat(), RemoteBzrDirFormat())],
MemoryServer
)
- adapt_modules(test_branch_implementations,
- adapt_to_smart_server,
- loader,
- result)
+ tests.adapt_modules(test_branch_implementations,
+ adapt_to_smart_server,
+ loader,
+ result)
return result
=== modified file 'bzrlib/tests/branch_implementations/test_branch.py'
--- a/bzrlib/tests/branch_implementations/test_branch.py 2007-04-13 07:39:17 +0000
+++ b/bzrlib/tests/branch_implementations/test_branch.py 2007-04-24 03:23:27 +0000
@@ -40,7 +40,7 @@
from bzrlib.osutils import getcwd
import bzrlib.revision
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
-from bzrlib.tests.bzrdir_implementations.test_bzrdir import TestCaseWithBzrDir
+from bzrlib.tests.branch_implementations import TestCaseWithBranch
from bzrlib.tests.HttpServer import HttpServer
from bzrlib.trace import mutter
from bzrlib.transport import get_transport
@@ -49,31 +49,6 @@
from bzrlib.workingtree import WorkingTree
-class TestCaseWithBranch(TestCaseWithBzrDir):
-
- def setUp(self):
- super(TestCaseWithBranch, self).setUp()
- self.branch = None
-
- def get_branch(self):
- if self.branch is None:
- self.branch = self.make_branch('')
- return self.branch
-
- def make_branch(self, relpath, format=None):
- repo = self.make_repository(relpath, format=format)
- # fixme RBC 20060210 this isnt necessarily a fixable thing,
- # Skipped is the wrong exception to raise.
- try:
- return self.branch_format.initialize(repo.bzrdir)
- except errors.UninitializableFormat:
- raise TestSkipped('Uninitializable branch format')
-
- def make_repository(self, relpath, shared=False, format=None):
- made_control = self.make_bzrdir(relpath, format=format)
- return made_control.create_repository(shared=shared)
-
-
class TestBranch(TestCaseWithBranch):
def test_append_revisions(self):
@@ -91,6 +66,15 @@
self.assertEquals(br.revision_history(), ["rev1", "rev2", "rev3"])
self.assertRaises(errors.ReservedId, br.append_revision, 'current:')
+ def test_create_tree_with_merge(self):
+ tree = self.create_tree_with_merge()
+ ancestry_graph = tree.branch.repository.get_revision_graph('rev-3')
+ self.assertEqual({'rev-1':[],
+ 'rev-2':['rev-1'],
+ 'rev-1.1.1':['rev-1'],
+ 'rev-3':['rev-2', 'rev-1.1.1'],
+ }, ancestry_graph)
+
def test_revision_ids_are_utf8(self):
wt = self.make_branch_and_tree('tree')
wt.commit('f', rev_id='rev1')
More information about the bazaar-commits
mailing list