/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
0.64.334 by Jelmer Vernooij
Remove old FSF address. Thanks Dan Callaghan.
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
15
16
"""Import processor that supports all Bazaar repository formats."""
17
18
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
19
import time
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
20
from .... import (
0.123.9 by Jelmer Vernooij
Provide stubs for logging functions no longer provided by python-fastimport.
21
    debug,
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
22
    delta,
0.64.5 by Ian Clatworthy
first cut at generic processing method
23
    errors,
24
    osutils,
0.64.26 by Ian Clatworthy
more progress reporting tweaks
25
    progress,
6846.3.1 by Jelmer Vernooij
Support '0' marker in fastimport plugin.
26
    revision as _mod_revision,
0.64.5 by Ian Clatworthy
first cut at generic processing method
27
    )
6670.4.5 by Jelmer Vernooij
Move breezy.repofmt contents to breezy.bzr.
28
from ....bzr.knitpack_repo import KnitPackRepository
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
29
from ....trace import (
0.123.9 by Jelmer Vernooij
Provide stubs for logging functions no longer provided by python-fastimport.
30
    mutter,
31
    note,
32
    warning,
33
    )
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
34
import configobj
35
from .. import (
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
36
    branch_updater,
0.78.3 by Ian Clatworthy
move GenericCacheManager into its own module
37
    cache_manager,
0.139.1 by Jelmer Vernooij
Import helper functions that have been removed from python-fastimport.
38
    helpers,
0.64.349 by Jelmer Vernooij
Reimport some modules removed from python-fastimport 0.9.2.
39
    idmapfile,
0.123.1 by Jelmer Vernooij
Move pure-fastimport code into its own directory, in preparation of splitting it into a separate package.
40
    marks_file,
41
    revision_store,
42
    )
0.123.2 by Jelmer Vernooij
Split out fastimport, import it from the system.
43
from fastimport import (
0.102.13 by Ian Clatworthy
Fix feature checking
44
    commands,
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
45
    errors as plugin_errors,
0.64.5 by Ian Clatworthy
first cut at generic processing method
46
    processor,
47
    )
6929.13.2 by Jelmer Vernooij
Remove functionality moved to fastimport.
48
from fastimport.helpers import (
49
    invert_dictset,
50
    )
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
51
52
0.64.41 by Ian Clatworthy
update multiple working trees if requested
53
# How many commits before automatically reporting progress
54
_DEFAULT_AUTO_PROGRESS = 1000
55
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
56
# How many commits before automatically checkpointing
57
_DEFAULT_AUTO_CHECKPOINT = 10000
58
0.64.170 by Ian Clatworthy
add autopack option to fast-import
59
# How many checkpoints before automatically packing
60
_DEFAULT_AUTO_PACK = 4
61
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
62
# How many inventories to cache
0.64.254 by Ian Clatworthy
Change the default inventory cache size to 1. For large projects, this reduces memory overhead and also speeds up conversion.
63
_DEFAULT_INV_CACHE_SIZE = 1
64
_DEFAULT_CHK_INV_CACHE_SIZE = 1
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
65
0.64.41 by Ian Clatworthy
update multiple working trees if requested
66
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
67
class GenericProcessor(processor.ImportProcessor):
68
    """An import processor that handles basic imports.
69
70
    Current features supported:
71
0.64.16 by Ian Clatworthy
safe processing tweaks
72
    * blobs are cached in memory
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
73
    * files and symlinks commits are supported
74
    * checkpoints automatically happen at a configurable frequency
75
      over and above the stream requested checkpoints
76
    * timestamped progress reporting, both automatic and stream requested
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
77
    * some basic statistics are dumped on completion.
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
78
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
79
    At checkpoints and on completion, the commit-id -> revision-id map is
80
    saved to a file called 'fastimport-id-map'. If the import crashes
81
    or is interrupted, it can be started again and this file will be
82
    used to skip over already loaded revisions. The format of each line
83
    is "commit-id revision-id" so commit-ids cannot include spaces.
84
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
85
    Here are the supported parameters:
86
0.64.38 by Ian Clatworthy
clean-up doc ready for initial release
87
    * info - name of a hints file holding the analysis generated
88
      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
89
      importing large repositories, this parameter is needed so
90
      that the importer knows what blobs to intelligently cache.
91
0.64.41 by Ian Clatworthy
update multiple working trees if requested
92
    * trees - update the working trees before completing.
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
93
      By default, the importer updates the repository
94
      and branches and the user needs to run 'bzr update' for the
0.64.41 by Ian Clatworthy
update multiple working trees if requested
95
      branches of interest afterwards.
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
96
0.64.170 by Ian Clatworthy
add autopack option to fast-import
97
    * count - only import this many commits then exit. If not set
98
      or negative, all commits are imported.
7143.15.2 by Jelmer Vernooij
Run autopep8.
99
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
100
    * checkpoint - automatically checkpoint every n commits over and
101
      above any checkpoints contained in the import stream.
102
      The default is 10000.
103
0.64.170 by Ian Clatworthy
add autopack option to fast-import
104
    * autopack - pack every n checkpoints. The default is 4.
105
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
106
    * inv-cache - number of inventories to cache.
0.64.254 by Ian Clatworthy
Change the default inventory cache size to 1. For large projects, this reduces memory overhead and also speeds up conversion.
107
      If not set, the default is 1.
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
108
7027.2.2 by Jelmer Vernooij
Drop mode=classic.
109
    * mode - import algorithm to use: default or experimental.
0.64.82 by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch
110
111
    * import-marks - name of file to read to load mark information from
112
113
    * 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
114
    """
115
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
116
    known_params = [
117
        'info',
118
        'trees',
0.64.170 by Ian Clatworthy
add autopack option to fast-import
119
        'count',
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
120
        'checkpoint',
0.64.170 by Ian Clatworthy
add autopack option to fast-import
121
        'autopack',
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
122
        'inv-cache',
0.64.171 by Ian Clatworthy
use inv deltas by default for all formats now: --classic to get old algorithm for packs
123
        'mode',
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
124
        'import-marks',
125
        'export-marks',
0.64.47 by Ian Clatworthy
add option for enabling experimental stuff
126
        ]
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
127
0.64.215 by Ian Clatworthy
tweak GenericProcessor __init__ method
128
    def __init__(self, bzrdir, params=None, verbose=False, outf=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
129
                 prune_empty_dirs=True):
0.123.4 by Jelmer Vernooij
Only require passing BzrDir to bzr-specific processors.
130
        processor.ImportProcessor.__init__(self, params, verbose)
0.64.196 by Ian Clatworthy
get tests passing again
131
        self.prune_empty_dirs = prune_empty_dirs
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
132
        self.controldir = bzrdir
0.123.4 by Jelmer Vernooij
Only require passing BzrDir to bzr-specific processors.
133
        try:
134
            # Might be inside a branch
135
            (self.working_tree, self.branch) = bzrdir._get_tree_branch()
136
            self.repo = self.branch.repository
137
        except errors.NotBranchError:
138
            # Must be inside a repository
139
            self.working_tree = None
140
            self.branch = None
141
            self.repo = bzrdir.open_repository()
0.64.196 by Ian Clatworthy
get tests passing again
142
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
143
    def pre_process(self):
0.64.26 by Ian Clatworthy
more progress reporting tweaks
144
        self._start_time = time.time()
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
145
        self._load_info_and_params()
0.102.18 by Ian Clatworthy
Tweak some diagnostic messages
146
        if self.total_commits:
147
            self.note("Starting import of %d commits ..." %
7143.15.2 by Jelmer Vernooij
Run autopep8.
148
                      (self.total_commits,))
0.102.18 by Ian Clatworthy
Tweak some diagnostic messages
149
        else:
150
            self.note("Starting import ...")
0.78.3 by Ian Clatworthy
move GenericCacheManager into its own module
151
        self.cache_mgr = cache_manager.CacheManager(self.info, self.verbose,
7143.15.2 by Jelmer Vernooij
Run autopep8.
152
                                                    self.inventory_cache_size)
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
153
0.64.82 by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch
154
        if self.params.get("import-marks") is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
155
            mark_info = marks_file.import_marks(
156
                self.params.get("import-marks"))
0.79.2 by Ian Clatworthy
extend & use marks_file API
157
            if mark_info is not None:
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
158
                self.cache_mgr.marks = mark_info
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
159
            self.skip_total = False
160
            self.first_incremental_commit = True
161
        else:
162
            self.first_incremental_commit = False
163
            self.skip_total = self._init_id_map()
164
            if self.skip_total:
165
                self.note("Found %d commits already loaded - "
7143.15.2 by Jelmer Vernooij
Run autopep8.
166
                          "skipping over these ...", self.skip_total)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
167
        self._revision_count = 0
168
169
        # mapping of tag name to revision_id
170
        self.tags = {}
171
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
172
        # Create the revision store to use for committing, if any
173
        self.rev_store = self._revision_store_factory()
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
174
0.64.51 by Ian Clatworthy
disable autopacking
175
        # Disable autopacking if the repo format supports it.
176
        # THIS IS A HACK - there is no sanctioned way of doing this yet.
0.64.313 by Jelmer Vernooij
Support both locations for KnitPackRepository.
177
        if isinstance(self.repo, KnitPackRepository):
0.64.51 by Ian Clatworthy
disable autopacking
178
            self._original_max_pack_count = \
179
                self.repo._pack_collection._max_pack_count
7143.15.2 by Jelmer Vernooij
Run autopep8.
180
0.64.51 by Ian Clatworthy
disable autopacking
181
            def _max_pack_count_for_import(total_revisions):
182
                return total_revisions + 1
183
            self.repo._pack_collection._max_pack_count = \
184
                _max_pack_count_for_import
185
        else:
186
            self._original_max_pack_count = None
7027.2.5 by Jelmer Vernooij
Drop unused methods.
187
0.64.144 by Ian Clatworthy
make groupcompress _FAST during import
188
        # Make groupcompress use the fast algorithm during importing.
189
        # We want to repack at the end anyhow when more information
190
        # is available to do a better job of saving space.
191
        try:
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
192
            from .... import groupcompress
0.64.144 by Ian Clatworthy
make groupcompress _FAST during import
193
            groupcompress._FAST = True
194
        except ImportError:
195
            pass
196
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
197
        # Create a write group. This is committed at the end of the import.
198
        # Checkpointing closes the current one and starts a new one.
199
        self.repo.start_write_group()
200
201
    def _load_info_and_params(self):
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
202
        from .. import bzr_commit_handler
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
203
        # This is currently hard-coded but might be configurable via
204
        # parameters one day if that's needed
7290.41.1 by Jelmer Vernooij
Drop unused mode flag, use standard transport.
205
        repo_transport = self.repo.control_transport
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
206
        self.id_map_path = repo_transport.local_abspath("fastimport-id-map")
207
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
208
        # Load the info file, if any
209
        info_path = self.params.get('info')
210
        if info_path is not None:
211
            self.info = configobj.ConfigObj(info_path)
212
        else:
213
            self.info = None
214
7027.2.4 by Jelmer Vernooij
Drop multiple CommitHandler implementations.
215
        self.supports_chk = self.repo._format.supports_chks
216
        self.commit_handler_factory = bzr_commit_handler.CommitHandler
0.84.4 by Ian Clatworthy
improved-but-not-yet-working CHKInventory support
217
0.64.41 by Ian Clatworthy
update multiple working trees if requested
218
        # Decide how often to automatically report progress
219
        # (not a parameter yet)
220
        self.progress_every = _DEFAULT_AUTO_PROGRESS
221
        if self.verbose:
222
            self.progress_every = self.progress_every / 10
223
0.64.170 by Ian Clatworthy
add autopack option to fast-import
224
        # Decide how often (# of commits) to automatically checkpoint
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
225
        self.checkpoint_every = int(self.params.get('checkpoint',
7143.15.2 by Jelmer Vernooij
Run autopep8.
226
                                                    _DEFAULT_AUTO_CHECKPOINT))
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
227
0.64.170 by Ian Clatworthy
add autopack option to fast-import
228
        # Decide how often (# of checkpoints) to automatically pack
229
        self.checkpoint_count = 0
230
        self.autopack_every = int(self.params.get('autopack',
7143.15.2 by Jelmer Vernooij
Run autopep8.
231
                                                  _DEFAULT_AUTO_PACK))
0.64.170 by Ian Clatworthy
add autopack option to fast-import
232
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
233
        # Decide how big to make the inventory cache
0.64.149 by Ian Clatworthy
larger default inventory cache for chk formats
234
        cache_size = int(self.params.get('inv-cache', -1))
235
        if cache_size == -1:
0.64.167 by Ian Clatworthy
incremental packing for chk formats
236
            if self.supports_chk:
0.64.149 by Ian Clatworthy
larger default inventory cache for chk formats
237
                cache_size = _DEFAULT_CHK_INV_CACHE_SIZE
238
            else:
239
                cache_size = _DEFAULT_INV_CACHE_SIZE
240
        self.inventory_cache_size = cache_size
0.64.44 by Ian Clatworthy
smart caching of serialised inventories
241
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
242
        # Find the maximum number of commits to import (None means all)
243
        # and prepare progress reporting. Just in case the info file
244
        # has an outdated count of commits, we store the max counts
245
        # at which we need to terminate separately to the total used
246
        # for progress tracking.
247
        try:
248
            self.max_commits = int(self.params['count'])
0.64.38 by Ian Clatworthy
clean-up doc ready for initial release
249
            if self.max_commits < 0:
250
                self.max_commits = None
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
251
        except KeyError:
252
            self.max_commits = None
0.64.25 by Ian Clatworthy
slightly better progress reporting
253
        if self.info is not None:
254
            self.total_commits = int(self.info['Command counts']['commit'])
7143.15.2 by Jelmer Vernooij
Run autopep8.
255
            if (self.max_commits is not None
256
                    and self.total_commits > self.max_commits):
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
257
                self.total_commits = self.max_commits
0.64.25 by Ian Clatworthy
slightly better progress reporting
258
        else:
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
259
            self.total_commits = self.max_commits
0.64.25 by Ian Clatworthy
slightly better progress reporting
260
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
261
    def _revision_store_factory(self):
262
        """Make a RevisionStore based on what the repository supports."""
7027.2.3 by Jelmer Vernooij
Drop old RevisionStore implementation.
263
        return revision_store.RevisionStore(self.repo)
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
264
0.123.5 by Jelmer Vernooij
Fix typo, handle bzr-specific locking in GenericProcessor.
265
    def process(self, command_iter):
266
        """Import data into Bazaar by processing a stream of commands.
267
268
        :param command_iter: an iterator providing commands
269
        """
270
        if self.working_tree is not None:
271
            self.working_tree.lock_write()
272
        elif self.branch is not None:
273
            self.branch.lock_write()
274
        elif self.repo is not None:
275
            self.repo.lock_write()
276
        try:
277
            super(GenericProcessor, self)._process(command_iter)
278
        finally:
279
            # If an unhandled exception occurred, abort the write group
280
            if self.repo is not None and self.repo.is_in_write_group():
281
                self.repo.abort_write_group()
282
            # Release the locks
283
            if self.working_tree is not None:
284
                self.working_tree.unlock()
285
            elif self.branch is not None:
286
                self.branch.unlock()
287
            elif self.repo is not None:
288
                self.repo.unlock()
289
0.64.27 by Ian Clatworthy
1st cut at performance tuning
290
    def _process(self, command_iter):
291
        # if anything goes wrong, abort the write group if any
292
        try:
293
            processor.ImportProcessor._process(self, command_iter)
294
        except:
295
            if self.repo is not None and self.repo.is_in_write_group():
296
                self.repo.abort_write_group()
297
            raise
298
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
299
    def post_process(self):
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
300
        # Commit the current write group and checkpoint the id map
0.64.27 by Ian Clatworthy
1st cut at performance tuning
301
        self.repo.commit_write_group()
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
302
        self._save_id_map()
0.64.27 by Ian Clatworthy
1st cut at performance tuning
303
0.64.82 by Ian Clatworthy
Merge Pieter de Bie's export-fixes branch
304
        if self.params.get("export-marks") is not None:
0.78.5 by Ian Clatworthy
move import/export of marks into a module
305
            marks_file.export_marks(self.params.get("export-marks"),
7143.15.2 by Jelmer Vernooij
Run autopep8.
306
                                    self.cache_mgr.marks)
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
307
7183.3.1 by Martin
Fix E71* lint errors
308
        if self.cache_mgr.reftracker.last_ref is None:
0.97.1 by Gonéri Le Bouder
avoid STDERR crash
309
            """Nothing to refresh"""
310
            return
311
0.64.31 by Ian Clatworthy
fix branch updating for the single branch case
312
        # Update the branches
313
        self.note("Updating branch information ...")
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
314
        updater = branch_updater.BranchUpdater(self.repo, self.branch,
7143.15.2 by Jelmer Vernooij
Run autopep8.
315
                                               self.cache_mgr, invert_dictset(
316
                                                   self.cache_mgr.reftracker.heads),
317
                                               self.cache_mgr.reftracker.last_ref, self.tags)
0.64.34 by Ian Clatworthy
report lost branches
318
        branches_updated, branches_lost = updater.update()
319
        self._branch_count = len(branches_updated)
320
321
        # Tell the user about branches that were not created
322
        if branches_lost:
0.64.37 by Ian Clatworthy
create branches as required
323
            if not self.repo.is_shared():
324
                self.warning("Cannot import multiple branches into "
7143.15.2 by Jelmer Vernooij
Run autopep8.
325
                             "a standalone branch")
0.64.37 by Ian Clatworthy
create branches as required
326
            self.warning("Not creating branches for these head revisions:")
0.64.34 by Ian Clatworthy
report lost branches
327
            for lost_info in branches_lost:
328
                head_revision = lost_info[1]
329
                branch_name = lost_info[0]
0.64.67 by James Westby
Add support for -Dfast-import.
330
                self.note("\t %s = %s", head_revision, branch_name)
0.64.34 by Ian Clatworthy
report lost branches
331
0.64.168 by Ian Clatworthy
blob reference counting, not just sticky vs otherwise
332
        # Update the working trees as requested
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
333
        self._tree_count = 0
0.64.34 by Ian Clatworthy
report lost branches
334
        remind_about_update = True
0.64.54 by Ian Clatworthy
handle existing branches and only count the branches really updated
335
        if self._branch_count == 0:
336
            self.note("no branches to update")
337
            self.note("no working trees to update")
338
            remind_about_update = False
339
        elif self.params.get('trees', False):
0.64.41 by Ian Clatworthy
update multiple working trees if requested
340
            trees = self._get_working_trees(branches_updated)
341
            if trees:
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
342
                self._update_working_trees(trees)
0.64.34 by Ian Clatworthy
report lost branches
343
                remind_about_update = False
0.64.41 by Ian Clatworthy
update multiple working trees if requested
344
            else:
345
                self.warning("No working trees available to update")
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
346
        else:
347
            # Update just the trunk. (This is always the first branch
348
            # returned by the branch updater.)
349
            trunk_branch = branches_updated[0]
350
            trees = self._get_working_trees([trunk_branch])
351
            if trees:
352
                self._update_working_trees(trees)
353
                remind_about_update = self._branch_count > 1
0.64.51 by Ian Clatworthy
disable autopacking
354
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
355
        # Dump the cache stats now because we clear it before the final pack
0.64.168 by Ian Clatworthy
blob reference counting, not just sticky vs otherwise
356
        if self.verbose:
357
            self.cache_mgr.dump_stats()
0.64.51 by Ian Clatworthy
disable autopacking
358
        if self._original_max_pack_count:
359
            # We earlier disabled autopacking, creating one pack every
0.64.75 by Ian Clatworthy
if checkpointed, pack repository and delete obsolete_packs
360
            # checkpoint instead. We now pack the repository to optimise
361
            # how data is stored.
0.64.168 by Ian Clatworthy
blob reference counting, not just sticky vs otherwise
362
            self.cache_mgr.clear_all()
0.64.162 by Ian Clatworthy
always repack the repository on completion
363
            self._pack_repository()
364
0.64.168 by Ian Clatworthy
blob reference counting, not just sticky vs otherwise
365
        # Finish up by dumping stats & telling the user what to do next.
366
        self.dump_stats()
0.64.34 by Ian Clatworthy
report lost branches
367
        if remind_about_update:
0.64.75 by Ian Clatworthy
if checkpointed, pack repository and delete obsolete_packs
368
            # This message is explicitly not timestamped.
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
369
            note("To refresh the working tree for other branches, "
7143.15.2 by Jelmer Vernooij
Run autopep8.
370
                 "use 'bzr update' inside that branch.")
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
371
372
    def _update_working_trees(self, trees):
373
        if self.verbose:
374
            reporter = delta._ChangeReporter()
375
        else:
376
            reporter = None
377
        for wt in trees:
378
            self.note("Updating the working tree for %s ...", wt.basedir)
379
            wt.update(reporter)
380
            self._tree_count += 1
0.64.41 by Ian Clatworthy
update multiple working trees if requested
381
0.64.167 by Ian Clatworthy
incremental packing for chk formats
382
    def _pack_repository(self, final=True):
0.64.162 by Ian Clatworthy
always repack the repository on completion
383
        # Before packing, free whatever memory we can and ensure
384
        # that groupcompress is configured to optimise disk space
385
        import gc
0.64.167 by Ian Clatworthy
incremental packing for chk formats
386
        if final:
387
            try:
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
388
                from .... import groupcompress
0.64.167 by Ian Clatworthy
incremental packing for chk formats
389
            except ImportError:
390
                pass
391
            else:
392
                groupcompress._FAST = False
0.64.162 by Ian Clatworthy
always repack the repository on completion
393
        gc.collect()
394
        self.note("Packing repository ...")
395
        self.repo.pack()
396
397
        # To be conservative, packing puts the old packs and
398
        # indices in obsolete_packs. We err on the side of
399
        # optimism and clear out that directory to save space.
400
        self.note("Removing obsolete packs ...")
401
        # TODO: Use a public API for this once one exists
402
        repo_transport = self.repo._pack_collection.transport
6926.1.1 by Jelmer Vernooij
Remove delete_multi.
403
        obsolete_pack_transport = repo_transport.clone('obsolete_packs')
404
        for name in obsolete_pack_transport.list_dir('.'):
405
            obsolete_pack_transport.delete(name)
0.64.162 by Ian Clatworthy
always repack the repository on completion
406
0.64.167 by Ian Clatworthy
incremental packing for chk formats
407
        # If we're not done, free whatever memory we can
408
        if not final:
409
            gc.collect()
410
0.64.41 by Ian Clatworthy
update multiple working trees if requested
411
    def _get_working_trees(self, branches):
412
        """Get the working trees for branches in the repository."""
413
        result = []
414
        wt_expected = self.repo.make_working_trees()
415
        for br in branches:
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
416
            if br is None:
417
                continue
418
            elif br == self.branch:
419
                if self.working_tree:
420
                    result.append(self.working_tree)
0.64.41 by Ian Clatworthy
update multiple working trees if requested
421
            elif wt_expected:
422
                try:
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
423
                    result.append(br.controldir.open_workingtree())
0.64.41 by Ian Clatworthy
update multiple working trees if requested
424
                except errors.NoWorkingTree:
425
                    self.warning("No working tree for branch %s", br)
426
        return result
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
427
428
    def dump_stats(self):
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
429
        time_required = progress.str_tdelta(time.time() - self._start_time)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
430
        rc = self._revision_count - self.skip_total
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
431
        bc = self._branch_count
0.64.33 by Ian Clatworthy
make tree updating optional and minor UI improvements
432
        wtc = self._tree_count
433
        self.note("Imported %d %s, updating %d %s and %d %s in %s",
7143.15.2 by Jelmer Vernooij
Run autopep8.
434
                  rc, helpers.single_plural(rc, "revision", "revisions"),
435
                  bc, helpers.single_plural(bc, "branch", "branches"),
436
                  wtc, helpers.single_plural(wtc, "tree", "trees"),
437
                  time_required)
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
438
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
439
    def _init_id_map(self):
440
        """Load the id-map and check it matches the repository.
6846.3.1 by Jelmer Vernooij
Support '0' marker in fastimport plugin.
441
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
442
        :return: the number of entries in the map
443
        """
444
        # Currently, we just check the size. In the future, we might
445
        # decide to be more paranoid and check that the revision-ids
446
        # are identical as well.
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
447
        self.cache_mgr.marks, known = idmapfile.load_id_map(
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
448
            self.id_map_path)
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
449
        if self.cache_mgr.add_mark(b'0', _mod_revision.NULL_REVISION):
6846.3.1 by Jelmer Vernooij
Support '0' marker in fastimport plugin.
450
            known += 1
451
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
452
        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
453
        if existing_count < known:
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
454
            raise plugin_errors.BadRepositorySize(known, existing_count)
455
        return known
456
457
    def _save_id_map(self):
458
        """Save the id-map."""
459
        # Save the whole lot every time. If this proves a problem, we can
460
        # change to 'append just the new ones' at a later time.
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
461
        idmapfile.save_id_map(self.id_map_path, self.cache_mgr.marks)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
462
0.64.5 by Ian Clatworthy
first cut at generic processing method
463
    def blob_handler(self, cmd):
464
        """Process a BlobCommand."""
465
        if cmd.mark is not None:
0.64.36 by Ian Clatworthy
fix head tracking when unmarked commits used
466
            dataref = cmd.id
0.64.5 by Ian Clatworthy
first cut at generic processing method
467
        else:
468
            dataref = osutils.sha_strings(cmd.data)
0.64.24 by Ian Clatworthy
smart blob caching using analysis done by --info
469
        self.cache_mgr.store_blob(dataref, cmd.data)
0.64.5 by Ian Clatworthy
first cut at generic processing method
470
0.64.170 by Ian Clatworthy
add autopack option to fast-import
471
    def checkpoint_handler(self, cmd):
0.64.5 by Ian Clatworthy
first cut at generic processing method
472
        """Process a CheckpointCommand."""
0.64.27 by Ian Clatworthy
1st cut at performance tuning
473
        # Commit the current write group and start a new one
474
        self.repo.commit_write_group()
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
475
        self._save_id_map()
0.64.220 by Ian Clatworthy
Only count implicit checkpoints when deciding when to auto-pack
476
        # track the number of automatic checkpoints done
477
        if cmd is None:
478
            self.checkpoint_count += 1
479
            if self.checkpoint_count % self.autopack_every == 0:
480
                self._pack_repository(final=False)
0.64.27 by Ian Clatworthy
1st cut at performance tuning
481
        self.repo.start_write_group()
0.64.5 by Ian Clatworthy
first cut at generic processing method
482
483
    def commit_handler(self, cmd):
484
        """Process a CommitCommand."""
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
485
        mark = cmd.id.lstrip(b':')
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
486
        if self.skip_total and self._revision_count < self.skip_total:
0.123.6 by Jelmer Vernooij
Split out reftracker.
487
            self.cache_mgr.reftracker.track_heads(cmd)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
488
            # Check that we really do know about this commit-id
7195.3.1 by Martin
Remove use of dict.has_key() in fastimport plugin
489
            if mark not in self.cache_mgr.marks:
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
490
                raise plugin_errors.BadRestart(mark)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
491
            self.cache_mgr._blobs = {}
492
            self._revision_count += 1
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
493
            if cmd.ref.startswith(b'refs/tags/'):
494
                tag_name = cmd.ref[len(b'refs/tags/'):]
0.111.2 by Max Bowsher
Also catch tagging via commit when resuming a crashed import.
495
                self._set_tag(tag_name, cmd.id)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
496
            return
0.68.7 by Pieter de Bie
Add importing and exporting of marks to bzr-fastimport
497
        if self.first_incremental_commit:
498
            self.first_incremental_commit = None
0.123.6 by Jelmer Vernooij
Split out reftracker.
499
            parents = self.cache_mgr.reftracker.track_heads(cmd)
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
500
501
        # 'Commit' the revision and report progress
0.84.4 by Ian Clatworthy
improved-but-not-yet-working CHKInventory support
502
        handler = self.commit_handler_factory(cmd, self.cache_mgr,
7143.15.2 by Jelmer Vernooij
Run autopep8.
503
                                              self.rev_store, verbose=self.verbose,
504
                                              prune_empty_dirs=self.prune_empty_dirs)
0.64.180 by Ian Clatworthy
report triggering commit when exception occurs
505
        try:
506
            handler.process()
507
        except:
6855.3.1 by Jelmer Vernooij
Several more fixes.
508
            print("ABORT: exception occurred processing commit %s" % (cmd.id))
0.64.180 by Ian Clatworthy
report triggering commit when exception occurs
509
            raise
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
510
        self.cache_mgr.add_mark(mark, handler.revision_id)
0.64.27 by Ian Clatworthy
1st cut at performance tuning
511
        self._revision_count += 1
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
512
        self.report_progress("(%s)" % cmd.id.lstrip(b':'))
0.64.31 by Ian Clatworthy
fix branch updating for the single branch case
513
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
514
        if cmd.ref.startswith(b'refs/tags/'):
515
            tag_name = cmd.ref[len(b'refs/tags/'):]
0.111.1 by Max Bowsher
Set a tag when touching a refs/tags/ ref with a commit command.
516
            self._set_tag(tag_name, cmd.id)
517
0.64.31 by Ian Clatworthy
fix branch updating for the single branch case
518
        # Check if we should finish up or automatically checkpoint
7143.15.2 by Jelmer Vernooij
Run autopep8.
519
        if (self.max_commits is not None
520
                and self._revision_count >= self.max_commits):
0.64.50 by Ian Clatworthy
cleanly restart after an interruption - basic mirroring
521
            self.note("Stopping after reaching requested count of commits")
0.64.28 by Ian Clatworthy
checkpoint and count params to generic processor
522
            self.finished = True
523
        elif self._revision_count % self.checkpoint_every == 0:
524
            self.note("%d commits - automatic checkpoint triggered",
7143.15.2 by Jelmer Vernooij
Run autopep8.
525
                      self._revision_count)
0.64.170 by Ian Clatworthy
add autopack option to fast-import
526
            self.checkpoint_handler(None)
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
527
0.64.25 by Ian Clatworthy
slightly better progress reporting
528
    def report_progress(self, details=''):
0.64.41 by Ian Clatworthy
update multiple working trees if requested
529
        if self._revision_count % self.progress_every == 0:
0.64.152 by Ian Clatworthy
miscellaneous progress reporting fixes
530
            if self.total_commits is not None:
0.64.26 by Ian Clatworthy
more progress reporting tweaks
531
                counts = "%d/%d" % (self._revision_count, self.total_commits)
532
            else:
533
                counts = "%d" % (self._revision_count,)
0.64.152 by Ian Clatworthy
miscellaneous progress reporting fixes
534
            minutes = (time.time() - self._start_time) / 60
535
            revisions_added = self._revision_count - self.skip_total
536
            rate = revisions_added * 1.0 / minutes
537
            if rate > 10:
538
                rate_str = "at %.0f/minute " % rate
539
            else:
540
                rate_str = "at %.1f/minute " % rate
7143.15.2 by Jelmer Vernooij
Run autopep8.
541
            self.note("%s commits processed %s%s" %
542
                      (counts, rate_str, details))
0.64.25 by Ian Clatworthy
slightly better progress reporting
543
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
544
    def progress_handler(self, cmd):
545
        """Process a ProgressCommand."""
0.64.271 by Ian Clatworthy
Ignore progress messages unless in verbose mode
546
        # Most progress messages embedded in streams are annoying.
547
        # Ignore them unless in verbose mode.
548
        if self.verbose:
549
            self.note("progress %s" % (cmd.message,))
0.64.5 by Ian Clatworthy
first cut at generic processing method
550
551
    def reset_handler(self, cmd):
552
        """Process a ResetCommand."""
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
553
        if cmd.ref.startswith(b'refs/tags/'):
554
            tag_name = cmd.ref[len(b'refs/tags/'):]
0.64.95 by Ian Clatworthy
only output warning about missing from clause for lightweight tags in verbose mode
555
            if cmd.from_ is not None:
556
                self._set_tag(tag_name, cmd.from_)
557
            elif self.verbose:
0.64.94 by Ian Clatworthy
ignore lightweight tags without a from clause
558
                self.warning("ignoring reset refs/tags/%s - no from clause"
7143.15.2 by Jelmer Vernooij
Run autopep8.
559
                             % tag_name)
0.64.109 by Ian Clatworthy
initial cut at reset support
560
            return
0.75.1 by Brian de Alwis
Add support for multiple branches by supporting the 'reset' command.
561
562
        if cmd.from_ is not None:
0.123.6 by Jelmer Vernooij
Split out reftracker.
563
            self.cache_mgr.reftracker.track_heads_for_ref(cmd.ref, cmd.from_)
0.64.5 by Ian Clatworthy
first cut at generic processing method
564
565
    def tag_handler(self, cmd):
566
        """Process a TagCommand."""
0.64.107 by Ian Clatworthy
warn on tags with a missing from clause
567
        if cmd.from_ is not None:
568
            self._set_tag(cmd.id, cmd.from_)
569
        else:
570
            self.warning("ignoring tag %s - no from clause" % cmd.id)
0.64.12 by Ian Clatworthy
lightweight tags, filter processor and param validation
571
572
    def _set_tag(self, name, from_):
0.64.93 by Ian Clatworthy
minor comment clean-ups
573
        """Define a tag given a name and import 'from' reference."""
0.64.12 by Ian Clatworthy
lightweight tags, filter processor and param validation
574
        bzr_tag_name = name.decode('utf-8', 'replace')
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
575
        bzr_rev_id = self.cache_mgr.lookup_committish(from_)
0.64.11 by Ian Clatworthy
tag support
576
        self.tags[bzr_tag_name] = bzr_rev_id
0.102.9 by Ian Clatworthy
parsing of multiple authors and commit properties
577
578
    def feature_handler(self, cmd):
579
        """Process a FeatureCommand."""
0.102.11 by Ian Clatworthy
Validate features are known before importing
580
        feature = cmd.feature_name
581
        if feature not in commands.FEATURE_NAMES:
582
            raise plugin_errors.UnknownFeature(feature)
0.123.9 by Jelmer Vernooij
Provide stubs for logging functions no longer provided by python-fastimport.
583
0.64.297 by Jelmer Vernooij
Fix typo.
584
    def debug(self, msg, *args):
0.123.9 by Jelmer Vernooij
Provide stubs for logging functions no longer provided by python-fastimport.
585
        """Output a debug message if the appropriate -D option was given."""
586
        if "fast-import" in debug.debug_flags:
587
            msg = "%s DEBUG: %s" % (self._time_of_day(), msg)
588
            mutter(msg, *args)
589
590
    def note(self, msg, *args):
591
        """Output a note but timestamp it."""
592
        msg = "%s %s" % (self._time_of_day(), msg)
593
        note(msg, *args)
594
595
    def warning(self, msg, *args):
596
        """Output a warning but timestamp it."""
597
        msg = "%s WARNING: %s" % (self._time_of_day(), msg)
598
        warning(msg, *args)