/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.64.128 by Ian Clatworthy
fix encoding issue in bzr_exporter (Teemu Likonen)
1
# -*- coding: utf-8 -*-
2
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
3
# Copyright (C) 2008 Canonical Ltd
4
#
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
#
15
# 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.
16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
17
#
0.64.333 by Jelmer Vernooij
Inline bzr-fast-export license.
18
# Based on bzr-fast-export
19
# Copyright (c) 2008 Adeodato Simó
20
#
21
# Permission is hereby granted, free of charge, to any person obtaining
22
# a copy of this software and associated documentation files (the
23
# "Software"), to deal in the Software without restriction, including
24
# without limitation the rights to use, copy, modify, merge, publish,
25
# distribute, sublicense, and/or sell copies of the Software, and to
26
# permit persons to whom the Software is furnished to do so, subject to
27
# the following conditions:
28
#
29
# The above copyright notice and this permission notice shall be included
30
# in all copies or substantial portions of the Software.
31
#
32
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
35
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
36
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
37
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
38
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0.79.10 by Ian Clatworthy
documentation clean-ups
39
#
0.64.57 by Ian Clatworthy
integrate dato's bzr-fast-export
40
# vim: fileencoding=utf-8
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
41
42
"""Core engine for the fast-export command."""
0.64.57 by Ian Clatworthy
integrate dato's bzr-fast-export
43
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
44
from __future__ import absolute_import
45
0.79.7 by Ian Clatworthy
trivial bzr_exporter clean-ups
46
# TODO: if a new_git_branch below gets merged repeatedly, the tip of the branch
0.64.57 by Ian Clatworthy
integrate dato's bzr-fast-export
47
# is not updated (because the parent of commit is already merged, so we don't
48
# set new_git_branch to the previously used name)
49
6791.2.4 by Jelmer Vernooij
Fix python3isms.
50
try:
51
    from email.utils import parseaddr
52
except ImportError:  # python < 3
53
    from email.Utils import parseaddr
7143.15.2 by Jelmer Vernooij
Run autopep8.
54
import sys
55
import time
56
import re
0.64.57 by Ian Clatworthy
integrate dato's bzr-fast-export
57
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
58
import breezy.branch
59
import breezy.revision
60
from ... import (
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
61
    builtins,
62
    errors as bazErrors,
6628.1.5 by Jelmer Vernooij
Consistently use fastimport feature.
63
    lazy_import,
0.64.237 by Ian Clatworthy
implicitly rename children on export when directory renamed
64
    osutils,
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
65
    progress,
66
    trace,
67
    )
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
68
from ...sixish import (
69
    int2byte,
7045.4.18 by Jelmer Vernooij
Fix compatibility with older versions of fastimport.
70
    PY3,
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
71
    viewitems,
72
    )
0.79.4 by Ian Clatworthy
use note and warning APIs
73
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
74
from . import (
0.64.284 by Jelmer Vernooij
Fix import of single_plural.
75
    helpers,
76
    marks_file,
77
    )
0.79.2 by Ian Clatworthy
extend & use marks_file API
78
6628.1.5 by Jelmer Vernooij
Consistently use fastimport feature.
79
lazy_import.lazy_import(globals(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
80
                        """
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
81
from fastimport import commands
6628.1.5 by Jelmer Vernooij
Consistently use fastimport feature.
82
""")
0.64.282 by Jelmer Vernooij
Fix output stream to stdout for bzr fast-export.
83
84
85
def _get_output_stream(destination):
86
    if destination is None or destination == '-':
7211.12.2 by Jelmer Vernooij
Unwrap sys.stdout.
87
        return helpers.binary_stream(getattr(sys.stdout, "buffer", sys.stdout))
7239.2.1 by Jelmer Vernooij
Require a dot in the extension for .gz
88
    elif destination.endswith('.gz'):
0.64.282 by Jelmer Vernooij
Fix output stream to stdout for bzr fast-export.
89
        import gzip
90
        return gzip.open(destination, 'wb')
91
    else:
92
        return open(destination, 'wb')
93
0.64.328 by Jelmer Vernooij
In "plain" mode, skip tags that contain characters not valid in Git.
94
# from dulwich.repo:
7143.15.2 by Jelmer Vernooij
Run autopep8.
95
96
0.64.328 by Jelmer Vernooij
In "plain" mode, skip tags that contain characters not valid in Git.
97
def check_ref_format(refname):
98
    """Check if a refname is correctly formatted.
99
100
    Implements all the same rules as git-check-ref-format[1].
101
102
    [1] http://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
103
104
    :param refname: The refname to check
105
    :return: True if refname is valid, False otherwise
106
    """
107
    # These could be combined into one big expression, but are listed separately
108
    # to parallel [1].
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
109
    if b'/.' in refname or refname.startswith(b'.'):
110
        return False
111
    if b'/' not in refname:
112
        return False
113
    if b'..' in refname:
114
        return False
115
    for i in range(len(refname)):
7143.15.2 by Jelmer Vernooij
Run autopep8.
116
        if ord(refname[i:i + 1]) < 0o40 or refname[i] in b'\177 ~^:?*[':
0.64.328 by Jelmer Vernooij
In "plain" mode, skip tags that contain characters not valid in Git.
117
            return False
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
118
    if refname[-1] in b'/.':
119
        return False
120
    if refname.endswith(b'.lock'):
121
        return False
122
    if b'@{' in refname:
123
        return False
124
    if b'\\' in refname:
0.64.328 by Jelmer Vernooij
In "plain" mode, skip tags that contain characters not valid in Git.
125
        return False
126
    return True
127
0.133.3 by Oleksandr Usov
Implement comments from patch review:
128
129
def sanitize_ref_name_for_git(refname):
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
130
    """Rewrite refname so that it will be accepted by git-fast-import.
131
    For the detailed rules see check_ref_format.
132
133
    By rewriting the refname we are breaking uniqueness guarantees provided by bzr
134
    so we have to manually
135
    verify that resulting ref names are unique.
136
137
    :param refname: refname to rewrite
138
    :return: new refname
139
    """
0.133.3 by Oleksandr Usov
Implement comments from patch review:
140
    new_refname = re.sub(
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
141
        # '/.' in refname or startswith '.'
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
142
        br"/\.|^\."
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
143
        # '..' in refname
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
144
        br"|\.\."
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
145
        # ord(c) < 040
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
146
        br"|[" + b"".join([int2byte(x) for x in range(0o40)]) + br"]"
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
147
        # c in '\177 ~^:?*['
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
148
        br"|[\177 ~^:?*[]"
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
149
        # last char in "/."
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
150
        br"|[/.]$"
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
151
        # endswith '.lock'
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
152
        br"|.lock$"
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
153
        # "@{" in refname
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
154
        br"|@{"
0.133.1 by Oleksandr Usov
Add function to rewrite refnames & tests for it
155
        # "\\" in refname
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
156
        br"|\\",
157
        b"_", refname)
0.133.3 by Oleksandr Usov
Implement comments from patch review:
158
    return new_refname
0.64.173 by Ian Clatworthy
add -r option to fast-export
159
0.64.339 by Jelmer Vernooij
Some refactoring of exporter.
160
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
161
class BzrFastExporter(object):
0.68.1 by Pieter de Bie
Classify bzr-fast-export
162
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
163
    def __init__(self, source, outf, ref=None, checkpoint=-1,
7143.15.2 by Jelmer Vernooij
Run autopep8.
164
                 import_marks_file=None, export_marks_file=None, revision=None,
165
                 verbose=False, plain_format=False, rewrite_tags=False,
166
                 no_tags=False, baseline=False):
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
167
        """Export branch data in fast import format.
168
169
        :param plain_format: if True, 'classic' fast-import format is
0.64.337 by Jelmer Vernooij
Merge support for --rewrite-tag-names.
170
            used without any extended features; if False, the generated
171
            data is richer and includes information like multiple
172
            authors, revision properties, etc.
173
        :param rewrite_tags: if True and if plain_format is set, tag names
174
            will be rewritten to be git-compatible.
175
            Otherwise tags which aren't valid for git will be skipped if
176
            plain_format is set.
0.138.1 by Oleksandr Usov
Add --no-tags flag
177
        :param no_tags: if True tags won't be exported at all
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
178
        """
0.64.339 by Jelmer Vernooij
Some refactoring of exporter.
179
        self.branch = source
180
        self.outf = outf
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
181
        self.ref = ref
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
182
        self.checkpoint = checkpoint
183
        self.import_marks_file = import_marks_file
184
        self.export_marks_file = export_marks_file
0.64.173 by Ian Clatworthy
add -r option to fast-export
185
        self.revision = revision
186
        self.excluded_revisions = set()
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
187
        self.plain_format = plain_format
0.133.2 by Oleksandr Usov
Rewrite tag names when exporting plain stream
188
        self.rewrite_tags = rewrite_tags
0.138.1 by Oleksandr Usov
Add --no-tags flag
189
        self.no_tags = no_tags
0.135.1 by Andy Grimm
Add --baseline option
190
        self.baseline = baseline
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
191
        self._multi_author_api_available = hasattr(breezy.revision.Revision,
7143.15.2 by Jelmer Vernooij
Run autopep8.
192
                                                   'get_apparent_authors')
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
193
        self.properties_to_exclude = ['authors', 'author']
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
194
195
        # Progress reporting stuff
196
        self.verbose = verbose
197
        if verbose:
198
            self.progress_every = 100
199
        else:
200
            self.progress_every = 1000
201
        self._start_time = time.time()
0.64.230 by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export
202
        self._commit_total = 0
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
203
204
        # Load the marks and initialise things accordingly
0.68.1 by Pieter de Bie
Classify bzr-fast-export
205
        self.revid_to_mark = {}
206
        self.branch_names = {}
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
207
        if self.import_marks_file:
0.79.2 by Ian Clatworthy
extend & use marks_file API
208
            marks_info = marks_file.import_marks(self.import_marks_file)
209
            if marks_info is not None:
0.64.134 by Ian Clatworthy
fix marks importing in fast-export
210
                self.revid_to_mark = dict((r, m) for m, r in
7143.15.2 by Jelmer Vernooij
Run autopep8.
211
                                          marks_info.items())
0.125.1 by Ian Clatworthy
Use the new marks file format (introduced in git 1.6 apparently)
212
                # These are no longer included in the marks file
213
                #self.branch_names = marks_info[1]
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
214
0.64.173 by Ian Clatworthy
add -r option to fast-export
215
    def interesting_history(self):
216
        if self.revision:
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
217
            rev1, rev2 = builtins._get_revision_range(self.revision,
7143.15.2 by Jelmer Vernooij
Run autopep8.
218
                                                      self.branch, "fast-export")
0.64.173 by Ian Clatworthy
add -r option to fast-export
219
            start_rev_id = rev1.rev_id
220
            end_rev_id = rev2.rev_id
221
        else:
222
            start_rev_id = None
223
            end_rev_id = None
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
224
        self.note("Calculating the revisions to include ...")
0.64.341 by Jelmer Vernooij
Fix test, clarify help description for 'bzr fast-export'.
225
        view_revisions = [rev_id for rev_id, _, _, _ in
7143.15.2 by Jelmer Vernooij
Run autopep8.
226
                          self.branch.iter_merge_sorted_revisions(end_rev_id, start_rev_id)]
0.64.341 by Jelmer Vernooij
Fix test, clarify help description for 'bzr fast-export'.
227
        view_revisions.reverse()
0.64.173 by Ian Clatworthy
add -r option to fast-export
228
        # If a starting point was given, we need to later check that we don't
229
        # start emitting revisions from before that point. Collect the
230
        # revisions to exclude now ...
231
        if start_rev_id is not None:
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
232
            self.note("Calculating the revisions to exclude ...")
0.100.1 by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth
233
            self.excluded_revisions = set([rev_id for rev_id, _, _, _ in
7143.15.2 by Jelmer Vernooij
Run autopep8.
234
                                           self.branch.iter_merge_sorted_revisions(start_rev_id)])
0.135.2 by Andy Grimm
fix --baseline bugs, and add a couple of tests
235
            if self.baseline:
236
                # needed so the first relative commit knows its parent
237
                self.excluded_revisions.remove(start_rev_id)
238
                view_revisions.insert(0, start_rev_id)
0.64.230 by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export
239
        return list(view_revisions)
0.64.173 by Ian Clatworthy
add -r option to fast-export
240
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
241
    def run(self):
242
        # Export the data
6754.8.4 by Jelmer Vernooij
Use new context stuff.
243
        with self.branch.repository.lock_read():
0.100.1 by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth
244
            interesting = self.interesting_history()
0.102.15 by Ian Clatworthy
add revision count to 'Starting export ...' message
245
            self._commit_total = len(interesting)
246
            self.note("Starting export of %d revisions ..." %
7143.15.2 by Jelmer Vernooij
Run autopep8.
247
                      self._commit_total)
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
248
            if not self.plain_format:
249
                self.emit_features()
0.135.1 by Andy Grimm
Add --baseline option
250
            if self.baseline:
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
251
                self.emit_baseline(interesting.pop(0), self.ref)
0.100.1 by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth
252
            for revid in interesting:
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
253
                self.emit_commit(revid, self.ref)
0.138.1 by Oleksandr Usov
Add --no-tags flag
254
            if self.branch.supports_tags() and not self.no_tags:
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
255
                self.emit_tags()
0.68.1 by Pieter de Bie
Classify bzr-fast-export
256
0.79.1 by Ian Clatworthy
turn bzr-fast-export into a fast-export command
257
        # Save the marks if requested
0.79.2 by Ian Clatworthy
extend & use marks_file API
258
        self._save_marks()
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
259
        self.dump_stats()
260
261
    def note(self, msg, *args):
262
        """Output a note but timestamp it."""
263
        msg = "%s %s" % (self._time_of_day(), msg)
264
        trace.note(msg, *args)
265
266
    def warning(self, msg, *args):
267
        """Output a warning but timestamp it."""
268
        msg = "%s WARNING: %s" % (self._time_of_day(), msg)
269
        trace.warning(msg, *args)
270
271
    def _time_of_day(self):
272
        """Time of day as a string."""
273
        # Note: this is a separate method so tests can patch in a fixed value
274
        return time.strftime("%H:%M:%S")
275
276
    def report_progress(self, commit_count, details=''):
277
        if commit_count and commit_count % self.progress_every == 0:
0.64.230 by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export
278
            if self._commit_total:
279
                counts = "%d/%d" % (commit_count, self._commit_total)
280
            else:
281
                counts = "%d" % (commit_count,)
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
282
            minutes = (time.time() - self._start_time) / 60
283
            rate = commit_count * 1.0 / minutes
284
            if rate > 10:
285
                rate_str = "at %.0f/minute " % rate
286
            else:
287
                rate_str = "at %.1f/minute " % rate
288
            self.note("%s commits exported %s%s" % (counts, rate_str, details))
289
290
    def dump_stats(self):
291
        time_required = progress.str_tdelta(time.time() - self._start_time)
292
        rc = len(self.revid_to_mark)
293
        self.note("Exported %d %s in %s",
7143.15.2 by Jelmer Vernooij
Run autopep8.
294
                  rc, helpers.single_plural(rc, "revision", "revisions"),
295
                  time_required)
0.79.2 by Ian Clatworthy
extend & use marks_file API
296
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
297
    def print_cmd(self, cmd):
7045.4.18 by Jelmer Vernooij
Fix compatibility with older versions of fastimport.
298
        if PY3:
299
            self.outf.write(b"%s\n" % cmd)
300
        else:
301
            self.outf.write(b"%r\n" % cmd)
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
302
0.79.2 by Ian Clatworthy
extend & use marks_file API
303
    def _save_marks(self):
304
        if self.export_marks_file:
0.64.134 by Ian Clatworthy
fix marks importing in fast-export
305
            revision_ids = dict((m, r) for r, m in self.revid_to_mark.items())
0.125.1 by Ian Clatworthy
Use the new marks file format (introduced in git 1.6 apparently)
306
            marks_file.export_marks(self.export_marks_file, revision_ids)
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
307
0.68.10 by Pieter de Bie
bzr-fast-export: Don't rename empty directories
308
    def is_empty_dir(self, tree, path):
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
309
        # Continue if path is not a directory
310
        try:
311
            if tree.kind(path) != 'directory':
312
                return False
313
        except bazErrors.NoSuchFile:
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
314
            self.warning("Skipping empty_dir detection - no file_id for %s" %
7143.15.2 by Jelmer Vernooij
Run autopep8.
315
                         (path,))
0.68.10 by Pieter de Bie
bzr-fast-export: Don't rename empty directories
316
            return False
317
318
        # Use treewalk to find the contents of our directory
319
        contents = list(tree.walkdirs(prefix=path))[0]
320
        if len(contents[1]) == 0:
321
            return True
322
        else:
323
            return False
324
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
325
    def emit_features(self):
0.102.5 by Ian Clatworthy
Define feature names in one place
326
        for feature in sorted(commands.FEATURE_NAMES):
327
            self.print_cmd(commands.FeatureCommand(feature))
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
328
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
329
    def emit_baseline(self, revid, ref):
0.135.1 by Andy Grimm
Add --baseline option
330
        # Emit a full source tree of the first commit's parent
331
        revobj = self.branch.repository.get_revision(revid)
332
        mark = 1
0.135.2 by Andy Grimm
fix --baseline bugs, and add a couple of tests
333
        self.revid_to_mark[revid] = mark
7143.15.2 by Jelmer Vernooij
Run autopep8.
334
        file_cmds = self._get_filecommands(
335
            breezy.revision.NULL_REVISION, revid)
0.430.1 by Oleksandr Usov
Emit 'reset' command for parentless & baseline commits.
336
        self.print_cmd(commands.ResetCommand(ref, None))
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
337
        self.print_cmd(self._get_commit_command(ref, mark, revobj, file_cmds))
0.135.1 by Andy Grimm
Add --baseline option
338
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
339
    def emit_commit(self, revid, ref):
0.64.173 by Ian Clatworthy
add -r option to fast-export
340
        if revid in self.revid_to_mark or revid in self.excluded_revisions:
0.68.4 by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits
341
            return
342
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
343
        # Get the Revision object
0.68.4 by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits
344
        try:
345
            revobj = self.branch.repository.get_revision(revid)
346
        except bazErrors.NoSuchRevision:
347
            # This is a ghost revision. Mark it as not found and next!
348
            self.revid_to_mark[revid] = -1
349
            return
7143.15.2 by Jelmer Vernooij
Run autopep8.
350
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
351
        # Get the primary parent
0.100.1 by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth
352
        # TODO: Consider the excluded revisions when deciding the parents.
353
        # Currently, a commit with parents that are excluded ought to be
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
354
        # triggering the ref calculation below (and it is not).
0.100.1 by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth
355
        # IGC 20090824
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
356
        ncommits = len(self.revid_to_mark)
0.100.1 by Ian Clatworthy
Stop fast-export from exceeding the maximum recursion depth
357
        nparents = len(revobj.parent_ids)
0.68.4 by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits
358
        if nparents == 0:
6628.1.2 by Jelmer Vernooij
Fix imports, move exporter.py, drop explorer metadata.
359
            parent = breezy.revision.NULL_REVISION
0.68.4 by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits
360
        else:
361
            parent = revobj.parent_ids[0]
362
0.430.1 by Oleksandr Usov
Emit 'reset' command for parentless & baseline commits.
363
        # For parentless commits we need to issue reset command first, otherwise
364
        # git-fast-import will assume previous commit was this one's parent
365
        if nparents == 0:
366
            self.print_cmd(commands.ResetCommand(ref, None))
367
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
368
        # Print the commit
0.98.1 by Gonéri Le Bouder
add the missing ":" since revid_to_mark are "committish"
369
        mark = ncommits + 1
0.64.221 by Ian Clatworthy
backout git-bzr fix as it was breaking fast-export
370
        self.revid_to_mark[revid] = mark
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
371
        file_cmds = self._get_filecommands(parent, revid)
0.64.350 by Jelmer Vernooij
Rename git_branch to ref.
372
        self.print_cmd(self._get_commit_command(ref, mark, revobj, file_cmds))
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
373
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
374
        # Report progress and checkpoint if it's time for that
375
        self.report_progress(ncommits)
7143.15.2 by Jelmer Vernooij
Run autopep8.
376
        if (self.checkpoint is not None and self.checkpoint > 0 and ncommits and
377
                ncommits % self.checkpoint == 0):
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
378
            self.note("Exported %i commits - adding checkpoint to output"
7143.15.2 by Jelmer Vernooij
Run autopep8.
379
                      % ncommits)
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
380
            self._save_marks()
381
            self.print_cmd(commands.CheckpointCommand())
382
0.102.16 by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer
383
    def _get_name_email(self, user):
384
        if user.find('<') == -1:
0.64.177 by Ian Clatworthy
fix round-tripping of committer & author when name is an email
385
            # If the email isn't inside <>, we need to use it as the name
386
            # in order for things to round-trip correctly.
387
            # (note: parseaddr('a@b.com') => name:'', email: 'a@b.com')
0.102.16 by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer
388
            name = user
0.64.177 by Ian Clatworthy
fix round-tripping of committer & author when name is an email
389
            email = ''
390
        else:
0.102.16 by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer
391
            name, email = parseaddr(user)
0.64.299 by Jelmer Vernooij
utf8 decode/encode paths and committer/author email/name, as python-fastimport no longer does so.
392
        return name.encode("utf-8"), email.encode("utf-8")
0.102.16 by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer
393
394
    def _get_commit_command(self, git_ref, mark, revobj, file_cmds):
395
        # Get the committer and author info
396
        committer = revobj.committer
397
        name, email = self._get_name_email(committer)
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
398
        committer_info = (name, email, revobj.timestamp, revobj.timezone)
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
399
        if self._multi_author_api_available:
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
400
            more_authors = revobj.get_apparent_authors()
401
            author = more_authors.pop(0)
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
402
        else:
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
403
            more_authors = []
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
404
            author = revobj.get_apparent_author()
0.64.291 by Jelmer Vernooij
In plain mode, don't export multiple authors.
405
        if not self.plain_format and more_authors:
0.102.16 by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer
406
            name, email = self._get_name_email(author)
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
407
            author_info = (name, email, revobj.timestamp, revobj.timezone)
408
            more_author_info = []
409
            for a in more_authors:
0.102.16 by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer
410
                name, email = self._get_name_email(a)
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
411
                more_author_info.append(
412
                    (name, email, revobj.timestamp, revobj.timezone))
413
        elif author != committer:
0.102.16 by Ian Clatworthy
tweak author formatting to use same smart rule as used for committer
414
            name, email = self._get_name_email(author)
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
415
            author_info = (name, email, revobj.timestamp, revobj.timezone)
416
            more_author_info = None
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
417
        else:
418
            author_info = None
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
419
            more_author_info = None
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
420
421
        # Get the parents in terms of marks
422
        non_ghost_parents = []
0.68.4 by Pieter de Bie
bzr-fast-export.py: Add support for ghost commits
423
        for p in revobj.parent_ids:
0.64.173 by Ian Clatworthy
add -r option to fast-export
424
            if p in self.excluded_revisions:
425
                continue
0.64.230 by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export
426
            try:
427
                parent_mark = self.revid_to_mark[p]
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
428
                non_ghost_parents.append(b":%d" % parent_mark)
0.64.230 by Ian Clatworthy
Fix ghost handling and improve progress tracking in fast-export
429
            except KeyError:
430
                # ghost - ignore
431
                continue
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
432
        if non_ghost_parents:
433
            from_ = non_ghost_parents[0]
434
            merges = non_ghost_parents[1:]
435
        else:
436
            from_ = None
437
            merges = None
438
0.102.3 by Ian Clatworthy
First cut at exporting additional metadata via 'features'
439
        # Filter the revision properties. Some metadata (like the
440
        # author information) is already exposed in other ways so
441
        # don't repeat it here.
442
        if self.plain_format:
443
            properties = None
444
        else:
445
            properties = revobj.properties
446
            for prop in self.properties_to_exclude:
447
                try:
448
                    del properties[prop]
449
                except KeyError:
450
                    pass
451
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
452
        # Build and return the result
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
453
        return commands.CommitCommand(git_ref, mark, author_info,
7143.15.2 by Jelmer Vernooij
Run autopep8.
454
                                      committer_info, revobj.message.encode(
7222.1.1 by Jelmer Vernooij
Fix a spurious test.
455
                                          "utf-8"), from_, merges, file_cmds,
7143.15.2 by Jelmer Vernooij
Run autopep8.
456
                                      more_authors=more_author_info, properties=properties)
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
457
458
    def _get_revision_trees(self, parent, revision_id):
0.68.6 by Pieter de Bie
bzr-fast-export.py: Skip over broken commits.
459
        try:
460
            tree_old = self.branch.repository.revision_tree(parent)
461
        except bazErrors.UnexpectedInventoryFormat:
7143.15.2 by Jelmer Vernooij
Run autopep8.
462
            self.warning(
463
                "Parent is malformed - diffing against previous parent")
0.68.6 by Pieter de Bie
bzr-fast-export.py: Skip over broken commits.
464
            # We can't find the old parent. Let's diff against his parent
465
            pp = self.branch.repository.get_revision(parent)
466
            tree_old = self.branch.repository.revision_tree(pp.parent_ids[0])
467
        tree_new = None
468
        try:
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
469
            tree_new = self.branch.repository.revision_tree(revision_id)
0.68.6 by Pieter de Bie
bzr-fast-export.py: Skip over broken commits.
470
        except bazErrors.UnexpectedInventoryFormat:
471
            # We can't really do anything anymore
0.87.1 by David Reitter
fix bug #348038 (call to warning() with two arguments) and handle malformed revisions gracefully by not generating any output
472
            self.warning("Revision %s is malformed - skipping" % revision_id)
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
473
        return tree_old, tree_new
0.68.1 by Pieter de Bie
Classify bzr-fast-export
474
0.79.6 by Ian Clatworthy
refactor bzr_exporter to use Command objects
475
    def _get_filecommands(self, parent, revision_id):
476
        """Get the list of FileCommands for the changes between two revisions."""
477
        tree_old, tree_new = self._get_revision_trees(parent, revision_id)
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
478
        if not(tree_old and tree_new):
479
            # Something is wrong with this revision - ignore the filecommands
7222.1.2 by Jelmer Vernooij
Don't return non-None from generator.
480
            return
0.68.1 by Pieter de Bie
Classify bzr-fast-export
481
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
482
        changes = tree_new.changes_from(tree_old)
483
484
        # Make "modified" have 3-tuples, as added does
7143.15.2 by Jelmer Vernooij
Run autopep8.
485
        my_modified = [x[0:3] for x in changes.modified]
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
486
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
487
        # The potential interaction between renames and deletes is messy.
488
        # Handle it here ...
489
        file_cmds, rd_modifies, renamed = self._process_renames_and_deletes(
490
            changes.renamed, changes.removed, revision_id, tree_old)
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
491
7222.1.1 by Jelmer Vernooij
Fix a spurious test.
492
        for cmd in file_cmds:
493
            yield cmd
494
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
495
        # Map kind changes to a delete followed by an add
496
        for path, id_, kind1, kind2 in changes.kind_changed:
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
497
            path = self._adjust_path_for_renames(path, renamed, revision_id)
0.64.174 by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export
498
            # IGC: I don't understand why a delete is needed here.
499
            # In fact, it seems harmful? If you uncomment this line,
500
            # please file a bug explaining why you needed to.
7222.1.1 by Jelmer Vernooij
Fix a spurious test.
501
            # yield commands.FileDeleteCommand(path)
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
502
            my_modified.append((path, id_, kind2))
503
504
        # Record modifications
7211.5.1 by Jelmer Vernooij
Batch up requests for iter_files_bytes.
505
        files_to_get = []
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
506
        for path, id_, kind in changes.added + my_modified + rd_modifies:
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
507
            if kind == 'file':
7211.5.2 by Jelmer Vernooij
Actually remove unnecessary get_file_text call.
508
                files_to_get.append(
509
                    (path,
510
                     (path, helpers.kind_to_mode(
511
                         'file', tree_new.is_executable(path)))))
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
512
            elif kind == 'symlink':
7222.1.1 by Jelmer Vernooij
Fix a spurious test.
513
                yield commands.FileModifyCommand(
7143.15.15 by Jelmer Vernooij
Merge trunk.
514
                    path.encode("utf-8"),
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
515
                    helpers.kind_to_mode('symlink', False),
7222.1.1 by Jelmer Vernooij
Fix a spurious test.
516
                    None, tree_new.get_symlink_target(path))
0.102.14 by Ian Clatworthy
export and import empty directories
517
            elif kind == 'directory':
0.105.1 by John Whitley
Don't emit directory info when plain format is specified.
518
                if not self.plain_format:
7222.1.1 by Jelmer Vernooij
Fix a spurious test.
519
                    yield commands.FileModifyCommand(
520
                        path.encode("utf-8"),
521
                        helpers.kind_to_mode('directory', False), None,
522
                        None)
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
523
            else:
0.102.14 by Ian Clatworthy
export and import empty directories
524
                self.warning("cannot export '%s' of kind %s yet - ignoring" %
7143.15.2 by Jelmer Vernooij
Run autopep8.
525
                             (path, kind))
7211.5.1 by Jelmer Vernooij
Batch up requests for iter_files_bytes.
526
        for (path, mode), chunks in tree_new.iter_files_bytes(
527
                files_to_get):
7222.1.1 by Jelmer Vernooij
Fix a spurious test.
528
            yield commands.FileModifyCommand(
529
                path.encode("utf-8"), mode, None, b''.join(chunks))
0.64.166 by Ian Clatworthy
graceful handling of faulty revisions (David Reitter)
530
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
531
    def _process_renames_and_deletes(self, renames, deletes,
7143.15.2 by Jelmer Vernooij
Run autopep8.
532
                                     revision_id, tree_old):
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
533
        file_cmds = []
534
        modifies = []
535
        renamed = []
536
537
        # See https://bugs.edge.launchpad.net/bzr-fastimport/+bug/268933.
538
        # In a nutshell, there are several nasty cases:
539
        #
540
        # 1) bzr rm a; bzr mv b a; bzr commit
541
        # 2) bzr mv x/y z; bzr rm x; commmit
542
        #
543
        # The first must come out with the delete first like this:
544
        #
545
        # D a
546
        # R b a
547
        #
548
        # The second case must come out with the rename first like this:
549
        #
550
        # R x/y z
551
        # D x
552
        #
553
        # So outputting all deletes first or all renames first won't work.
554
        # Instead, we need to make multiple passes over the various lists to
555
        # get the ordering right.
556
0.64.237 by Ian Clatworthy
implicitly rename children on export when directory renamed
557
        must_be_renamed = {}
558
        old_to_new = {}
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
559
        deleted_paths = set([p for p, _, _ in deletes])
560
        for (oldpath, newpath, id_, kind,
561
                text_modified, meta_modified) in renames:
0.106.2 by Harry Hirsch
Don't emit directory info for renames operations when using plain format
562
            emit = kind != 'directory' or not self.plain_format
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
563
            if newpath in deleted_paths:
0.106.2 by Harry Hirsch
Don't emit directory info for renames operations when using plain format
564
                if emit:
7143.15.2 by Jelmer Vernooij
Run autopep8.
565
                    file_cmds.append(commands.FileDeleteCommand(
566
                        newpath.encode("utf-8")))
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
567
                deleted_paths.remove(newpath)
568
            if (self.is_empty_dir(tree_old, oldpath)):
569
                self.note("Skipping empty dir %s in rev %s" % (oldpath,
7143.15.2 by Jelmer Vernooij
Run autopep8.
570
                                                               revision_id))
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
571
                continue
7143.15.2 by Jelmer Vernooij
Run autopep8.
572
            # oldpath = self._adjust_path_for_renames(oldpath, renamed,
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
573
            #    revision_id)
574
            renamed.append([oldpath, newpath])
0.64.237 by Ian Clatworthy
implicitly rename children on export when directory renamed
575
            old_to_new[oldpath] = newpath
0.106.2 by Harry Hirsch
Don't emit directory info for renames operations when using plain format
576
            if emit:
0.64.299 by Jelmer Vernooij
utf8 decode/encode paths and committer/author email/name, as python-fastimport no longer does so.
577
                file_cmds.append(
578
                    commands.FileRenameCommand(oldpath.encode("utf-8"), newpath.encode("utf-8")))
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
579
            if text_modified or meta_modified:
580
                modifies.append((newpath, id_, kind))
581
0.64.237 by Ian Clatworthy
implicitly rename children on export when directory renamed
582
            # Renaming a directory implies all children must be renamed.
583
            # Note: changes_from() doesn't handle this
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
584
            if kind == 'directory' and tree_old.kind(oldpath, id_) == 'directory':
0.64.237 by Ian Clatworthy
implicitly rename children on export when directory renamed
585
                for p, e in tree_old.inventory.iter_entries_by_dir(from_dir=id_):
0.106.2 by Harry Hirsch
Don't emit directory info for renames operations when using plain format
586
                    if e.kind == 'directory' and self.plain_format:
587
                        continue
0.64.237 by Ian Clatworthy
implicitly rename children on export when directory renamed
588
                    old_child_path = osutils.pathjoin(oldpath, p)
589
                    new_child_path = osutils.pathjoin(newpath, p)
590
                    must_be_renamed[old_child_path] = new_child_path
591
592
        # Add children not already renamed
593
        if must_be_renamed:
594
            renamed_already = set(old_to_new.keys())
595
            still_to_be_renamed = set(must_be_renamed.keys()) - renamed_already
596
            for old_child_path in sorted(still_to_be_renamed):
597
                new_child_path = must_be_renamed[old_child_path]
598
                if self.verbose:
599
                    self.note("implicitly renaming %s => %s" % (old_child_path,
7143.15.2 by Jelmer Vernooij
Run autopep8.
600
                                                                new_child_path))
0.64.299 by Jelmer Vernooij
utf8 decode/encode paths and committer/author email/name, as python-fastimport no longer does so.
601
                file_cmds.append(commands.FileRenameCommand(old_child_path.encode("utf-8"),
7143.15.2 by Jelmer Vernooij
Run autopep8.
602
                                                            new_child_path.encode("utf-8")))
0.64.237 by Ian Clatworthy
implicitly rename children on export when directory renamed
603
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
604
        # Record remaining deletes
605
        for path, id_, kind in deletes:
606
            if path not in deleted_paths:
607
                continue
0.106.2 by Harry Hirsch
Don't emit directory info for renames operations when using plain format
608
            if kind == 'directory' and self.plain_format:
609
                continue
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
610
            #path = self._adjust_path_for_renames(path, renamed, revision_id)
0.64.299 by Jelmer Vernooij
utf8 decode/encode paths and committer/author email/name, as python-fastimport no longer does so.
611
            file_cmds.append(commands.FileDeleteCommand(path.encode("utf-8")))
0.64.178 by Ian Clatworthy
improve fast-export's handling of rename+delete combinations
612
        return file_cmds, modifies, renamed
613
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
614
    def _adjust_path_for_renames(self, path, renamed, revision_id):
0.64.174 by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export
615
        # If a previous rename is found, we should adjust the path
616
        for old, new in renamed:
617
            if path == old:
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
618
                self.note("Changing path %s given rename to %s in revision %s"
7143.15.2 by Jelmer Vernooij
Run autopep8.
619
                          % (path, new, revision_id))
0.64.174 by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export
620
                path = new
621
            elif path.startswith(old + '/'):
0.64.176 by Ian Clatworthy
faster export of revision range & improved diagnostics in fast-export
622
                self.note(
623
                    "Adjusting path %s given rename of %s to %s in revision %s"
624
                    % (path, old, new, revision_id))
0.64.174 by Ian Clatworthy
fix rename adjustment & kind change logic in fast-export
625
                path = path.replace(old + "/", new + "/")
626
        return path
627
0.68.1 by Pieter de Bie
Classify bzr-fast-export
628
    def emit_tags(self):
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
629
        for tag, revid in viewitems(self.branch.tags.get_tag_dict()):
0.68.1 by Pieter de Bie
Classify bzr-fast-export
630
            try:
631
                mark = self.revid_to_mark[revid]
632
            except KeyError:
0.79.4 by Ian Clatworthy
use note and warning APIs
633
                self.warning('not creating tag %r pointing to non-existent '
7143.15.2 by Jelmer Vernooij
Run autopep8.
634
                             'revision %s' % (tag, revid))
0.68.1 by Pieter de Bie
Classify bzr-fast-export
635
            else:
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
636
                git_ref = b'refs/tags/%s' % tag.encode("utf-8")
0.64.328 by Jelmer Vernooij
In "plain" mode, skip tags that contain characters not valid in Git.
637
                if self.plain_format and not check_ref_format(git_ref):
0.133.2 by Oleksandr Usov
Rewrite tag names when exporting plain stream
638
                    if self.rewrite_tags:
0.133.3 by Oleksandr Usov
Implement comments from patch review:
639
                        new_ref = sanitize_ref_name_for_git(git_ref)
0.133.2 by Oleksandr Usov
Rewrite tag names when exporting plain stream
640
                        self.warning('tag %r is exported as %r to be valid in git.',
641
                                     git_ref, new_ref)
642
                        git_ref = new_ref
0.133.3 by Oleksandr Usov
Implement comments from patch review:
643
                    else:
0.133.2 by Oleksandr Usov
Rewrite tag names when exporting plain stream
644
                        self.warning('not creating tag %r as its name would not be '
645
                                     'valid in git.', git_ref)
646
                        continue
7027.2.1 by Jelmer Vernooij
Port fastimport to python3.
647
                self.print_cmd(commands.ResetCommand(git_ref, b":%d" % mark))