Rev 2390: Start work on GraphDelta support. in file:///home/robertc/source/baz/netsim/

Robert Collins robertc at robertcollins.net
Sun Apr 1 07:19:41 BST 2007


At file:///home/robertc/source/baz/netsim/

------------------------------------------------------------
revno: 2390
revision-id: robertc at robertcollins.net-20070401061938-xzhb1m77i7fzzkb6
parent: robertc at robertcollins.net-20070401021622-c63kkszulpt30wae
committer: Robert Collins <robertc at robertcollins.net>
branch nick: netsim
timestamp: Sun 2007-04-01 16:19:38 +1000
message:
  Start work on GraphDelta support.
modified:
  bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
  bzrlib/graph.py                graph.py-20050905070950-b47dce53236c5e48
  bzrlib/tests/test_errors.py    test_errors.py-20060210110251-41aba2deddf936a8
  bzrlib/tests/test_graph.py     testgraph.py-20050905070950-42e6c958106610fd
=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py	2007-03-29 16:23:49 +0000
+++ b/bzrlib/errors.py	2007-04-01 06:19:38 +0000
@@ -255,6 +255,15 @@
         self.url = url
 
 
+class NotSubGraph(BzrError):
+
+    _fmt = "'%(to)s' is not a subgraph of '%(from_)s'."
+
+    def __init__(self, from_, to):
+        self.from_ = from_
+        self.to = to
+
+
 class WorkingTreeAlreadyPopulated(BzrError):
 
     _fmt = """Working tree already populated in %(base)s"""

=== modified file 'bzrlib/graph.py'
--- a/bzrlib/graph.py	2006-10-05 05:37:25 +0000
+++ b/bzrlib/graph.py	2007-04-01 06:19:38 +0000
@@ -15,6 +15,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 
+from bzrlib import errors
 from bzrlib.tsort import topo_sort
 
 
@@ -118,6 +119,9 @@
         self._graph_ancestors = {}
         self._graph_descendants = {}
 
+    def __eq__(self, other):
+        return isinstance(other, Graph) and self.__dict__ == other.__dict__
+
     def add_ghost(self, node_id):
         """Add a ghost to the graph."""
         self.ghosts.add(node_id)
@@ -132,7 +136,19 @@
         for parent in parent_ids:
             self._ensure_descendant(parent)
             self._graph_descendants[parent][node_id] = 1
-        
+
+    def apply_changes(self, delta):
+        """Apply a delta obtained from a changes_from call.
+
+        :return: A new graph which is the result of applying delta to this
+        graph.
+        """
+        return Graph()
+
+    def changes_from(self, graph_from):
+        """Create a GraphDelta from graph_from to self."""
+        return GraphDelta._changes_from(graph_from, self)
+
     def _ensure_descendant(self, node_id):
         """Ensure that a descendant lookup for node_id will work."""
         if not node_id in self._graph_descendants:
@@ -160,3 +176,21 @@
     def get_descendants(self):
         """Return a dictionary of graph node:child_node:distance entries."""
         return dict(self._graph_descendants.items())
+
+
+class GraphDelta(object):
+    """A delta between two DAG's. 
+
+    Currently this requires that the from DAG be a supergraph of the to DAG.
+    This restriction may be lifted in the future.
+    """
+
+    @classmethod
+    def _changes_from(cls, from_, to):
+        """Construct a delta from from_ to to."""
+        result = GraphDelta()
+        from_nodes = set(from_.get_ancestors())
+        to_nodes = set(to.get_ancestors())
+        if to_nodes.difference(from_nodes):
+            raise errors.NotSubGraph(from_, to)
+        return result

=== modified file 'bzrlib/tests/test_errors.py'
--- a/bzrlib/tests/test_errors.py	2007-03-14 20:47:17 +0000
+++ b/bzrlib/tests/test_errors.py	2007-04-01 06:19:38 +0000
@@ -99,6 +99,10 @@
             str(error))
         self.assertIsInstance(error, errors.NoSuchRevision)
 
+    def test_not_sub_graph(self):
+        error = errors.NotSubGraph("from", "to")
+        self.assertEqualDiff("'to' is not a subgraph of 'from'.", str(error))
+
     def test_not_write_locked(self):
         error = errors.NotWriteLocked('a thing to repr')
         self.assertEqualDiff("'a thing to repr' is not write locked but needs "

=== modified file 'bzrlib/tests/test_graph.py'
--- a/bzrlib/tests/test_graph.py	2006-10-11 23:08:27 +0000
+++ b/bzrlib/tests/test_graph.py	2007-04-01 06:19:38 +0000
@@ -14,8 +14,9 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+from bzrlib.errors import NotSubGraph
 from bzrlib.tests import TestCase
-from bzrlib.graph import node_distances, nodes_by_distance, Graph
+from bzrlib.graph import node_distances, nodes_by_distance, Graph, GraphDelta
 
 
 class TestBase(TestCase):
@@ -78,3 +79,21 @@
         # check the result contains ghosts:
         self.assertEqual({'ghost': {'rev1': 1}, 'rev1': {}},
                          graph.get_descendants())
+
+
+class TestGraphDelta(TestCase):
+
+    def testEmptyEmptyGraph(self):
+        graph_from = Graph()
+        graph_to = Graph()
+        delta = graph_to.changes_from(graph_from)
+        self.assertIsInstance(delta, GraphDelta)
+        new_to = graph_from.apply_changes(delta)
+        self.assertEqual(graph_to, new_to)
+
+    def testTargetNotSubGraph(self):
+        """When the target is not a sub-graph of the source, get an exception."""
+        graph_from = Graph()
+        graph_to = Graph()
+        graph_to.add_node('A', [])
+        self.assertRaises(NotSubGraph, graph_to.changes_from, graph_from)



More information about the bazaar-commits mailing list