/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info 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
"""Import processor that supports all Bazaar repository formats."""
18
19
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
20
import time
0.64.5 by Ian Clatworthy
first cut at generic processing method
21
from bzrlib import (
0.64.37 by Ian Clatworthy
create branches as required
22
    bzrdir,
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
23
    delta,
0.64.5 by Ian Clatworthy
first cut at generic processing method
24
    errors,
25
    osutils,
0.64.26 by Ian Clatworthy
more progress reporting tweaks
26
    progress,
0.64.5 by Ian Clatworthy
first cut at generic processing method
27
    )
0.64.51 by Ian Clatworthy
disable autopacking
28
from bzrlib.repofmt import pack_repo
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
29
from bzrlib.trace import note
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
30
import bzrlib.util.configobj.configobj as configobj
0.64.5 by Ian Clatworthy
first cut at generic processing method
31
from bzrlib.plugins.fastimport import (
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
32
    branch_updater,
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
33
    bzr_commit_handler,
0.78.3 by Ian Clatworthy
move GenericCacheManager into its own module
34
    cache_manager,
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
35
    errors as plugin_errors,
0.64.31 by Ian Clatworthy
fix branch updating for the single branch case
36
    helpers,
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
37
    idmapfile,
0.78.5 by Ian Clatworthy
move import/export of marks into a module
38
    marks_file,
0.64.5 by Ian Clatworthy
first cut at generic processing method
39
    processor,
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
40
    revision_store,
0.64.5 by Ian Clatworthy
first cut at generic processing method
41
    )
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
42
43
0.64.41 by Ian Clatworthy
update multiple working trees if requested
44
# How many commits before automatically reporting progress
45
_DEFAULT_AUTO_PROGRESS = 1000
46
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
47
# How many commits before automatically checkpointing
48
_DEFAULT_AUTO_CHECKPOINT = 10000
49
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
50
# How many inventories to cache
51
_DEFAULT_INV_CACHE_SIZE = 10
52
0.64.41 by Ian Clatworthy
update multiple working trees if requested
53
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
54
class GenericProcessor(processor.ImportProcessor):
55
    """An import processor that handles basic imports.
56
57
    Current features supported:
58
0.64.16 by Ian Clatworthy
safe processing tweaks
59
    * blobs are cached in memory
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
60
    * files and symlinks commits are supported
61
    * checkpoints automatically happen at a configurable frequency
62
      over and above the stream requested checkpoints
63
    * timestamped progress reporting, both automatic and stream requested
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
64
    * some basic statistics are dumped on completion.
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
65
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
66
    At checkpoints and on completion, the commit-id -> revision-id map is
67
    saved to a file called 'fastimport-id-map'. If the import crashes
68
    or is interrupted, it can be started again and this file will be
69
    used to skip over already loaded revisions. The format of each line
70
    is "commit-id revision-id" so commit-ids cannot include spaces.
71
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
72
    Here are the supported parameters:
73
0.64.38 by Ian Clatworthy
clean-up doc ready for initial release
74
    * info - name of a hints file holding the analysis generated
75
      by running the fast-import-info processor in verbose mode. When
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
76
      importing large repositories, this parameter is needed so
77
      that the importer knows what blobs to intelligently cache.
78
0.64.41 by Ian Clatworthy
update multiple working trees if requested
79
    * trees - update the working trees before completing.
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
80
      By default, the importer updates the repository
81
      and branches and the user needs to run 'bzr update' for the
0.64.41 by Ian Clatworthy
update multiple working trees if requested
82
      branches of interest afterwards.
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
83
84
    * checkpoint - automatically checkpoint every n commits over and
85
      above any checkpoints contained in the import stream.
86
      The default is 10000.
87
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
88
    * count - only import this many commits then exit. If not set
89
      or negative, all commits are imported.
90
    
91
    * inv-cache - number of inventories to cache.
92
      If not set, the default is 10.
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
93
94
    * experimental - enable experimental mode, i.e. use features
95
      not yet fully tested.
0.64.82 by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch
96
97
    * import-marks - name of file to read to load mark information from
98
99
    * export-marks - name of file to write to save mark information to
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
100
    """
101
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
102
    known_params = [
103
        'info',
104
        'trees',
105
        'checkpoint',
106
        'count',
107
        'inv-cache',
108
        'experimental',
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
109
        'import-marks',
110
        'export-marks',
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
111
        ]
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
112
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
113
    def pre_process(self):
0.64.26 by Ian Clatworthy
more progress reporting tweaks
114
        self._start_time = time.time()
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
115
        self._load_info_and_params()
0.78.3 by Ian Clatworthy
move GenericCacheManager into its own module
116
        self.cache_mgr = cache_manager.CacheManager(self.info, self.verbose,
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
117
            self.inventory_cache_size)
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
118
        
0.64.82 by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch
119
        if self.params.get("import-marks") is not None:
0.79.2 by Ian Clatworthy
extend & use marks_file API
120
            mark_info = marks_file.import_marks(self.params.get("import-marks"))
121
            if mark_info is not None:
122
                self.cache_mgr.revision_ids = mark_info[0]
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
123
            self.skip_total = False
124
            self.first_incremental_commit = True
125
        else:
126
            self.first_incremental_commit = False
127
            self.skip_total = self._init_id_map()
128
            if self.skip_total:
129
                self.note("Found %d commits already loaded - "
130
                    "skipping over these ...", self.skip_total)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
131
        self._revision_count = 0
132
133
        # mapping of tag name to revision_id
134
        self.tags = {}
135
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
136
        # Create the revision store to use for committing, if any
137
        self.rev_store = self._revision_store_factory()
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
138
0.64.51 by Ian Clatworthy
disable autopacking
139
        # Disable autopacking if the repo format supports it.
140
        # THIS IS A HACK - there is no sanctioned way of doing this yet.
141
        if isinstance(self.repo, pack_repo.KnitPackRepository):
142
            self._original_max_pack_count = \
143
                self.repo._pack_collection._max_pack_count
144
            def _max_pack_count_for_import(total_revisions):
145
                return total_revisions + 1
146
            self.repo._pack_collection._max_pack_count = \
147
                _max_pack_count_for_import
148
        else:
149
            self._original_max_pack_count = None
0.64.144 by Ian Clatworthy
make groupcompress _FAST during import
150
 
151
        # Make groupcompress use the fast algorithm during importing.
152
        # We want to repack at the end anyhow when more information
153
        # is available to do a better job of saving space.
154
        try:
155
            from bzrlib.plugins.groupcompress import groupcompress
156
            groupcompress._FAST = True
157
        except ImportError:
158
            pass
159
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
160
        # Create a write group. This is committed at the end of the import.
161
        # Checkpointing closes the current one and starts a new one.
162
        self.repo.start_write_group()
163
164
    def _load_info_and_params(self):
0.64.52 by Ian Clatworthy
switch on experimental mode by default
165
        self._experimental = bool(self.params.get('experimental', False))
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
166
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
167
        # This is currently hard-coded but might be configurable via
168
        # parameters one day if that's needed
169
        repo_transport = self.repo.control_files._transport
170
        self.id_map_path = repo_transport.local_abspath("fastimport-id-map")
171
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
172
        # Load the info file, if any
173
        info_path = self.params.get('info')
174
        if info_path is not None:
175
            self.info = configobj.ConfigObj(info_path)
176
        else:
177
            self.info = None
178
0.84.4 by Ian Clatworthy
improved-but-not-yet-working CHKInventory support
179
        # Decide which CommitHandler to use
0.84.8 by Ian Clatworthy
ensure the chk stuff is only used on formats actually supporting it
180
        if getattr(self.repo._format, 'supports_chks', False):
0.84.4 by Ian Clatworthy
improved-but-not-yet-working CHKInventory support
181
            self.commit_handler_factory = \
0.84.7 by Ian Clatworthy
CHKInventory support for non rich-root repos working, for simple imports at least
182
                bzr_commit_handler.CHKInventoryCommitHandler
0.84.4 by Ian Clatworthy
improved-but-not-yet-working CHKInventory support
183
        else:
184
            self.commit_handler_factory = \
185
                bzr_commit_handler.InventoryCommitHandler
186
0.64.41 by Ian Clatworthy
update multiple working trees if requested
187
        # Decide how often to automatically report progress
188
        # (not a parameter yet)
189
        self.progress_every = _DEFAULT_AUTO_PROGRESS
190
        if self.verbose:
191
            self.progress_every = self.progress_every / 10
192
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
193
        # Decide how often to automatically checkpoint
194
        self.checkpoint_every = int(self.params.get('checkpoint',
195
            _DEFAULT_AUTO_CHECKPOINT))
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
196
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
197
        # Decide how big to make the inventory cache
198
        self.inventory_cache_size = int(self.params.get('inv-cache',
199
            _DEFAULT_INV_CACHE_SIZE))
200
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
201
        # Find the maximum number of commits to import (None means all)
202
        # and prepare progress reporting. Just in case the info file
203
        # has an outdated count of commits, we store the max counts
204
        # at which we need to terminate separately to the total used
205
        # for progress tracking.
206
        try:
207
            self.max_commits = int(self.params['count'])
0.64.38 by Ian Clatworthy
clean-up doc ready for initial release
208
            if self.max_commits < 0:
209
                self.max_commits = None
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
210
        except KeyError:
211
            self.max_commits = None
0.64.25 by Ian Clatworthy
slightly better progress reporting
212
        if self.info is not None:
213
            self.total_commits = int(self.info['Command counts']['commit'])
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
214
            if (self.max_commits is not None and
215
                self.total_commits > self.max_commits):
216
                self.total_commits = self.max_commits
0.64.25 by Ian Clatworthy
slightly better progress reporting
217
        else:
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
218
            self.total_commits = self.max_commits
0.64.25 by Ian Clatworthy
slightly better progress reporting
219
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
220
    def _revision_store_factory(self):
221
        """Make a RevisionStore based on what the repository supports."""
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
222
        new_repo_api = hasattr(self.repo, 'revisions')
223
        if new_repo_api:
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
224
            return revision_store.RevisionStore2(self.repo)
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
225
        elif not self._experimental:
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
226
            return revision_store.RevisionStore1(self.repo)
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
227
        else:
228
            def fulltext_when(count):
229
                total = self.total_commits
230
                if total is not None and count == total:
231
                    fulltext = True
232
                else:
233
                    # Create an inventory fulltext every 200 revisions
234
                    fulltext = count % 200 == 0
235
                if fulltext:
236
                    self.note("%d commits - storing inventory as full-text",
237
                        count)
238
                return fulltext
239
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
240
            return revision_store.ImportRevisionStore1(
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
241
                self.repo, self.inventory_cache_size,
242
                fulltext_when=fulltext_when)
243
0.64.27 by Ian Clatworthy
1st cut at performance tuning
244
    def _process(self, command_iter):
245
        # if anything goes wrong, abort the write group if any
246
        try:
247
            processor.ImportProcessor._process(self, command_iter)
248
        except:
249
            if self.repo is not None and self.repo.is_in_write_group():
250
                self.repo.abort_write_group()
251
            raise
252
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
253
    def post_process(self):
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
254
        # Commit the current write group and checkpoint the id map
0.64.27 by Ian Clatworthy
1st cut at performance tuning
255
        self.repo.commit_write_group()
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
256
        self._save_id_map()
0.64.27 by Ian Clatworthy
1st cut at performance tuning
257
0.64.82 by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch
258
        if self.params.get("export-marks") is not None:
0.78.5 by Ian Clatworthy
move import/export of marks into a module
259
            marks_file.export_marks(self.params.get("export-marks"),
260
                self.cache_mgr.revision_ids)
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
261
0.64.31 by Ian Clatworthy
fix branch updating for the single branch case
262
        # Update the branches
263
        self.note("Updating branch information ...")
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
264
        updater = branch_updater.BranchUpdater(self.repo, self.branch,
265
            self.cache_mgr, helpers.invert_dictset(self.cache_mgr.heads),
0.64.64 by Ian Clatworthy
save tags known about in each branch
266
            self.cache_mgr.last_ref, self.tags)
0.64.34 by Ian Clatworthy
report lost branches
267
        branches_updated, branches_lost = updater.update()
268
        self._branch_count = len(branches_updated)
269
270
        # Tell the user about branches that were not created
271
        if branches_lost:
0.64.37 by Ian Clatworthy
create branches as required
272
            if not self.repo.is_shared():
273
                self.warning("Cannot import multiple branches into "
274
                    "an unshared repository")
275
            self.warning("Not creating branches for these head revisions:")
0.64.34 by Ian Clatworthy
report lost branches
276
            for lost_info in branches_lost:
277
                head_revision = lost_info[1]
278
                branch_name = lost_info[0]
0.64.67 by James Westby
Add support for -Dfast-import.
279
                self.note("\t %s = %s", head_revision, branch_name)
0.64.34 by Ian Clatworthy
report lost branches
280
281
        # Update the working trees as requested and dump stats
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
282
        self._tree_count = 0
0.64.34 by Ian Clatworthy
report lost branches
283
        remind_about_update = True
0.64.54 by Ian Clatworthy
handle existing branches and only count the branches really updated
284
        if self._branch_count == 0:
285
            self.note("no branches to update")
286
            self.note("no working trees to update")
287
            remind_about_update = False
288
        elif self.params.get('trees', False):
0.64.41 by Ian Clatworthy
update multiple working trees if requested
289
            trees = self._get_working_trees(branches_updated)
290
            if trees:
291
                self.note("Updating the working trees ...")
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
292
                if self.verbose:
293
                    report = delta._ChangeReporter()
294
                else:
295
                    reporter = None
0.64.41 by Ian Clatworthy
update multiple working trees if requested
296
                for wt in trees:
297
                    wt.update(reporter)
298
                    self._tree_count += 1
0.64.34 by Ian Clatworthy
report lost branches
299
                remind_about_update = False
0.64.41 by Ian Clatworthy
update multiple working trees if requested
300
            else:
301
                self.warning("No working trees available to update")
0.64.31 by Ian Clatworthy
fix branch updating for the single branch case
302
        self.dump_stats()
0.64.51 by Ian Clatworthy
disable autopacking
303
304
        # Finish up by telling the user what to do next.
305
        if self._original_max_pack_count:
306
            # We earlier disabled autopacking, creating one pack every
0.64.75 by Ian Clatworthy
if checkpointed, pack repository and delete obsolete_packs
307
            # checkpoint instead. We now pack the repository to optimise
308
            # how data is stored.
309
            if self._revision_count > self.checkpoint_every:
310
                self.note("Packing repository ...")
311
                self.repo.pack()
312
                # To be conservative, packing puts the old packs and
313
                # indices in obsolete_packs. We err on the side of
314
                # optimism and clear out that directory to save space.
315
                self.note("Removing obsolete packs ...")
316
                # TODO: Use a public API for this once one exists
317
                repo_transport = self.repo._pack_collection.transport
318
                repo_transport.clone('obsolete_packs').delete_multi(
319
                    repo_transport.list_dir('obsolete_packs'))
0.64.34 by Ian Clatworthy
report lost branches
320
        if remind_about_update:
0.64.75 by Ian Clatworthy
if checkpointed, pack repository and delete obsolete_packs
321
            # This message is explicitly not timestamped.
0.64.51 by Ian Clatworthy
disable autopacking
322
            note("To refresh the working tree for a branch, "
323
                "use 'bzr update'.")
0.64.41 by Ian Clatworthy
update multiple working trees if requested
324
325
    def _get_working_trees(self, branches):
326
        """Get the working trees for branches in the repository."""
327
        result = []
328
        wt_expected = self.repo.make_working_trees()
329
        for br in branches:
330
            if br == self.branch and br is not None:
331
                wt = self.working_tree
332
            elif wt_expected:
333
                try:
334
                    wt = br.bzrdir.open_workingtree()
335
                except errors.NoWorkingTree:
336
                    self.warning("No working tree for branch %s", br)
337
                    continue
338
            else:
339
                continue
340
            result.append(wt)
341
        return result
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
342
343
    def dump_stats(self):
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
344
        time_required = progress.str_tdelta(time.time() - self._start_time)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
345
        rc = self._revision_count - self.skip_total
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
346
        bc = self._branch_count
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
347
        wtc = self._tree_count
348
        self.note("Imported %d %s, updating %d %s and %d %s in %s",
0.64.32 by Ian Clatworthy
move single_plural into helpers
349
            rc, helpers.single_plural(rc, "revision", "revisions"),
350
            bc, helpers.single_plural(bc, "branch", "branches"),
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
351
            wtc, helpers.single_plural(wtc, "tree", "trees"),
352
            time_required)
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
353
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
354
    def _init_id_map(self):
355
        """Load the id-map and check it matches the repository.
356
        
357
        :return: the number of entries in the map
358
        """
359
        # Currently, we just check the size. In the future, we might
360
        # decide to be more paranoid and check that the revision-ids
361
        # are identical as well.
362
        self.cache_mgr.revision_ids, known = idmapfile.load_id_map(
363
            self.id_map_path)
364
        existing_count = len(self.repo.all_revision_ids())
0.64.106 by Ian Clatworthy
let the id-map file have more revisions than the repository
365
        if existing_count < known:
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
366
            raise plugin_errors.BadRepositorySize(known, existing_count)
367
        return known
368
369
    def _save_id_map(self):
370
        """Save the id-map."""
371
        # Save the whole lot every time. If this proves a problem, we can
372
        # change to 'append just the new ones' at a later time.
373
        idmapfile.save_id_map(self.id_map_path, self.cache_mgr.revision_ids)
374
0.64.5 by Ian Clatworthy
first cut at generic processing method
375
    def blob_handler(self, cmd):
376
        """Process a BlobCommand."""
377
        if cmd.mark is not None:
0.64.36 by Ian Clatworthy
fix head tracking when unmarked commits used
378
            dataref = cmd.id
0.64.5 by Ian Clatworthy
first cut at generic processing method
379
        else:
380
            dataref = osutils.sha_strings(cmd.data)
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
381
        self.cache_mgr.store_blob(dataref, cmd.data)
0.64.5 by Ian Clatworthy
first cut at generic processing method
382
383
    def checkpoint_handler(self, cmd):
384
        """Process a CheckpointCommand."""
0.64.27 by Ian Clatworthy
1st cut at performance tuning
385
        # Commit the current write group and start a new one
386
        self.repo.commit_write_group()
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
387
        self._save_id_map()
0.64.27 by Ian Clatworthy
1st cut at performance tuning
388
        self.repo.start_write_group()
0.64.5 by Ian Clatworthy
first cut at generic processing method
389
390
    def commit_handler(self, cmd):
391
        """Process a CommitCommand."""
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
392
        if self.skip_total and self._revision_count < self.skip_total:
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
393
            self.cache_mgr.track_heads(cmd)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
394
            # Check that we really do know about this commit-id
395
            if not self.cache_mgr.revision_ids.has_key(cmd.id):
396
                raise plugin_errors.BadRestart(cmd.id)
397
            # Consume the file commands and free any non-sticky blobs
398
            for fc in cmd.file_iter():
399
                pass
400
            self.cache_mgr._blobs = {}
401
            self._revision_count += 1
402
            # If we're finished getting back to where we were,
403
            # load the file-ids cache
404
            if self._revision_count == self.skip_total:
405
                self._gen_file_ids_cache()
406
                self.note("Generated the file-ids cache - %d entries",
407
                    len(self.cache_mgr.file_ids.keys()))
408
            return
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
409
        if self.first_incremental_commit:
410
            self.first_incremental_commit = None
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
411
            parents = self.cache_mgr.track_heads(cmd)
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
412
            self._gen_file_ids_cache(parents)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
413
414
        # 'Commit' the revision and report progress
0.84.4 by Ian Clatworthy
improved-but-not-yet-working CHKInventory support
415
        handler = self.commit_handler_factory(cmd, self.cache_mgr,
416
            self.rev_store, verbose=self.verbose)
0.64.27 by Ian Clatworthy
1st cut at performance tuning
417
        handler.process()
0.64.36 by Ian Clatworthy
fix head tracking when unmarked commits used
418
        self.cache_mgr.revision_ids[cmd.id] = handler.revision_id
0.64.27 by Ian Clatworthy
1st cut at performance tuning
419
        self._revision_count += 1
0.64.36 by Ian Clatworthy
fix head tracking when unmarked commits used
420
        self.report_progress("(%s)" % cmd.id)
0.64.31 by Ian Clatworthy
fix branch updating for the single branch case
421
422
        # Check if we should finish up or automatically checkpoint
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
423
        if (self.max_commits is not None and
424
            self._revision_count >= self.max_commits):
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
425
            self.note("Stopping after reaching requested count of commits")
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
426
            self.finished = True
427
        elif self._revision_count % self.checkpoint_every == 0:
428
            self.note("%d commits - automatic checkpoint triggered",
429
                self._revision_count)
430
            self.checkpoint_handler(None)
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
431
0.64.82 by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch
432
    def _gen_file_ids_cache(self, revs=False):
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
433
        """Generate the file-id cache by searching repository inventories.
434
        """
435
        # Get the interesting revisions - the heads
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
436
        if revs:
437
            head_ids = revs
438
        else:
439
            head_ids = self.cache_mgr.heads.keys()
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
440
        revision_ids = [self.cache_mgr.revision_ids[h] for h in head_ids]
441
442
        # Update the fileid cache
443
        file_ids = {}
444
        for revision_id in revision_ids:
445
            inv = self.repo.revision_tree(revision_id).inventory
0.64.93 by Ian Clatworthy
minor comment clean-ups
446
            # Cache the inventories while we're at it
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
447
            self.cache_mgr.inventories[revision_id] = inv
448
            for path, ie in inv.iter_entries():
449
                file_ids[path] = ie.file_id
450
        self.cache_mgr.file_ids = file_ids
451
0.64.25 by Ian Clatworthy
slightly better progress reporting
452
    def report_progress(self, details=''):
453
        # TODO: use a progress bar with ETA enabled
0.64.41 by Ian Clatworthy
update multiple working trees if requested
454
        if self._revision_count % self.progress_every == 0:
0.64.26 by Ian Clatworthy
more progress reporting tweaks
455
            if self.total_commits is not None:
456
                counts = "%d/%d" % (self._revision_count, self.total_commits)
457
                eta = progress.get_eta(self._start_time, self._revision_count,
458
                    self.total_commits)
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
459
                eta_str = progress.str_tdelta(eta)
460
                if eta_str.endswith('--'):
461
                    eta_str = ''
462
                else:
463
                    eta_str = '[%s] ' % eta_str
0.64.26 by Ian Clatworthy
more progress reporting tweaks
464
            else:
465
                counts = "%d" % (self._revision_count,)
466
                eta_str = ''
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
467
            self.note("%s commits processed %s%s" % (counts, eta_str, details))
0.64.25 by Ian Clatworthy
slightly better progress reporting
468
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
469
    def progress_handler(self, cmd):
470
        """Process a ProgressCommand."""
0.64.34 by Ian Clatworthy
report lost branches
471
        # We could use a progress bar here instead
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
472
        self.note("progress %s" % (cmd.message,))
0.64.5 by Ian Clatworthy
first cut at generic processing method
473
474
    def reset_handler(self, cmd):
475
        """Process a ResetCommand."""
0.64.12 by Ian Clatworthy
lightweight tags, filter processor and param validation
476
        if cmd.ref.startswith('refs/tags/'):
0.64.94 by Ian Clatworthy
ignore lightweight tags without a from clause
477
            tag_name = cmd.ref[len('refs/tags/'):]
0.64.95 by Ian Clatworthy
only output warning about missing from clause for lightweight tags in verbose mode
478
            if cmd.from_ is not None:
479
                self._set_tag(tag_name, cmd.from_)
480
            elif self.verbose:
0.64.94 by Ian Clatworthy
ignore lightweight tags without a from clause
481
                self.warning("ignoring reset refs/tags/%s - no from clause"
482
                    % tag_name)
0.64.109 by Ian Clatworthy
initial cut at reset support
483
            return
0.75.1 by Brian de Alwis
Add support for multiple branches by supporting the 'reset' command.
484
485
        if cmd.from_ is not None:
0.64.109 by Ian Clatworthy
initial cut at reset support
486
            self.cache_mgr.track_heads_for_ref(cmd.ref, cmd.from_)
0.64.5 by Ian Clatworthy
first cut at generic processing method
487
488
    def tag_handler(self, cmd):
489
        """Process a TagCommand."""
0.64.107 by Ian Clatworthy
warn on tags with a missing from clause
490
        if cmd.from_ is not None:
491
            self._set_tag(cmd.id, cmd.from_)
492
        else:
493
            self.warning("ignoring tag %s - no from clause" % cmd.id)
0.64.12 by Ian Clatworthy
lightweight tags, filter processor and param validation
494
495
    def _set_tag(self, name, from_):
0.64.93 by Ian Clatworthy
minor comment clean-ups
496
        """Define a tag given a name and import 'from' reference."""
0.64.12 by Ian Clatworthy
lightweight tags, filter processor and param validation
497
        bzr_tag_name = name.decode('utf-8', 'replace')
498
        bzr_rev_id = self.cache_mgr.revision_ids[from_]
0.64.11 by Ian Clatworthy
tag support
499
        self.tags[bzr_tag_name] = bzr_rev_id