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