Rev 3441: (jam) 'bzr missing' uses Graph.find* rather than using whole ancestry in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue May 20 22:00:41 BST 2008
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3441
revision-id:pqm at pqm.ubuntu.com-20080520210027-wetfxldz1ggc5u2a
parent: pqm at pqm.ubuntu.com-20080520094809-682f95w1gbrji5t0
parent: john at arbash-meinel.com-20080520182859-tvhy5hjx3jnlfzk6
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2008-05-20 22:00:27 +0100
message:
(jam) 'bzr missing' uses Graph.find* rather than using whole ancestry
comparisons (bug #174625)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/missing.py missing.py-20050812153334-097f7097e2a8bcd1
bzrlib/tests/blackbox/test_missing.py test_missing.py-20051211212735-a2cf4c1840bb84c4
bzrlib/tests/test_missing.py test_missing.py-20051212000028-694fa4f658a81f48
------------------------------------------------------------
revno: 3427.3.8
revision-id:john at arbash-meinel.com-20080520182859-tvhy5hjx3jnlfzk6
parent: john at arbash-meinel.com-20080520181835-kw4sd2fzblnw23mj
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Tue 2008-05-20 13:28:59 -0500
message:
Change the output to 'This branch' and 'Other branch', and document the text in NEWS
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/tests/blackbox/test_missing.py test_missing.py-20051211212735-a2cf4c1840bb84c4
------------------------------------------------------------
revno: 3427.3.7
revision-id:john at arbash-meinel.com-20080520181835-kw4sd2fzblnw23mj
parent: john at arbash-meinel.com-20080520023401-42mkw5g7dhq9f5bh
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Tue 2008-05-20 13:18:35 -0500
message:
Update how 'bzr missing' works when given --mine-only or --theirs-only
It used to always determine missing revisions on both sides, and then just suppress
displaying them if the flag was given. It would also return status 1 if either side
had extra revisions. However, if you are asking for --mine-only, it doesn't make sense
to return status 1 when the local branch has nothing new.
And the new code doesn't know whether there are new revisions on the other side anyway.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/tests/blackbox/test_missing.py test_missing.py-20051211212735-a2cf4c1840bb84c4
------------------------------------------------------------
revno: 3427.3.6
revision-id:john at arbash-meinel.com-20080520023401-42mkw5g7dhq9f5bh
parent: john at arbash-meinel.com-20080519214725-z6g0mq5tsibsbrfj
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Mon 2008-05-19 21:34:01 -0500
message:
review feedback from Ian
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/missing.py missing.py-20050812153334-097f7097e2a8bcd1
------------------------------------------------------------
revno: 3427.3.5
revision-id:john at arbash-meinel.com-20080519214725-z6g0mq5tsibsbrfj
parent: john at arbash-meinel.com-20080519214254-aolweqts5hzrn879
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Mon 2008-05-19 16:47:25 -0500
message:
NEWS about fixing bug #174625
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 3427.3.4
revision-id:john at arbash-meinel.com-20080519214254-aolweqts5hzrn879
parent: john at arbash-meinel.com-20080519213939-7d47qehv3kez1gfx
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Mon 2008-05-19 16:42:54 -0500
message:
Fix cmd_missing for --this or --other
modified:
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
------------------------------------------------------------
revno: 3427.3.3
revision-id:john at arbash-meinel.com-20080519213939-7d47qehv3kez1gfx
parent: john at arbash-meinel.com-20080519213552-8jc1yc4w8rqhgzri
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Mon 2008-05-19 16:39:39 -0500
message:
Revert cmd_missing to use the original function, only now supply restrict
modified:
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
------------------------------------------------------------
revno: 3427.3.2
revision-id:john at arbash-meinel.com-20080519213552-8jc1yc4w8rqhgzri
parent: john at arbash-meinel.com-20080519203537-6dqmxtn6fxlk1ter
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Mon 2008-05-19 16:35:52 -0500
message:
switch find_unmerged to use the new function
The api is very compatible, so we don't really need to expose a new function.
So make it hidden, and leave find_unmerged to take out the write lock and call it.
modified:
bzrlib/missing.py missing.py-20050812153334-097f7097e2a8bcd1
bzrlib/tests/test_missing.py test_missing.py-20051212000028-694fa4f658a81f48
------------------------------------------------------------
revno: 3427.3.1
revision-id:john at arbash-meinel.com-20080519203537-6dqmxtn6fxlk1ter
parent: pqm at pqm.ubuntu.com-20080512115743-6uz3lnmrrbhmoiqe
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: missing
timestamp: Mon 2008-05-19 15:35:37 -0500
message:
Add bzrlib.missing.find_unmerged_mainline_revisions
This is a helper function that is designed to give 'missing' what it wants
without having to search all of ancestry.
modified:
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/missing.py missing.py-20050812153334-097f7097e2a8bcd1
bzrlib/tests/test_missing.py test_missing.py-20051212000028-694fa4f658a81f48
=== modified file 'NEWS'
--- a/NEWS 2008-05-20 07:16:50 +0000
+++ b/NEWS 2008-05-20 21:00:27 +0000
@@ -31,6 +31,10 @@
IMPROVEMENTS:
+ * ``bzr missing`` uses the new ``Graph.find_unique_ancestors`` and
+ ``Graph.find_differences`` to determine missing revisions without having
+ to search the whole ancestry. (John Arbash Meinel, #174625)
+
BUGFIXES:
* Correctly track the base URL of a smart medium when using bzr+http://
@@ -68,6 +72,13 @@
API BREAKS:
+ * ``bzr missing --mine-only`` will return status code 0 if you have no
+ new revisions, but the remote does. Similarly for ``--theirs-only``.
+ The new code only checks one side, so it doesn't know if the other
+ side has changes. This seems more accurate with the request anyway.
+ It also changes the output to print '[This|Other] branch is up to
+ date.' rather than displaying nothing. (John Arbash Meinel)
+
* Many methods on ``VersionedFile``, ``Repository`` and in
``bzrlib.revision`` deprecated before bzrlib 1.5 have been removed.
(Robert Collins)
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2008-05-09 06:46:17 +0000
+++ b/bzrlib/builtins.py 2008-05-20 18:28:59 +0000
@@ -3308,9 +3308,17 @@
from bzrlib.missing import find_unmerged, iter_log_revisions
if this:
- mine_only = this
+ mine_only = this
if other:
- theirs_only = other
+ theirs_only = other
+ # TODO: We should probably check that we don't have mine-only and
+ # theirs-only set, but it gets complicated because we also have
+ # this and other which could be used.
+ restrict = 'all'
+ if mine_only:
+ restrict = 'local'
+ elif theirs_only:
+ restrict = 'remote'
local_branch = Branch.open_containing(u".")[0]
parent = local_branch.get_parent()
@@ -3330,8 +3338,9 @@
try:
remote_branch.lock_read()
try:
- local_extra, remote_extra = find_unmerged(local_branch,
- remote_branch)
+ local_extra, remote_extra = find_unmerged(
+ local_branch, remote_branch, restrict)
+
if log_format is None:
registry = log.log_formatter_registry
log_format = registry.get_default(local_branch)
@@ -3339,8 +3348,12 @@
show_ids=show_ids,
show_timezone='original')
if reverse is False:
- local_extra.reverse()
- remote_extra.reverse()
+ if local_extra is not None:
+ local_extra.reverse()
+ if remote_extra is not None:
+ remote_extra.reverse()
+
+ status_code = 0
if local_extra and not theirs_only:
self.outf.write("You have %d extra revision(s):\n" %
len(local_extra))
@@ -3349,8 +3362,10 @@
verbose):
lf.log_revision(revision)
printed_local = True
+ status_code = 1
else:
printed_local = False
+
if remote_extra and not mine_only:
if printed_local is True:
self.outf.write("\n\n\n")
@@ -3360,11 +3375,19 @@
remote_branch.repository,
verbose):
lf.log_revision(revision)
- if not remote_extra and not local_extra:
- status_code = 0
+ status_code = 1
+
+ if mine_only and not local_extra:
+ # We checked local, and found nothing extra
+ self.outf.write('This branch is up to date.\n')
+ elif theirs_only and not remote_extra:
+ # We checked remote, and found nothing extra
+ self.outf.write('Other branch is up to date.\n')
+ elif not (mine_only or theirs_only or local_extra or
+ remote_extra):
+ # We checked both branches, and neither one had extra
+ # revisions
self.outf.write("Branches are up to date.\n")
- else:
- status_code = 1
finally:
remote_branch.unlock()
finally:
=== modified file 'bzrlib/missing.py'
--- a/bzrlib/missing.py 2008-05-02 07:31:24 +0000
+++ b/bzrlib/missing.py 2008-05-20 02:34:01 +0000
@@ -16,7 +16,6 @@
"""Display what revisions are missing in 'other' from 'this' and vice versa."""
-from bzrlib import ui
from bzrlib.log import (
LogRevision,
)
@@ -43,82 +42,100 @@
yield LogRevision(rev, revno, delta=delta)
-def find_unmerged(local_branch, remote_branch):
- progress = ui.ui_factory.nested_progress_bar()
+def find_unmerged(local_branch, remote_branch, restrict='all'):
+ """Find revisions from each side that have not been merged.
+
+ :param local_branch: Compare the history of local_branch
+ :param remote_branch: versus the history of remote_branch, and determine
+ mainline revisions which have not been merged.
+ :param restrict: ('all', 'local', 'remote') If 'all', we will return the
+ unique revisions from both sides. If 'local', we will return None
+ for the remote revisions, similarly if 'remote' we will return None for
+ the local revisions.
+
+ :return: A list of [(revno, revision_id)] for the mainline revisions on
+ each side.
+ """
local_branch.lock_read()
try:
remote_branch.lock_read()
try:
- # check for special case: both branches are equivalent
- if (local_branch.last_revision_info() ==
- remote_branch.last_revision_info()):
- return [], []
- local_rev_history, local_rev_history_map = \
- _get_history(local_branch, progress, "local", 0)
- remote_rev_history, remote_rev_history_map = \
- _get_history(remote_branch, progress, "remote", 1)
- result = _shortcut(local_rev_history, remote_rev_history)
- if result is not None:
- local_extra, remote_extra = result
- local_extra = sorted_revisions(local_extra,
- local_rev_history_map)
- remote_extra = sorted_revisions(remote_extra,
- remote_rev_history_map)
- return local_extra, remote_extra
-
- local_ancestry = _get_ancestry(local_branch.repository, progress,
- "local", 2, local_rev_history)
- remote_ancestry = _get_ancestry(remote_branch.repository, progress,
- "remote", 3, remote_rev_history)
- progress.update('pondering', 4, 5)
- extras = local_ancestry.symmetric_difference(remote_ancestry)
- local_extra = extras.intersection(set(local_rev_history))
- remote_extra = extras.intersection(set(remote_rev_history))
- local_extra = sorted_revisions(local_extra, local_rev_history_map)
- remote_extra = sorted_revisions(remote_extra,
- remote_rev_history_map)
-
+ return _find_unmerged(local_branch,
+ remote_branch, restrict=restrict)
finally:
remote_branch.unlock()
finally:
local_branch.unlock()
- progress.finished()
- return (local_extra, remote_extra)
-
-def _shortcut(local_rev_history, remote_rev_history):
- local_history = set(local_rev_history)
- remote_history = set(remote_rev_history)
- if len(local_rev_history) == 0:
- return set(), remote_history
- elif len(remote_rev_history) == 0:
- return local_history, set()
- elif local_rev_history[-1] in remote_history:
- return set(), _after(remote_rev_history, local_rev_history)
- elif remote_rev_history[-1] in local_history:
- return _after(local_rev_history, remote_rev_history), set()
- else:
+
+
+def _enumerate_mainline(ancestry, graph, tip_revno, tip):
+ """Enumerate the mainline revisions for these revisions.
+
+ :param ancestry: A set of revisions that we care about
+ :param graph: A Graph which lets us find the parents for a revision
+ :param tip_revno: The revision number for the tip revision
+ :param tip: The tip of mainline
+ :return: [(revno, revision_id)] for all revisions in ancestry that
+ are left-hand parents from tip, or None if ancestry is None.
+ """
+ if ancestry is None:
return None
-
-def _after(larger_history, smaller_history):
- return set(larger_history[larger_history.index(smaller_history[-1])+1:])
-
-def _get_history(branch, progress, label, step):
- progress.update('%s history' % label, step, 5)
- rev_history = branch.revision_history()
- rev_history_map = dict(
- [(rev, rev_history.index(rev) + 1)
- for rev in rev_history])
- return rev_history, rev_history_map
-
-def _get_ancestry(repository, progress, label, step, rev_history):
- progress.update('%s ancestry' % label, step, 5)
- if len(rev_history) > 0:
- ancestry = set(repository.get_ancestry(rev_history[-1],
- topo_sorted=False))
+ if not ancestry: #Empty ancestry, no need to do any work
+ return []
+
+ # Optionally, we could make 1 call to graph.get_parent_map with all
+ # ancestors. However that will often check many more parents than we
+ # actually need, and the Graph is likely to already have the parents cached
+ # anyway.
+ mainline = []
+ cur = tip
+ cur_revno = tip_revno
+ while cur in ancestry:
+ parent_map = graph.get_parent_map([cur])
+ parents = parent_map.get(cur)
+ if not parents:
+ break # Ghost, we are done
+ mainline.append((cur_revno, cur))
+ cur = parents[0]
+ cur_revno -= 1
+ mainline.reverse()
+ return mainline
+
+
+def _find_unmerged(local_branch, remote_branch, restrict):
+ """See find_unmerged.
+
+ The branches should already be locked before entering.
+ """
+ local_revno, local_revision_id = local_branch.last_revision_info()
+ remote_revno, remote_revision_id = remote_branch.last_revision_info()
+ if local_revno == remote_revno and local_revision_id == remote_revision_id:
+ # A simple shortcut when the tips are at the same point
+ return [], []
+ graph = local_branch.repository.get_graph(
+ remote_branch.repository)
+ if restrict == 'remote':
+ local_extra = None
+ remote_extra = graph.find_unique_ancestors(
+ remote_revision_id, [local_revision_id])
+ elif restrict == 'local':
+ remote_extra = None
+ local_extra = graph.find_unique_ancestors(
+ local_revision_id, [remote_revision_id])
else:
- ancestry = set()
- return ancestry
-
+ if restrict != 'all':
+ raise ValueError('param restrict not one of "all", "local",'
+ ' "remote": %r' % (restrict,))
+ local_extra, remote_extra = graph.find_difference(
+ local_revision_id, remote_revision_id)
+ # Now that we have unique ancestors, compute just the mainline, and
+ # generate revnos for them.
+ local_mainline = _enumerate_mainline(local_extra, graph, local_revno,
+ local_revision_id)
+ remote_mainline = _enumerate_mainline(remote_extra, graph, remote_revno,
+ remote_revision_id)
+ return local_mainline, remote_mainline
+
def sorted_revisions(revisions, history_map):
revisions = [(history_map[r],r) for r in revisions]
=== modified file 'bzrlib/tests/blackbox/test_missing.py'
--- a/bzrlib/tests/blackbox/test_missing.py 2007-08-08 12:48:16 +0000
+++ b/bzrlib/tests/blackbox/test_missing.py 2008-05-20 18:28:59 +0000
@@ -77,9 +77,8 @@
lines2 = self.run_bzr('missing ../b --mine-only', retcode=1)[0]
lines2 = lines2.splitlines()
self.assertEqual(lines, lines2)
- lines3 = self.run_bzr('missing ../b --theirs-only', retcode=1)[0]
- lines3 = lines3.splitlines()
- self.assertEqual(0, len(lines3))
+ lines3 = self.run_bzr('missing ../b --theirs-only', retcode=0)[0]
+ self.assertEqualDiff('Other branch is up to date.\n', lines3)
# relative to a, missing the 'merge' commit
os.chdir('../b')
@@ -89,9 +88,8 @@
lines2 = self.run_bzr('missing ../a --theirs-only', retcode=1)[0]
lines2 = lines2.splitlines()
self.assertEqual(lines, lines2)
- lines3 = self.run_bzr('missing ../a --mine-only', retcode=1)[0]
- lines3 = lines3.splitlines()
- self.assertEqual(0, len(lines3))
+ lines3 = self.run_bzr('missing ../a --mine-only', retcode=0)[0]
+ self.assertEqualDiff('This branch is up to date.\n', lines3)
lines4 = self.run_bzr('missing ../a --short', retcode=1)[0]
lines4 = lines4.splitlines()
self.assertEqual(4, len(lines4))
@@ -109,9 +107,22 @@
self.assertEqual("modified:", lines8[-2])
self.assertEqual(" a", lines8[-1])
+ os.chdir('../a')
+ self.assertEqualDiff('Other branch is up to date.\n',
+ self.run_bzr('missing ../b --theirs-only')[0])
+
# after a pull we're back on track
b_tree.pull(a_branch)
- self.assertEqual("Branches are up to date.\n", self.run_bzr('missing ../a')[0])
+ self.assertEqualDiff("Branches are up to date.\n",
+ self.run_bzr('missing ../b')[0])
+ os.chdir('../b')
+ self.assertEqualDiff('Branches are up to date.\n',
+ self.run_bzr('missing ../a')[0])
+ # If you supply mine or theirs you only know one side is up to date
+ self.assertEqualDiff('This branch is up to date.\n',
+ self.run_bzr('missing ../a --mine-only')[0])
+ self.assertEqualDiff('Other branch is up to date.\n',
+ self.run_bzr('missing ../a --theirs-only')[0])
def test_missing_check_last_location(self):
# check that last location shown as filepath not file URL
=== modified file 'bzrlib/tests/test_missing.py'
--- a/bzrlib/tests/test_missing.py 2008-05-02 07:31:24 +0000
+++ b/bzrlib/tests/test_missing.py 2008-05-19 21:35:52 +0000
@@ -17,8 +17,11 @@
import os
+from bzrlib import (
+ missing,
+ tests,
+ )
from bzrlib.missing import (
- find_unmerged,
iter_log_revisions,
)
from bzrlib.tests import TestCaseWithTransport
@@ -27,6 +30,10 @@
class TestMissing(TestCaseWithTransport):
+ def assertUnmerged(self, expected, source, target, restrict='all'):
+ unmerged = missing.find_unmerged(source, target, restrict=restrict)
+ self.assertEqual(expected, unmerged)
+
def test_find_unmerged(self):
original_tree = self.make_branch_and_tree('original')
original = original_tree.branch
@@ -34,26 +41,26 @@
puller = puller_tree.branch
merger_tree = self.make_branch_and_tree('merger')
merger = merger_tree.branch
- self.assertEqual(find_unmerged(original, puller), ([], []))
+ self.assertUnmerged(([], []), original, puller)
original_tree.commit('a', rev_id='a')
- self.assertEqual(find_unmerged(original, puller), ([(1, u'a')], []))
+ self.assertUnmerged(([(1, 'a')], []), original, puller)
puller_tree.pull(original)
- self.assertEqual(find_unmerged(original, puller), ([], []))
+ self.assertUnmerged(([], []), original, puller)
merger_tree.pull(original)
original_tree.commit('b', rev_id='b')
original_tree.commit('c', rev_id='c')
- self.assertEqual(find_unmerged(original, puller), ([(2, u'b'),
- (3, u'c')], []))
+ self.assertUnmerged(([(2, 'b'), (3, 'c')], []),
+ original, puller)
puller_tree.pull(original)
- self.assertEqual(find_unmerged(original, puller), ([], []))
- self.assertEqual(find_unmerged(original, merger), ([(2, u'b'),
- (3, u'c')], []))
+ self.assertUnmerged(([], []), original, puller)
+ self.assertUnmerged(([(2, 'b'), (3, 'c')], []),
+ original, merger)
merger_tree.merge_from_branch(original)
- self.assertEqual(find_unmerged(original, merger), ([(2, u'b'),
- (3, u'c')], []))
+ self.assertUnmerged(([(2, 'b'), (3, 'c')], []),
+ original, merger)
merger_tree.commit('d', rev_id='d')
- self.assertEqual(find_unmerged(original, merger), ([], [(2, 'd')]))
+ self.assertUnmerged(([], [(2, 'd')]), original, merger)
def test_iter_log_revisions(self):
base_tree = self.make_branch_and_tree('base')
@@ -76,8 +83,8 @@
child_tree.rename_one('b', 'c')
child_tree.commit('rename b=>c', rev_id='c-5')
- base_extra, child_extra = find_unmerged(base_tree.branch,
- child_tree.branch)
+ base_extra, child_extra = missing.find_unmerged(base_tree.branch,
+ child_tree.branch)
results = list(iter_log_revisions(base_extra,
base_tree.branch.repository,
verbose=True))
@@ -123,3 +130,63 @@
self.assertEqual([('b', 'c', 'b-id', 'file', False, False)],
delta3.renamed)
self.assertEqual([], delta3.modified)
+
+
+class TestFindUnmerged(tests.TestCaseWithTransport):
+
+ def assertUnmerged(self, local, remote, local_branch, remote_branch,
+ restrict):
+ """Check the output of find_unmerged_mainline_revisions"""
+ local_extra, remote_extra = missing.find_unmerged(
+ local_branch, remote_branch, restrict)
+ self.assertEqual(local, local_extra)
+ self.assertEqual(remote, remote_extra)
+
+ def test_same_branch(self):
+ tree = self.make_branch_and_tree('tree')
+ rev1 = tree.commit('one')
+ tree.lock_read()
+ self.addCleanup(tree.unlock)
+ self.assertUnmerged([], [], tree.branch, tree.branch, 'all')
+
+ def test_one_ahead(self):
+ tree = self.make_branch_and_tree('tree')
+ rev1 = tree.commit('one')
+ tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
+ rev2 = tree2.commit('two')
+ tree.lock_read()
+ self.addCleanup(tree.unlock)
+ tree2.lock_read()
+ self.addCleanup(tree2.unlock)
+ self.assertUnmerged([], [(2, rev2)], tree.branch, tree2.branch, 'all')
+ self.assertUnmerged([(2, rev2)], [], tree2.branch, tree.branch, 'all')
+
+ def test_restrict(self):
+ tree = self.make_branch_and_tree('tree')
+ rev1 = tree.commit('one')
+ tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
+ rev2 = tree2.commit('two')
+ tree.lock_read()
+ self.addCleanup(tree.unlock)
+ tree2.lock_read()
+ self.addCleanup(tree2.unlock)
+ self.assertUnmerged([], [(2, rev2)], tree.branch, tree2.branch, 'all')
+ self.assertUnmerged([], None, tree.branch, tree2.branch, 'local')
+ self.assertUnmerged(None, [(2, rev2)], tree.branch, tree2.branch,
+ 'remote')
+
+ def test_merged(self):
+ tree = self.make_branch_and_tree('tree')
+ rev1 = tree.commit('one')
+ tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
+ rev2 = tree2.commit('two')
+ rev3 = tree2.commit('three')
+ tree.merge_from_branch(tree2.branch)
+ rev4 = tree.commit('four')
+
+ tree.lock_read()
+ self.addCleanup(tree.unlock)
+ tree2.lock_read()
+ self.addCleanup(tree2.unlock)
+
+ self.assertUnmerged([(2, rev4)], [], tree.branch, tree2.branch, 'all')
More information about the bazaar-commits
mailing list