~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/reconcile.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-03-08 00:37:41 UTC
  • mfrom: (1594.2.4 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20060308003741-08afccbf89005e87
Merge in :
 * Knit repositories use knits
 * Nested progress bar support.
 * Ghost aware graph api.

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
        garbage_inventories: The number of inventory objects without revisions
58
58
                             that were garbage collected.
59
59
        """
60
 
        self.pb = ui.ui_factory.progress_bar()
 
60
        self.pb = ui.ui_factory.nested_progress_bar()
 
61
        try:
 
62
            self._reconcile()
 
63
        finally:
 
64
            self.pb.finished()
 
65
 
 
66
    def _reconcile(self):
 
67
        """Helper function for performing reconciliation."""
61
68
        self.repo = self.bzrdir.find_repository()
62
69
        self.pb.note('Reconciling repository %s',
63
70
                     self.repo.bzrdir.root_transport.base)
86
93
        garbage_inventories: The number of inventory objects without revisions
87
94
                             that were garbage collected.
88
95
        """
89
 
        self.pb = ui.ui_factory.progress_bar()
90
96
        self.repo.lock_write()
91
97
        try:
92
 
            self._reweave_inventory()
 
98
            self.pb = ui.ui_factory.nested_progress_bar()
 
99
            try:
 
100
                self._reweave_inventory()
 
101
            finally:
 
102
                self.pb.finished()
93
103
        finally:
94
104
            self.repo.unlock()
95
105
 
96
106
    def _reweave_inventory(self):
97
107
        """Regenerate the inventory weave for the repository from scratch."""
 
108
        # local because its really a wart we want to hide
 
109
        from bzrlib.weave import WeaveFile, Weave
 
110
        transaction = self.repo.get_transaction()
98
111
        self.pb.update('Reading inventory data.')
99
112
        self.inventory = self.repo.get_inventory_weave()
100
113
        # the total set of revisions to process
101
 
        self.pending = set([file_id for file_id in self.repo.revision_store])
 
114
        self.pending = set([rev_id for rev_id in self.repo._revision_store.all_revision_ids(transaction)])
102
115
 
103
116
        # mapping from revision_id to parents
104
117
        self._rev_graph = {}
109
122
        for rev_id in self.pending:
110
123
            # put a revision into the graph.
111
124
            self._graph_revision(rev_id)
112
 
        # we gc unreferenced inventories too
113
 
        self.garbage_inventories = len(self.inventory.names()) \
114
 
                                   - len(self._rev_graph)
115
 
 
 
125
        self._check_garbage_inventories()
116
126
        if not self.inconsistent_parents and not self.garbage_inventories:
117
127
            self.pb.note('Inventory ok.')
118
128
            return
119
129
        self.pb.update('Backing up inventory...', 0, 0)
120
 
        self.repo.control_weaves.put_weave('inventory.backup',
121
 
                                           self.inventory,
122
 
                                           self.repo.get_transaction())
 
130
        self.repo.control_weaves.copy(self.inventory, 'inventory.backup', self.repo.get_transaction())
123
131
        self.pb.note('Backup Inventory created.')
124
132
        # asking for '' should never return a non-empty weave
125
 
        new_inventory = self.repo.control_weaves.get_weave_or_empty('',
 
133
        new_inventory = self.repo.control_weaves.get_empty('inventory.new',
126
134
            self.repo.get_transaction())
127
135
 
128
136
        # we have topological order of revisions and non ghost parents ready.
135
143
            # this entry has all the non ghost parents in the inventory
136
144
            # file already.
137
145
            self._reweave_step('adding inventories')
138
 
            new_inventory.add(rev_id, parents, self.inventory.get(rev_id))
 
146
            # ugly but needed, weaves are just way tooooo slow else.
 
147
            if isinstance(new_inventory, WeaveFile):
 
148
                Weave.add_lines(new_inventory, rev_id, parents, self.inventory.get_lines(rev_id))
 
149
            else:
 
150
                new_inventory.add_lines(rev_id, parents, self.inventory.get_lines(rev_id))
139
151
 
 
152
        if isinstance(new_inventory, WeaveFile):
 
153
            new_inventory._save()
140
154
        # if this worked, the set of new_inventory.names should equal
141
155
        # self.pending
142
 
        assert set(new_inventory.names()) == self.pending
 
156
        assert set(new_inventory.versions()) == self.pending
143
157
        self.pb.update('Writing weave')
144
 
        self.repo.control_weaves.put_weave('inventory',
145
 
                                           new_inventory,
146
 
                                           self.repo.get_transaction())
 
158
        self.repo.control_weaves.copy(new_inventory, 'inventory', self.repo.get_transaction())
 
159
        self.repo.control_weaves.delete('inventory.new', self.repo.get_transaction())
147
160
        self.inventory = None
148
161
        self.pb.note('Inventory regenerated.')
149
162
 
166
179
            else:
167
180
                mutter('found ghost %s', parent)
168
181
        self._rev_graph[rev_id] = parents   
169
 
        if set(self.inventory.parent_names(rev_id)) != set(parents):
 
182
        if set(self.inventory.get_parents(rev_id)) != set(parents):
170
183
            self.inconsistent_parents += 1
 
184
            mutter('Inconsistent inventory parents: id {%s} '
 
185
                   'inventory claims %r, '
 
186
                   'available parents are %r, '
 
187
                   'unavailable parents are %r',
 
188
                   rev_id, 
 
189
                   set(self.inventory.get_parents(rev_id)),
 
190
                   set(parents),
 
191
                   set(rev.parent_ids).difference(set(parents)))
 
192
 
 
193
    def _check_garbage_inventories(self):
 
194
        """Check for garbage inventories which we cannot trust
 
195
 
 
196
        We cant trust them because their pre-requisite file data may not
 
197
        be present - all we know is that their revision was not installed.
 
198
        """
 
199
        inventories = set(self.inventory.versions())
 
200
        revisions = set(self._rev_graph.keys())
 
201
        garbage = inventories.difference(revisions)
 
202
        self.garbage_inventories = len(garbage)
 
203
        for revision_id in garbage:
 
204
            mutter('Garbage inventory {%s} found.', revision_id)
171
205
 
172
206
    def _parent_is_available(self, parent):
173
207
        """True if parent is a fully available revision