/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.64.5 by Ian Clatworthy
first cut at generic processing method
1
# Copyright (C) 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
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
16
17
"""Parameterised loading of revisions into a repository."""
18
19
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
20
from bzrlib import errors
21
22
0.64.5 by Ian Clatworthy
first cut at generic processing method
23
class RevisionLoader(object):
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
24
    # NOTE: This is effectively bzrlib.repository._install_revision
25
    # refactored to be a class. When importing, we want more flexibility
26
    # in how previous revisions are cached, data is feed in, etc.
0.64.5 by Ian Clatworthy
first cut at generic processing method
27
28
    def __init__(self, repo, inventories_provider=None):
29
        """An object responsible for loading revisions into a repository.
30
31
        NOTE: Repository locking is not managed by this class. Clients
32
        should take a write lock, call load() multiple times, then release
33
        the lock.
34
35
        :param repository: the target repository
36
        :param inventories_provider: a callable expecting a repository and
37
            a list of revision-ids, that returns:
38
              * the list of revision-ids present in the repository
39
              * the list of inventories for the revision-id's,
40
                including an empty inventory for the missing revisions
41
            If None, a default implementation is provided.
42
        """
43
        self.repo = repo
44
        if inventories_provider is not None:
45
            self.inventories_provider = inventories_provider
46
        else:
47
            self.inventories_provider = self._default_inventories_provider
48
49
    def load(self, rev, inv, signature, text_provider):
50
        """Load a revision into a repository.
51
52
        :param rev: the Revision
53
        :param inv: the inventory
54
        :param signature: signing information
55
        :param text_provider: a callable expecting a file_id parameter
56
            that returns the text for that file-id
57
        """
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
58
        present_parents, parent_invs = self.inventories_provider(
0.64.5 by Ian Clatworthy
first cut at generic processing method
59
            rev.parent_ids)
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
60
        self._load_texts(rev.revision_id, inv.iter_entries(), parent_invs,
0.64.5 by Ian Clatworthy
first cut at generic processing method
61
            text_provider)
62
        try:
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
63
            rev.inventory_sha1 = self.repo.add_inventory(rev.revision_id,
64
                inv, present_parents)
0.64.5 by Ian Clatworthy
first cut at generic processing method
65
        except errors.RevisionAlreadyPresent:
66
            pass
67
        if signature is not None:
68
            self.repo.add_signature_text(rev.revision_id, signature)
69
        self.repo.add_revision(rev.revision_id, rev, inv)
70
71
    def _load_texts(self, revision_id, entries, parent_invs, text_provider):
72
        """Load texts to a repository for inventory entries.
73
        
74
        This method is provided for subclasses to use or override.
75
76
        :param revision_id: the revision identifier
77
        :param entries: iterator over the inventory entries
78
        :param parent_inv: the parent inventories
79
        :param text_provider: a callable expecting a file_id parameter
80
            that returns the text for that file-id
81
        """
82
83
        # Backwards compatibility hack: skip the root id.
84
        if not self.repo.supports_rich_root():
85
            path, root = entries.next()
86
            if root.revision != revision_id:
87
                raise errors.IncompatibleRevision(repr(self.repo))
88
        # Add the texts that are not already present
0.64.27 by Ian Clatworthy
1st cut at performance tuning
89
        tx = self.repo.get_transaction()
0.64.5 by Ian Clatworthy
first cut at generic processing method
90
        for path, ie in entries:
0.64.27 by Ian Clatworthy
1st cut at performance tuning
91
            # This test is *really* slow: over 50% of import time
92
            #w = self.repo.weave_store.get_weave_or_empty(ie.file_id, tx)
93
            #if ie.revision in w:
94
            #    continue
0.64.29 by Ian Clatworthy
improve explanation of faster check in revisionloader
95
            # Try another way, realising that this assumes that the
96
            # version is not already there. In the general case,
97
            # a shared repository might already have the revision but
98
            # we arguably don't need that check when importing from
99
            # a foreign system.
0.64.27 by Ian Clatworthy
1st cut at performance tuning
100
            if ie.revision != revision_id:
101
                continue
102
            text_parents = []
103
            for parent_inv in parent_invs:
104
                if ie.file_id not in parent_inv:
105
                    continue
106
                parent_id = parent_inv[ie.file_id].revision
107
                if parent_id in text_parents:
108
                    continue
109
                text_parents.append(parent_id)
110
            vfile = self.repo.weave_store.get_weave_or_empty(ie.file_id,  tx)
111
            lines = text_provider(ie.file_id)
112
            vfile.add_lines(revision_id, text_parents, lines)
0.64.5 by Ian Clatworthy
first cut at generic processing method
113
114
    def _default_inventories_provider(self, revision_ids):
115
        """An inventories provider that queries the repository."""
116
        present = []
117
        inventories = []
118
        for revision_id in revision_ids:
119
            if self.repo.has_revision(revision_id):
120
                present.append(revision_id)
121
                rev_tree = self.repo.revision_tree(revision_id)
122
            else:
123
                rev_tree = self.repo.revision_tree(None)
124
            inventories.append(rev_tree.inventory)
125
        return present, inventories