/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/graph.py

  • Committer: Martin Pool
  • Date: 2009-06-10 02:51:23 UTC
  • mfrom: (4423 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4464.
  • Revision ID: mbp@sourcefrog.net-20090610025123-2u0c0ng5jcezjzqh
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import time
18
18
 
20
20
    debug,
21
21
    errors,
22
22
    revision,
23
 
    symbol_versioning,
24
23
    trace,
25
24
    tsort,
26
25
    )
 
26
from bzrlib.symbol_versioning import deprecated_function, deprecated_in
27
27
 
28
28
STEP_UNIQUE_SEARCHER_EVERY = 5
29
29
 
60
60
        return 'DictParentsProvider(%r)' % self.ancestry
61
61
 
62
62
    def get_parent_map(self, keys):
63
 
        """See _StackedParentsProvider.get_parent_map"""
 
63
        """See StackedParentsProvider.get_parent_map"""
64
64
        ancestry = self.ancestry
65
65
        return dict((k, ancestry[k]) for k in keys if k in ancestry)
66
66
 
67
 
 
68
 
class _StackedParentsProvider(object):
69
 
 
 
67
@deprecated_function(deprecated_in((1, 16, 0)))
 
68
def _StackedParentsProvider(*args, **kwargs):
 
69
    return StackedParentsProvider(*args, **kwargs)
 
70
 
 
71
class StackedParentsProvider(object):
 
72
    """A parents provider which stacks (or unions) multiple providers.
 
73
    
 
74
    The providers are queries in the order of the provided parent_providers.
 
75
    """
 
76
    
70
77
    def __init__(self, parent_providers):
71
78
        self._parent_providers = parent_providers
72
79
 
73
80
    def __repr__(self):
74
 
        return "_StackedParentsProvider(%r)" % self._parent_providers
 
81
        return "%s(%r)" % (self.__class__.__name__, self._parent_providers)
75
82
 
76
83
    def get_parent_map(self, keys):
77
84
        """Get a mapping of keys => parents
121
128
            self._get_parent_map = self._real_provider.get_parent_map
122
129
        else:
123
130
            self._get_parent_map = get_parent_map
124
 
        self._cache = {}
125
 
        self._cache_misses = True
 
131
        self._cache = None
 
132
        self.enable_cache(True)
126
133
 
127
134
    def __repr__(self):
128
135
        return "%s(%r)" % (self.__class__.__name__, self._real_provider)
133
140
            raise AssertionError('Cache enabled when already enabled.')
134
141
        self._cache = {}
135
142
        self._cache_misses = cache_misses
 
143
        self.missing_keys = set()
136
144
 
137
145
    def disable_cache(self):
138
146
        """Disable and clear the cache."""
139
147
        self._cache = None
 
148
        self._cache_misses = None
 
149
        self.missing_keys = set()
140
150
 
141
151
    def get_cached_map(self):
142
152
        """Return any cached get_parent_map values."""
143
153
        if self._cache is None:
144
154
            return None
145
 
        return dict((k, v) for k, v in self._cache.items()
146
 
                    if v is not None)
 
155
        return dict(self._cache)
147
156
 
148
157
    def get_parent_map(self, keys):
149
 
        """See _StackedParentsProvider.get_parent_map."""
150
 
        # Hack to build up the caching logic.
151
 
        ancestry = self._cache
152
 
        if ancestry is None:
153
 
            # Caching is disabled.
154
 
            missing_revisions = set(keys)
155
 
            ancestry = {}
 
158
        """See StackedParentsProvider.get_parent_map."""
 
159
        cache = self._cache
 
160
        if cache is None:
 
161
            cache = self._get_parent_map(keys)
156
162
        else:
157
 
            missing_revisions = set(key for key in keys if key not in ancestry)
158
 
        if missing_revisions:
159
 
            parent_map = self._get_parent_map(missing_revisions)
160
 
            ancestry.update(parent_map)
161
 
            if self._cache_misses:
162
 
                # None is never a valid parents list, so it can be used to
163
 
                # record misses.
164
 
                ancestry.update(dict((k, None) for k in missing_revisions
165
 
                                     if k not in parent_map))
166
 
        present_keys = [k for k in keys if ancestry.get(k) is not None]
167
 
        return dict((k, ancestry[k]) for k in present_keys)
 
163
            needed_revisions = set(key for key in keys if key not in cache)
 
164
            # Do not ask for negatively cached keys
 
165
            needed_revisions.difference_update(self.missing_keys)
 
166
            if needed_revisions:
 
167
                parent_map = self._get_parent_map(needed_revisions)
 
168
                cache.update(parent_map)
 
169
                if self._cache_misses:
 
170
                    for key in needed_revisions:
 
171
                        if key not in parent_map:
 
172
                            self.note_missing_key(key)
 
173
        result = {}
 
174
        for key in keys:
 
175
            value = cache.get(key)
 
176
            if value is not None:
 
177
                result[key] = value
 
178
        return result
 
179
 
 
180
    def note_missing_key(self, key):
 
181
        """Note that key is a missing key."""
 
182
        if self._cache_misses:
 
183
            self.missing_keys.add(key)
168
184
 
169
185
 
170
186
class Graph(object):
600
616
                                 all_unique_searcher._iterations)
601
617
            unique_tip_searchers = next_unique_searchers
602
618
 
603
 
    @symbol_versioning.deprecated_method(symbol_versioning.one_one)
604
 
    def get_parents(self, revisions):
605
 
        """Find revision ids of the parents of a list of revisions
606
 
 
607
 
        A list is returned of the same length as the input.  Each entry
608
 
        is a list of parent ids for the corresponding input revision.
609
 
 
610
 
        [NULL_REVISION] is used as the parent of the first user-committed
611
 
        revision.  Its parent list is empty.
612
 
 
613
 
        If the revision is not present (i.e. a ghost), None is used in place
614
 
        of the list of parents.
615
 
 
616
 
        Deprecated in bzr 1.2 - please see get_parent_map.
617
 
        """
618
 
        parents = self.get_parent_map(revisions)
619
 
        return [parents.get(r, None) for r in revisions]
620
 
 
621
619
    def get_parent_map(self, revisions):
622
620
        """Get a map of key:parent_list for revisions.
623
621
 
1469
1467
 
1470
1468
        The recipe allows reconstruction of the same results at a later date
1471
1469
        without knowing all the found keys. The essential elements are a list
1472
 
        of keys to start and and to stop at. In order to give reproducible
 
1470
        of keys to start and to stop at. In order to give reproducible
1473
1471
        results when ghosts are encountered by a search they are automatically
1474
1472
        added to the exclude list (or else ghost filling may alter the
1475
1473
        results).
1495
1493
        return self._keys
1496
1494
 
1497
1495
    def is_empty(self):
1498
 
        """Return true if the search lists 1 or more revisions."""
 
1496
        """Return false if the search lists 1 or more revisions."""
1499
1497
        return self._recipe[3] == 0
1500
1498
 
1501
1499
    def refine(self, seen, referenced):
1565
1563
    def _get_keys(self, graph):
1566
1564
        NULL_REVISION = revision.NULL_REVISION
1567
1565
        keys = [key for (key, parents) in graph.iter_ancestry(self.heads)
1568
 
                if key != NULL_REVISION]
 
1566
                if key != NULL_REVISION and parents is not None]
1569
1567
        return keys
1570
1568
 
1571
1569
    def is_empty(self):
1572
 
        """Return true if the search lists 1 or more revisions."""
 
1570
        """Return false if the search lists 1 or more revisions."""
1573
1571
        if revision.NULL_REVISION in self.heads:
1574
1572
            return len(self.heads) == 1
1575
1573
        else: