Rev 3428: Add bzrlib.missing.find_unmerged_mainline_revisions in http://bzr.arbash-meinel.com/branches/bzr/1.6-dev/missing
John Arbash Meinel
john at arbash-meinel.com
Mon May 19 21:35:48 BST 2008
At http://bzr.arbash-meinel.com/branches/bzr/1.6-dev/missing
------------------------------------------------------------
revno: 3428
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
-------------- next part --------------
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2008-05-09 06:46:17 +0000
+++ b/bzrlib/builtins.py 2008-05-19 20:35:37 +0000
@@ -3330,8 +3330,25 @@
try:
remote_branch.lock_read()
try:
- local_extra, remote_extra = find_unmerged(local_branch,
- remote_branch)
+ graph = local_branch.repository.get_graph(
+ remote_branch.repository)
+ local_revision_id = local_branch.last_revision()
+ remote_revision_id = remote_branch.last_revision()
+ if theirs_only:
+ local_extra = None
+ remote_extra = graph.find_unique_ancestors(
+ remote_revision_id, [local_revision_id])
+ elif mine_only:
+ remote_extra = None
+ local_extra = graph.find_unique_ancestors(
+ local_revision_id, [remote_revision_id])
+ else:
+ local_extra, remote_extra = graph.find_difference(
+ local_revision_id, remote_revision_id)
+ # We now have the set of local and remote revisions, but they
+ # are not sorted. They also include all merged revisions, while
+ # missing only shows the mainline revisions.
+
if log_format is None:
registry = log.log_formatter_registry
log_format = registry.get_default(local_branch)
=== modified file 'bzrlib/missing.py'
--- a/bzrlib/missing.py 2008-05-02 07:31:24 +0000
+++ b/bzrlib/missing.py 2008-05-19 20:35:37 +0000
@@ -85,6 +85,86 @@
progress.finished()
return (local_extra, remote_extra)
+
+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 mailine
+ :return: [(revno, revision_id)] for all revisions in ancestry that
+ left-hand parents from tip
+ """
+ if ancestry is None:
+ return None
+ 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])
+ if cur not in parent_map:
+ break # Ghost, we are done
+ mainline.append((cur_revno, cur))
+ cur = parent_map[cur]
+ cur_revno -= 1
+ mainline.reverse()
+ return mainline
+
+
+def find_unmerged_mainline_revisions(local_branch, remote_branch, restrict):
+ """Find revisions from each side that have not been merged.
+
+ Both branches should already be locked.
+
+ :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.
+ """
+ graph = local_branch.repository.get_graph(
+ remote_branch.repository)
+ 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 [], []
+ 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:
+ 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 _shortcut(local_rev_history, remote_rev_history):
local_history = set(local_rev_history)
remote_history = set(remote_rev_history)
=== 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 20:35:37 +0000
@@ -17,6 +17,10 @@
import os
+from bzrlib import (
+ missing,
+ tests,
+ )
from bzrlib.missing import (
find_unmerged,
iter_log_revisions,
@@ -123,3 +127,48 @@
self.assertEqual([('b', 'c', 'b-id', 'file', False, False)],
delta3.renamed)
self.assertEqual([], delta3.modified)
+
+
+class TestFindUnmergedMainlineRevisions(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_mainline_revisions(
+ 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')
+
More information about the bazaar-commits
mailing list