/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
89
        transaction = self.repo.get_transaction()
90
        for path, ie in entries:
91
            w = self.repo.weave_store.get_weave_or_empty(ie.file_id,
92
                transaction)
93
            if ie.revision not in w:
94
                text_parents = []
95
                for parent_inv in parent_invs:
96
                    if ie.file_id not in parent_inv:
97
                        continue
98
                    parent_id = parent_inv[ie.file_id].revision
99
                    if parent_id in text_parents:
100
                        continue
101
                    text_parents.append(parent_id)
102
                vfile = self.repo.weave_store.get_weave_or_empty(ie.file_id, 
103
                    transaction)
104
                lines = text_provider(ie.file_id)
105
                vfile.add_lines(revision_id, text_parents, lines)
106
107
    def _default_inventories_provider(self, revision_ids):
108
        """An inventories provider that queries the repository."""
109
        present = []
110
        inventories = []
111
        for revision_id in revision_ids:
112
            if self.repo.has_revision(revision_id):
113
                present.append(revision_id)
114
                rev_tree = self.repo.revision_tree(revision_id)
115
            else:
116
                rev_tree = self.repo.revision_tree(None)
117
            inventories.append(rev_tree.inventory)
118
        return present, inventories