/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
20
class RevisionLoader(object):
21
22
    def __init__(self, repo, inventories_provider=None):
23
        """An object responsible for loading revisions into a repository.
24
25
        NOTE: Repository locking is not managed by this class. Clients
26
        should take a write lock, call load() multiple times, then release
27
        the lock.
28
29
        :param repository: the target repository
30
        :param inventories_provider: a callable expecting a repository and
31
            a list of revision-ids, that returns:
32
              * the list of revision-ids present in the repository
33
              * the list of inventories for the revision-id's,
34
                including an empty inventory for the missing revisions
35
            If None, a default implementation is provided.
36
        """
37
        self.repo = repo
38
        if inventories_provider is not None:
39
            self.inventories_provider = inventories_provider
40
        else:
41
            self.inventories_provider = self._default_inventories_provider
42
43
    def load(self, rev, inv, signature, text_provider):
44
        """Load a revision into a repository.
45
46
        :param rev: the Revision
47
        :param inv: the inventory
48
        :param signature: signing information
49
        :param text_provider: a callable expecting a file_id parameter
50
            that returns the text for that file-id
51
        """
52
        # NOTE: Code based on bzrlib.repository._install_revision
53
        present_parents, parent_invs = self.inventories_provider(self.repo,
54
            rev.parent_ids)
55
        self._load_texts(rev.revision_id, inv.entries, parent_invs,
56
            text_provider)
57
        try:
58
            self.repo.add_inventory(rev.revision_id, inv, present_parents)
59
        except errors.RevisionAlreadyPresent:
60
            pass
61
        if signature is not None:
62
            self.repo.add_signature_text(rev.revision_id, signature)
63
        self.repo.add_revision(rev.revision_id, rev, inv)
64
65
    def _load_texts(self, revision_id, entries, parent_invs, text_provider):
66
        """Load texts to a repository for inventory entries.
67
        
68
        This method is provided for subclasses to use or override.
69
70
        :param revision_id: the revision identifier
71
        :param entries: iterator over the inventory entries
72
        :param parent_inv: the parent inventories
73
        :param text_provider: a callable expecting a file_id parameter
74
            that returns the text for that file-id
75
        """
76
        # NOTE: Code based on bzrlib.repository._install_revision
77
78
        # Backwards compatibility hack: skip the root id.
79
        if not self.repo.supports_rich_root():
80
            path, root = entries.next()
81
            if root.revision != revision_id:
82
                raise errors.IncompatibleRevision(repr(self.repo))
83
        # Add the texts that are not already present
84
        transaction = self.repo.get_transaction()
85
        for path, ie in entries:
86
            w = self.repo.weave_store.get_weave_or_empty(ie.file_id,
87
                transaction)
88
            if ie.revision not in w:
89
                text_parents = []
90
                for parent_inv in parent_invs:
91
                    if ie.file_id not in parent_inv:
92
                        continue
93
                    parent_id = parent_inv[ie.file_id].revision
94
                    if parent_id in text_parents:
95
                        continue
96
                    text_parents.append(parent_id)
97
                vfile = self.repo.weave_store.get_weave_or_empty(ie.file_id, 
98
                    transaction)
99
                lines = text_provider(ie.file_id)
100
                vfile.add_lines(revision_id, text_parents, lines)
101
102
    def _default_inventories_provider(self, revision_ids):
103
        """An inventories provider that queries the repository."""
104
        present = []
105
        inventories = []
106
        for revision_id in revision_ids:
107
            if self.repo.has_revision(revision_id):
108
                present.append(revision_id)
109
                rev_tree = self.repo.revision_tree(revision_id)
110
            else:
111
                rev_tree = self.repo.revision_tree(None)
112
            inventories.append(rev_tree.inventory)
113
        return present, inventories