/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/reconcile.py

  • Committer: John Arbash Meinel
  • Date: 2009-04-21 23:54:16 UTC
  • mto: (4300.1.7 groupcompress_info)
  • mto: This revision was merged to the branch mainline in revision 4301.
  • Revision ID: john@arbash-meinel.com-20090421235416-f0cz6ilf5cufbugi
Fix bug #364900, properly remove the 64kB that was just encoded in the copy.
Also, stop supporting None as a copy length in 'encode_copy_instruction'.
It was only used by the test suite, and it is good to pull that sort of thing out of
production code. (Besides, setting the copy to 64kB has the same effect.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
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
27
27
 
28
28
 
29
29
from bzrlib import (
30
 
    cleanup,
31
30
    errors,
32
31
    ui,
 
32
    repository,
 
33
    repofmt,
33
34
    )
34
 
from bzrlib.trace import mutter
35
 
from bzrlib.tsort import topo_sort
 
35
from bzrlib.trace import mutter, note
 
36
from bzrlib.tsort import TopoSorter
36
37
from bzrlib.versionedfile import AdapterFactory, FulltextContentFactory
37
38
 
38
39
 
89
90
            # Nothing to check here
90
91
            self.fixed_branch_history = None
91
92
            return
92
 
        ui.ui_factory.note('Reconciling branch %s' % self.branch.base)
 
93
        self.pb.note('Reconciling branch %s',
 
94
                     self.branch.base)
93
95
        branch_reconciler = self.branch.reconcile(thorough=True)
94
96
        self.fixed_branch_history = branch_reconciler.fixed_history
95
97
 
96
98
    def _reconcile_repository(self):
97
99
        self.repo = self.bzrdir.find_repository()
98
 
        ui.ui_factory.note('Reconciling repository %s' %
99
 
            self.repo.user_url)
 
100
        self.pb.note('Reconciling repository %s',
 
101
                     self.repo.bzrdir.root_transport.base)
100
102
        self.pb.update("Reconciling repository", 0, 1)
101
103
        repo_reconciler = self.repo.reconcile(thorough=True)
102
104
        self.inconsistent_parents = repo_reconciler.inconsistent_parents
103
105
        self.garbage_inventories = repo_reconciler.garbage_inventories
104
106
        if repo_reconciler.aborted:
105
 
            ui.ui_factory.note(
 
107
            self.pb.note(
106
108
                'Reconcile aborted: revision index has inconsistent parents.')
107
 
            ui.ui_factory.note(
 
109
            self.pb.note(
108
110
                'Run "bzr check" for more details.')
109
111
        else:
110
 
            ui.ui_factory.note('Reconciliation complete.')
 
112
            self.pb.note('Reconciliation complete.')
111
113
 
112
114
 
113
115
class BranchReconciler(object):
119
121
        self.branch = a_branch
120
122
 
121
123
    def reconcile(self):
122
 
        operation = cleanup.OperationWithCleanups(self._reconcile)
123
 
        self.add_cleanup = operation.add_cleanup
124
 
        operation.run_simple()
125
 
 
126
 
    def _reconcile(self):
127
124
        self.branch.lock_write()
128
 
        self.add_cleanup(self.branch.unlock)
129
 
        self.pb = ui.ui_factory.nested_progress_bar()
130
 
        self.add_cleanup(self.pb.finished)
131
 
        self._reconcile_steps()
 
125
        try:
 
126
            self.pb = ui.ui_factory.nested_progress_bar()
 
127
            try:
 
128
                self._reconcile_steps()
 
129
            finally:
 
130
                self.pb.finished()
 
131
        finally:
 
132
            self.branch.unlock()
132
133
 
133
134
    def _reconcile_steps(self):
134
135
        self._reconcile_revision_history()
136
137
    def _reconcile_revision_history(self):
137
138
        repo = self.branch.repository
138
139
        last_revno, last_revision_id = self.branch.last_revision_info()
139
 
        real_history = []
140
 
        try:
141
 
            for revid in repo.iter_reverse_revision_history(
142
 
                    last_revision_id):
143
 
                real_history.append(revid)
144
 
        except errors.RevisionNotPresent:
145
 
            pass # Hit a ghost left hand parent
 
140
        real_history = list(repo.iter_reverse_revision_history(
 
141
                                last_revision_id))
146
142
        real_history.reverse()
147
143
        if last_revno != len(real_history):
148
144
            self.fixed_history = True
150
146
            # set_revision_history, as this will regenerate it again.
151
147
            # Not really worth a whole BranchReconciler class just for this,
152
148
            # though.
153
 
            ui.ui_factory.note('Fixing last revision info %s => %s' % (
154
 
                 last_revno, len(real_history)))
 
149
            self.pb.note('Fixing last revision info %s => %s',
 
150
                         last_revno, len(real_history))
155
151
            self.branch.set_last_revision_info(len(real_history),
156
152
                                               last_revision_id)
157
153
        else:
158
154
            self.fixed_history = False
159
 
            ui.ui_factory.note('revision_history ok.')
 
155
            self.pb.note('revision_history ok.')
160
156
 
161
157
 
162
158
class RepoReconciler(object):
192
188
        garbage_inventories: The number of inventory objects without revisions
193
189
                             that were garbage collected.
194
190
        """
195
 
        operation = cleanup.OperationWithCleanups(self._reconcile)
196
 
        self.add_cleanup = operation.add_cleanup
197
 
        operation.run_simple()
198
 
 
199
 
    def _reconcile(self):
200
191
        self.repo.lock_write()
201
 
        self.add_cleanup(self.repo.unlock)
202
 
        self.pb = ui.ui_factory.nested_progress_bar()
203
 
        self.add_cleanup(self.pb.finished)
204
 
        self._reconcile_steps()
 
192
        try:
 
193
            self.pb = ui.ui_factory.nested_progress_bar()
 
194
            try:
 
195
                self._reconcile_steps()
 
196
            finally:
 
197
                self.pb.finished()
 
198
        finally:
 
199
            self.repo.unlock()
205
200
 
206
201
    def _reconcile_steps(self):
207
202
        """Perform the steps to reconcile this repository."""
238
233
        # (no garbage inventories or we are not doing a thorough check)
239
234
        if (not self.inconsistent_parents and
240
235
            (not self.garbage_inventories or not self.thorough)):
241
 
            ui.ui_factory.note('Inventory ok.')
 
236
            self.pb.note('Inventory ok.')
242
237
            return
243
238
        self.pb.update('Backing up inventory', 0, 0)
244
239
        self.repo._backup_inventory()
245
 
        ui.ui_factory.note('Backup inventory created.')
 
240
        self.pb.note('Backup inventory created.')
246
241
        new_inventories = self.repo._temp_inventories()
247
242
 
248
243
        # we have topological order of revisions and non ghost parents ready.
249
244
        self._setup_steps(len(self._rev_graph))
250
 
        revision_keys = [(rev_id,) for rev_id in topo_sort(self._rev_graph)]
 
245
        revision_keys = [(rev_id,) for rev_id in
 
246
            TopoSorter(self._rev_graph.items()).iter_topo_order()]
251
247
        stream = self._change_inv_parents(
252
248
            self.inventory.get_record_stream(revision_keys, 'unordered', True),
253
249
            self._new_inv_parents,
261
257
        self.pb.update('Writing weave')
262
258
        self.repo._activate_new_inventory()
263
259
        self.inventory = None
264
 
        ui.ui_factory.note('Inventory regenerated.')
 
260
        self.pb.note('Inventory regenerated.')
265
261
 
266
262
    def _new_inv_parents(self, revision_key):
267
263
        """Lookup ghost-filtered parents for revision_key."""
368
364
        self._check_garbage_inventories()
369
365
        self.pb.update('Checking unused inventories', 1, 3)
370
366
        if not self.garbage_inventories:
371
 
            ui.ui_factory.note('Inventory ok.')
 
367
            self.pb.note('Inventory ok.')
372
368
            return
373
369
        self.pb.update('Backing up inventory', 0, 0)
374
370
        self.repo._backup_inventory()
375
 
        ui.ui_factory.note('Backup Inventory created')
 
371
        self.pb.note('Backup Inventory created')
376
372
        # asking for '' should never return a non-empty weave
377
373
        new_inventories = self.repo._temp_inventories()
378
374
        # we have topological order of revisions and non ghost parents ready.
379
375
        graph = self.revisions.get_parent_map(self.revisions.keys())
380
 
        revision_keys = topo_sort(graph)
 
376
        revision_keys = list(TopoSorter(graph).iter_topo_order())
381
377
        revision_ids = [key[-1] for key in revision_keys]
382
378
        self._setup_steps(len(revision_keys))
383
379
        stream = self._change_inv_parents(
392
388
        self.pb.update('Writing weave')
393
389
        self.repo._activate_new_inventory()
394
390
        self.inventory = None
395
 
        ui.ui_factory.note('Inventory regenerated.')
 
391
        self.pb.note('Inventory regenerated.')
396
392
 
397
393
    def _fix_text_parents(self):
398
394
        """Fix bad versionedfile parent entries.
503
499
        collection = self.repo._pack_collection
504
500
        collection.ensure_loaded()
505
501
        collection.lock_names()
506
 
        self.add_cleanup(collection._unlock_names)
507
 
        packs = collection.all_packs()
508
 
        all_revisions = self.repo.all_revision_ids()
509
 
        total_inventories = len(list(
510
 
            collection.inventory_index.combined_index.iter_all_entries()))
511
 
        if len(all_revisions):
512
 
            new_pack =  self.repo._reconcile_pack(collection, packs,
513
 
                ".reconcile", all_revisions, self.pb)
514
 
            if new_pack is not None:
 
502
        try:
 
503
            packs = collection.all_packs()
 
504
            all_revisions = self.repo.all_revision_ids()
 
505
            total_inventories = len(list(
 
506
                collection.inventory_index.combined_index.iter_all_entries()))
 
507
            if len(all_revisions):
 
508
                new_pack =  self.repo._reconcile_pack(collection, packs,
 
509
                    ".reconcile", all_revisions, self.pb)
 
510
                if new_pack is not None:
 
511
                    self._discard_and_save(packs)
 
512
            else:
 
513
                # only make a new pack when there is data to copy.
515
514
                self._discard_and_save(packs)
516
 
        else:
517
 
            # only make a new pack when there is data to copy.
518
 
            self._discard_and_save(packs)
519
 
        self.garbage_inventories = total_inventories - len(list(
520
 
            collection.inventory_index.combined_index.iter_all_entries()))
 
515
            self.garbage_inventories = total_inventories - len(list(
 
516
                collection.inventory_index.combined_index.iter_all_entries()))
 
517
        finally:
 
518
            collection._unlock_names()
521
519
 
522
520
    def _discard_and_save(self, packs):
523
521
        """Discard some packs from the repository.