~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

  • Committer: Aaron Bentley
  • Date: 2007-03-07 23:15:10 UTC
  • mto: (1551.19.24 Aaron's mergeable stuff)
  • mto: This revision was merged to the branch mainline in revision 2325.
  • Revision ID: abentley@panoramicfeedback.com-20070307231510-jae63zsli83db3eb
Make ChangeReporter private

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33
33
 
34
34
import bzrlib
35
35
import bzrlib.errors as errors
36
 
from bzrlib.errors import (InstallFailed, NoSuchRevision,
37
 
                           MissingText)
 
36
from bzrlib.errors import (InstallFailed,
 
37
                           )
 
38
from bzrlib.progress import ProgressPhase
 
39
from bzrlib.revision import NULL_REVISION
 
40
from bzrlib.symbol_versioning import (deprecated_function,
 
41
        deprecated_method,
 
42
        zero_eight,
 
43
        )
38
44
from bzrlib.trace import mutter
39
 
from bzrlib.progress import ProgressBar, ProgressPhase
40
 
from bzrlib.reconcile import RepoReconciler
41
 
from bzrlib.revision import NULL_REVISION
42
 
from bzrlib.symbol_versioning import *
 
45
import bzrlib.ui
43
46
 
44
47
 
45
48
# TODO: Avoid repeatedly opening weaves so many times.
124
127
        self.from_control = self.from_repository.control_weaves
125
128
        self.count_total = 0
126
129
        self.file_ids_names = {}
127
 
        pp = ProgressPhase('fetch phase', 4, self.pb)
 
130
        pp = ProgressPhase('Fetch phase', 4, self.pb)
128
131
        try:
 
132
            pp.next_phase()
129
133
            revs = self._revids_to_fetch()
130
134
            # something to do ?
131
135
            if revs:
144
148
        if self._last_revision is NULL_REVISION:
145
149
            # explicit limit of no revisions needed
146
150
            return None
147
 
        if (self._last_revision != None and
 
151
        if (self._last_revision is not None and
148
152
            self.to_repository.has_revision(self._last_revision)):
149
153
            return None
150
154
            
157
161
    def _fetch_weave_texts(self, revs):
158
162
        texts_pb = bzrlib.ui.ui_factory.nested_progress_bar()
159
163
        try:
 
164
            # fileids_altered_by_revision_ids requires reading the inventory
 
165
            # weave, we will need to read the inventory weave again when
 
166
            # all this is done, so enable caching for that specific weave
 
167
            inv_w = self.from_repository.get_inventory_weave()
 
168
            inv_w.enable_cache()
160
169
            file_ids = self.from_repository.fileids_altered_by_revision_ids(revs)
161
170
            count = 0
162
171
            num_file_ids = len(file_ids)
170
179
                # we fetch all the texts, because texts do
171
180
                # not reference anything, and its cheap enough
172
181
                to_weave.join(from_weave, version_ids=required_versions)
 
182
                # we don't need *all* of this data anymore, but we dont know
 
183
                # what we do. This cache clearing will result in a new read 
 
184
                # of the knit data when we do the checkout, but probably we
 
185
                # want to emit the needed data on the fly rather than at the
 
186
                # end anyhow.
 
187
                # the from weave should know not to cache data being joined,
 
188
                # but its ok to ask it to clear.
 
189
                from_weave.clear_cache()
 
190
                to_weave.clear_cache()
173
191
        finally:
174
192
            texts_pb.finished()
175
193
 
182
200
    
183
201
            child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
184
202
            try:
185
 
                # just merge, this is optimisable and its means we dont
 
203
                # just merge, this is optimisable and its means we don't
186
204
                # copy unreferenced data such as not-needed inventories.
187
205
                pb.update("fetch inventory", 1, 3)
188
206
                from_weave = self.from_repository.get_inventory_weave()
193
211
                # corrupt.
194
212
                to_weave.join(from_weave, pb=child_pb, msg='merge inventory',
195
213
                              version_ids=revs)
 
214
                from_weave.clear_cache()
196
215
            finally:
197
216
                child_pb.finished()
198
217
        finally:
263
282
        to_rf.join(from_rf, version_ids=revs)
264
283
 
265
284
 
 
285
class Inter1and2Helper(object):
 
286
    """Helper for operations that convert data from model 1 and 2
 
287
    
 
288
    This is for use by fetchers and converters.
 
289
    """
 
290
 
 
291
    def __init__(self, source, target):
 
292
        """Constructor.
 
293
 
 
294
        :param source: The repository data comes from
 
295
        :param target: The repository data goes to
 
296
        """
 
297
        self.source = source
 
298
        self.target = target
 
299
 
 
300
    def iter_rev_trees(self, revs):
 
301
        """Iterate through RevisionTrees efficiently.
 
302
 
 
303
        Additionally, the inventory's revision_id is set if unset.
 
304
 
 
305
        Trees are retrieved in batches of 100, and then yielded in the order
 
306
        they were requested.
 
307
 
 
308
        :param revs: A list of revision ids
 
309
        """
 
310
        while revs:
 
311
            for tree in self.source.revision_trees(revs[:100]):
 
312
                if tree.inventory.revision_id is None:
 
313
                    tree.inventory.revision_id = tree.get_revision_id()
 
314
                yield tree
 
315
            revs = revs[100:]
 
316
 
 
317
    def generate_root_texts(self, revs):
 
318
        """Generate VersionedFiles for all root ids.
 
319
        
 
320
        :param revs: the revisions to include
 
321
        """
 
322
        inventory_weave = self.source.get_inventory_weave()
 
323
        parent_texts = {}
 
324
        versionedfile = {}
 
325
        to_store = self.target.weave_store
 
326
        for tree in self.iter_rev_trees(revs):
 
327
            revision_id = tree.inventory.root.revision
 
328
            root_id = tree.inventory.root.file_id
 
329
            parents = inventory_weave.get_parents(revision_id)
 
330
            if root_id not in versionedfile:
 
331
                versionedfile[root_id] = to_store.get_weave_or_empty(root_id, 
 
332
                    self.target.get_transaction())
 
333
            parent_texts[root_id] = versionedfile[root_id].add_lines(
 
334
                revision_id, parents, [], parent_texts)
 
335
 
 
336
    def regenerate_inventory(self, revs):
 
337
        """Generate a new inventory versionedfile in target, convertin data.
 
338
        
 
339
        The inventory is retrieved from the source, (deserializing it), and
 
340
        stored in the target (reserializing it in a different format).
 
341
        :param revs: The revisions to include
 
342
        """
 
343
        inventory_weave = self.source.get_inventory_weave()
 
344
        for tree in self.iter_rev_trees(revs):
 
345
            parents = inventory_weave.get_parents(tree.get_revision_id())
 
346
            self.target.add_inventory(tree.get_revision_id(), tree.inventory,
 
347
                                      parents)
 
348
 
 
349
 
 
350
class Model1toKnit2Fetcher(GenericRepoFetcher):
 
351
    """Fetch from a Model1 repository into a Knit2 repository
 
352
    """
 
353
    def __init__(self, to_repository, from_repository, last_revision=None, 
 
354
                 pb=None):
 
355
        self.helper = Inter1and2Helper(from_repository, to_repository)
 
356
        GenericRepoFetcher.__init__(self, to_repository, from_repository,
 
357
                                    last_revision, pb)
 
358
 
 
359
    def _fetch_weave_texts(self, revs):
 
360
        GenericRepoFetcher._fetch_weave_texts(self, revs)
 
361
        # Now generate a weave for the tree root
 
362
        self.helper.generate_root_texts(revs)
 
363
 
 
364
    def _fetch_inventory_weave(self, revs):
 
365
        self.helper.regenerate_inventory(revs)
 
366
 
 
367
 
 
368
class Knit1to2Fetcher(KnitRepoFetcher):
 
369
    """Fetch from a Knit1 repository into a Knit2 repository"""
 
370
 
 
371
    def __init__(self, to_repository, from_repository, last_revision=None, 
 
372
                 pb=None):
 
373
        self.helper = Inter1and2Helper(from_repository, to_repository)
 
374
        KnitRepoFetcher.__init__(self, to_repository, from_repository,
 
375
                                 last_revision, pb)
 
376
 
 
377
    def _fetch_weave_texts(self, revs):
 
378
        KnitRepoFetcher._fetch_weave_texts(self, revs)
 
379
        # Now generate a weave for the tree root
 
380
        self.helper.generate_root_texts(revs)
 
381
 
 
382
    def _fetch_inventory_weave(self, revs):
 
383
        self.helper.regenerate_inventory(revs)
 
384
        
 
385
 
266
386
class Fetcher(object):
267
 
    """Backwards compatability glue for branch.fetch()."""
 
387
    """Backwards compatibility glue for branch.fetch()."""
268
388
 
269
389
    @deprecated_method(zero_eight)
270
390
    def __init__(self, to_branch, from_branch, last_revision=None, pb=None):