~lifeless/bzrtools/trunk

« back to all changes in this revision

Viewing changes to graph.py

  • Committer: Robert Collins
  • Date: 2008-07-08 04:11:21 UTC
  • mfrom: (623.1.33 bzrtools)
  • Revision ID: robertc@robertcollins.net-20080708041121-lo0k7os2y03uclt2
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Aaron Bentley
 
1
# Copyright (C) 2005, 2008 Aaron Bentley
2
2
# <aaron@aaronbentley.com>
3
3
#
4
4
#    This program is free software; you can redistribute it and/or modify
14
14
#    You should have received a copy of the GNU General Public License
15
15
#    along with this program; if not, write to the Free Software
16
16
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
from bzrtools import short_committer
18
 
from dotgraph import Node, dot_output, invoke_dot, invoke_dot_aa, NoDot, NoRsvg
19
 
from dotgraph import RSVG_OUTPUT_TYPES, DOT_OUTPUT_TYPES, Edge, invoke_dot_html
 
17
 
 
18
 
 
19
import time
 
20
 
20
21
from bzrlib.branch import Branch
21
 
from bzrlib.errors import BzrCommandError, NoCommonRoot, NoSuchRevision
 
22
from bzrlib.errors import BzrCommandError, NoSuchRevision
22
23
from bzrlib.graph import node_distances, select_farthest
23
 
from bzrlib.revision import combined_graph, revision_graph
24
 
from bzrlib.revision import MultipleRevisionSources
25
 
import bzrlib.errors
26
 
import re
27
 
import os.path
28
 
import time
 
24
from bzrlib.revision import NULL_REVISION
 
25
 
 
26
from bzrtools import short_committer
 
27
from dotgraph import (
 
28
    dot_output,
 
29
    DOT_OUTPUT_TYPES,
 
30
    Edge,
 
31
    invoke_dot,
 
32
    invoke_dot_aa,
 
33
    invoke_dot_html,
 
34
    Node,
 
35
    NoDot,
 
36
    NoRsvg,
 
37
    RSVG_OUTPUT_TYPES,
 
38
    )
 
39
 
29
40
 
30
41
mail_map = {'aaron.bentley@utoronto.ca'     : 'Aaron Bentley',
31
42
            'abentley@panoramicfeedback.com': 'Aaron Bentley',
106
117
    return committer, message, nick, date
107
118
 
108
119
class Grapher(object):
 
120
 
109
121
    def __init__(self, branch, other_branch=None):
110
122
        object.__init__(self)
111
123
        self.branch = branch
112
124
        self.other_branch = other_branch
 
125
        if other_branch is not None:
 
126
            other_repo = other_branch.repository
 
127
            revision_b = self.other_branch.last_revision()
 
128
        else:
 
129
            other_repo = None
 
130
            revision_b = None
 
131
        self.graph = self.branch.repository.get_graph(other_repo)
113
132
        revision_a = self.branch.last_revision()
114
 
        if other_branch is not None:
115
 
            branch.fetch(other_branch)
116
 
            revision_b = self.other_branch.last_revision()
117
 
            try:
118
 
                self.root, self.ancestors, self.descendants, self.common = \
119
 
                    combined_graph(revision_a, revision_b,
120
 
                                   self.branch.repository)
121
 
            except bzrlib.errors.NoCommonRoot:
122
 
                raise bzrlib.errors.NoCommonAncestor(revision_a, revision_b)
123
 
        else:
124
 
            self.root, self.ancestors, self.descendants = \
125
 
                revision_graph(revision_a, branch.repository)
126
 
            self.common = []
127
 
 
 
133
        self.scan_graph(revision_a, revision_b)
128
134
        self.n_history = branch.revision_history()
129
135
        self.n_revnos = branch.get_revision_id_to_revno_map()
130
136
        self.distances = node_distances(self.descendants, self.ancestors,
133
139
            self.base = select_farthest(self.distances, self.common)
134
140
            self.m_history = other_branch.revision_history()
135
141
            self.m_revnos = other_branch.get_revision_id_to_revno_map()
136
 
            new_graph = getattr(branch.repository, 'get_graph', lambda: None)()
137
 
            if new_graph is None:
138
 
                self.new_base = None
139
 
                self.lcas = set()
140
 
            else:
141
 
                self.new_base = new_graph.find_unique_lca(revision_a,
142
 
                                                          revision_b)
143
 
                self.lcas = new_graph.find_lca(revision_a, revision_b)
 
142
            self.new_base = self.graph.find_unique_lca(revision_a,
 
143
                                                       revision_b)
 
144
            self.lcas = self.graph.find_lca(revision_a, revision_b)
144
145
        else:
145
146
            self.base = None
146
147
            self.new_base = None
148
149
            self.m_history = []
149
150
            self.m_revnos = {}
150
151
 
 
152
    def scan_graph(self, revision_a, revision_b):
 
153
        a_ancestors = dict(self.graph.iter_ancestry([revision_a]))
 
154
        self.ancestors = a_ancestors
 
155
        self.root = NULL_REVISION
 
156
        if revision_b is not None:
 
157
            b_ancestors = dict(self.graph.iter_ancestry([revision_b]))
 
158
            self.common = set(a_ancestors.keys())
 
159
            self.common.intersection_update(b_ancestors)
 
160
            self.ancestors.update(b_ancestors)
 
161
        else:
 
162
            self.common = []
 
163
            revision_b = None
 
164
        self.descendants = {}
 
165
        ghosts = set()
 
166
        for revision, parents in self.ancestors.iteritems():
 
167
            self.descendants.setdefault(revision, [])
 
168
            if parents is None:
 
169
                ghosts.add(revision)
 
170
                parents = [NULL_REVISION]
 
171
            for parent in parents:
 
172
                self.descendants.setdefault(parent, []).append(revision)
 
173
        for ghost in ghosts:
 
174
            self.ancestors[ghost] = [NULL_REVISION]
 
175
 
151
176
    @staticmethod
152
177
    def _get_revno_str(prefix, revno_map, revision_id):
153
178
        try:
322
347
                " is installed correctly.")
323
348
    elif not done:
324
349
        print "Unknown file extension: %s" % ext
325