/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
1
# Copyright (C) 2007 Canonical Ltd
2
# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@samba.org>
3
# Copyright (C) 2008 John Carr
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
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
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
"""Converters, etc for going between Bazaar and Git ids."""
20
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
21
import base64
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
22
import stat
23
0.200.292 by Jelmer Vernooij
Fix formatting.
24
from bzrlib import (
25
    errors,
26
    foreign,
0.200.356 by Jelmer Vernooij
Fix nasty bug in inventory_to_trees_and_blobs
27
    osutils,
0.200.490 by Jelmer Vernooij
Warn about unusual modes and escaped XML-invalid characters.
28
    trace,
0.200.292 by Jelmer Vernooij
Fix formatting.
29
    urlutils,
30
    )
0.200.550 by Jelmer Vernooij
Fix import.
31
try:
32
    from bzrlib import bencode
33
except ImportError:
34
    from bzrlib.util import bencode
0.200.292 by Jelmer Vernooij
Fix formatting.
35
from bzrlib.inventory import (
36
    ROOT_ID,
37
    )
0.200.152 by Jelmer Vernooij
Fix syntax errors.
38
from bzrlib.foreign import (
0.200.292 by Jelmer Vernooij
Fix formatting.
39
    ForeignVcs, 
40
    VcsMappingRegistry, 
41
    ForeignRevision,
42
    )
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
43
from bzrlib.plugins.git.hg import (
44
    format_hg_metadata,
45
    extract_hg_metadata,
46
    )
0.200.309 by Jelmer Vernooij
Add XML escaping to work around serialization bug in bzr.
47
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
48
DEFAULT_FILE_MODE = stat.S_IFREG | 0644
0.200.345 by Jelmer Vernooij
Keep track of file modes to use.
49
0.206.1 by Jelmer Vernooij
Use foreign utility functions.
50
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
51
def escape_file_id(file_id):
52
    return file_id.replace('_', '__').replace(' ', '_s')
53
54
55
def unescape_file_id(file_id):
0.200.390 by Jelmer Vernooij
Fix file id unescape function when there are other underscores in the file id.
56
    ret = []
57
    i = 0
58
    while i < len(file_id):
59
        if file_id[i] != '_':
60
            ret.append(file_id[i])
61
        else:
62
            if file_id[i+1] == '_':
63
                ret.append("_")
64
            elif file_id[i+1] == 's':
65
                ret.append(" ")
66
            else:
67
                raise AssertionError("unknown escape character %s" % file_id[i+1])
68
            i += 1
69
        i += 1
70
    return "".join(ret)
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
71
72
0.200.376 by Jelmer Vernooij
Make sure author and committer names pushed to git contain < and >, otherwise the git parser barfs.
73
def fix_person_identifier(text):
74
    if "<" in text and ">" in text:
75
        return text
76
    return "%s <%s>" % (text, text)
77
78
0.200.490 by Jelmer Vernooij
Warn about unusual modes and escaped XML-invalid characters.
79
def warn_escaped(commit, num_escaped):
80
    trace.warning("Escaped %d XML-invalid characters in %s. Will be unable "
81
                  "to regenerate the SHA map.", num_escaped, commit)
82
83
84
def warn_unusual_mode(commit, path, mode):
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
85
    trace.mutter("Unusual file mode %o for %s in %s. Storing as revision property. ",
86
                 mode, path, commit)
0.200.490 by Jelmer Vernooij
Warn about unusual modes and escaped XML-invalid characters.
87
88
0.200.545 by Jelmer Vernooij
Squash revision data only if necessary.
89
def squash_revision(target_repo, rev):
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
90
    """Remove characters that can't be stored from a revision, if necessary.
91
    
92
    :param target_repo: Repository in which the revision will be stored
93
    :param rev: Revision object, will be modified in-place
94
    """
0.200.545 by Jelmer Vernooij
Squash revision data only if necessary.
95
    if not getattr(target_repo._serializer, "squashes_xml_invalid_characters", True):
96
        return
97
    from bzrlib.xml_serializer import escape_invalid_chars
98
    rev.message, num_escaped = escape_invalid_chars(rev.message)
99
    if num_escaped:
100
        warn_escaped(rev.foreign_revid, num_escaped)
101
    if 'author' in rev.properties:
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
102
        rev.properties['author'], num_escaped = escape_invalid_chars(
103
            rev.properties['author'])
0.200.545 by Jelmer Vernooij
Squash revision data only if necessary.
104
        if num_escaped:
105
            warn_escaped(rev.foreign_revid, num_escaped)
106
    rev.committer, num_escaped = escape_invalid_chars(rev.committer)
107
    if num_escaped:
108
        warn_escaped(rev.foreign_revid, num_escaped)
109
110
0.206.1 by Jelmer Vernooij
Use foreign utility functions.
111
class BzrGitMapping(foreign.VcsMapping):
0.200.97 by Jelmer Vernooij
use mapping object.
112
    """Class that maps between Git and Bazaar semantics."""
113
    experimental = False
114
0.200.198 by Jelmer Vernooij
Cope with move of show_foreign_revid.
115
    def __init__(self):
116
        super(BzrGitMapping, self).__init__(foreign_git)
117
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
118
    def __eq__(self, other):
119
        return type(self) == type(other) and self.revid_prefix == other.revid_prefix
120
121
    @classmethod
122
    def revision_id_foreign_to_bzr(cls, git_rev_id):
0.200.97 by Jelmer Vernooij
use mapping object.
123
        """Convert a git revision id handle to a Bazaar revision id."""
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
124
        return "%s:%s" % (cls.revid_prefix, git_rev_id)
0.200.97 by Jelmer Vernooij
use mapping object.
125
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
126
    @classmethod
127
    def revision_id_bzr_to_foreign(cls, bzr_rev_id):
0.200.97 by Jelmer Vernooij
use mapping object.
128
        """Convert a Bazaar revision id to a git revision id handle."""
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
129
        if not bzr_rev_id.startswith("%s:" % cls.revid_prefix):
130
            raise errors.InvalidRevisionId(bzr_rev_id, cls)
131
        return bzr_rev_id[len(cls.revid_prefix)+1:], cls()
0.200.97 by Jelmer Vernooij
use mapping object.
132
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
133
    def generate_file_id(self, path):
0.200.297 by Jelmer Vernooij
Cope with non-ascii characters in filenames (needs a test..).
134
        # Git paths are just bytestrings
135
        # We must just hope they are valid UTF-8..
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
136
        if path == "":
137
            return ROOT_ID
0.200.297 by Jelmer Vernooij
Cope with non-ascii characters in filenames (needs a test..).
138
        return escape_file_id(path)
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
139
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
140
    def parse_file_id(self, file_id):
141
        if file_id == ROOT_ID:
142
            return ""
143
        return unescape_file_id(file_id)
144
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
145
    def import_unusual_file_modes(self, rev, unusual_file_modes):
146
        if unusual_file_modes:
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
147
            ret = [(name, unusual_file_modes[name]) for name in sorted(unusual_file_modes.keys())]
148
            rev.properties['file-modes'] = bencode.bencode(ret)
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
149
0.200.547 by Jelmer Vernooij
Support getting unusual file modes out of revision properties.
150
    def export_unusual_file_modes(self, rev):
151
        try:
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
152
            return dict([(self.generate_file_id(path), mode) for (path, mode) in bencode.bdecode(rev.properties['file-modes'])])
0.200.547 by Jelmer Vernooij
Support getting unusual file modes out of revision properties.
153
        except KeyError:
154
            return {}
155
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
156
    def _generate_hg_message_tail(self, rev):
157
        extra = {}
158
        renames = []
0.200.639 by Jelmer Vernooij
Support renames in hg-git messages as well.
159
        branch = 'default'
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
160
        for name in rev.properties:
161
            if name == 'hg:extra:branch':
162
                branch = rev.properties['hg:extra:branch']
163
            elif name.startswith('hg:extra'):
164
                extra[name[len('hg:extra:'):]] = base64.b64decode(rev.properties[name])
0.200.639 by Jelmer Vernooij
Support renames in hg-git messages as well.
165
            elif name == 'hg:renames':
166
                renames = bencode.bdecode(base64.b64decode(rev.properties['hg:renames']))
167
            # TODO: Export other properties as 'bzr:' extras?
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
168
        return format_hg_metadata(renames, branch, extra)
169
170
    def _extract_hg_metadata(self, rev, message):
171
        (message, renames, branch, extra) = extract_hg_metadata(message)
172
        if branch is not None:
173
            rev.properties['hg:extra:branch'] = branch
174
        for name, value in extra.iteritems():
175
            rev.properties['hg:extra:' + name] = base64.b64encode(value)
0.200.639 by Jelmer Vernooij
Support renames in hg-git messages as well.
176
        if renames:
177
            rev.properties['hg:renames'] = base64.b64encode(bencode.bencode([(new, old) for (old, new) in renames.iteritems()]))
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
178
        return message
179
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
180
    def _decode_commit_message(self, rev, message):
181
        return message.decode("utf-8", "replace")
182
183
    def _encode_commit_message(self, rev, message):
184
        return message.encode("utf-8")
185
186
    def export_commit(self, rev, tree_sha, parent_lookup):
187
        """Turn a Bazaar revision in to a Git commit
188
189
        :param tree_sha: Tree sha for the commit
190
        :param parent_lookup: Function for looking up the GIT sha equiv of a bzr revision
191
        :return dulwich.objects.Commit represent the revision:
192
        """
193
        from dulwich.objects import Commit
194
        commit = Commit()
195
        commit.tree = tree_sha
196
        for p in rev.parent_ids:
197
            git_p = parent_lookup(p)
198
            if git_p is not None:
199
                assert len(git_p) == 40, "unexpected length for %r" % git_p
200
                commit.parents.append(git_p)
201
        commit.committer = fix_person_identifier(rev.committer.encode("utf-8"))
202
        commit.author = fix_person_identifier(rev.get_apparent_authors()[0].encode("utf-8"))
203
        commit.commit_time = long(rev.timestamp)
204
        if 'author-timestamp' in rev.properties:
205
            commit.author_time = long(rev.properties['author-timestamp'])
206
        else:
207
            commit.author_time = commit.commit_time
208
        commit.commit_timezone = rev.timezone
209
        if 'author-timezone' in rev.properties:
210
            commit.author_timezone = int(rev.properties['author-timezone'])
211
        else:
212
            commit.author_timezone = commit.commit_timezone 
213
        commit.message = self._encode_commit_message(rev, rev.message)
214
        return commit
215
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
216
    def import_commit(self, commit):
217
        """Convert a git commit to a bzr revision.
218
219
        :return: a `bzrlib.revision.Revision` object.
220
        """
221
        if commit is None:
222
            raise AssertionError("Commit object can't be None")
223
        rev = ForeignRevision(commit.id, self, self.revision_id_foreign_to_bzr(commit.id))
224
        rev.parent_ids = tuple([self.revision_id_foreign_to_bzr(p) for p in commit.parents])
0.200.545 by Jelmer Vernooij
Squash revision data only if necessary.
225
        rev.committer = str(commit.committer).decode("utf-8", "replace")
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
226
        if commit.committer != commit.author:
0.200.545 by Jelmer Vernooij
Squash revision data only if necessary.
227
            rev.properties['author'] = str(commit.author).decode("utf-8", "replace")
0.200.350 by Jelmer Vernooij
Support author_time
228
229
        if commit.commit_time != commit.author_time:
230
            rev.properties['author-timestamp'] = str(commit.author_time)
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
231
        if commit.commit_timezone != commit.author_timezone:
0.200.440 by Jelmer Vernooij
Remove silly mapping of timezones; dulwich uses offsets now as well.
232
            rev.properties['author-timezone'] = "%d" % (commit.author_timezone, )
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
233
        rev.timestamp = commit.commit_time
0.200.440 by Jelmer Vernooij
Remove silly mapping of timezones; dulwich uses offsets now as well.
234
        rev.timezone = commit.commit_timezone
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
235
        rev.message = self._decode_commit_message(rev, commit.message)
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
236
        return rev
237
0.200.97 by Jelmer Vernooij
use mapping object.
238
0.200.190 by Jelmer Vernooij
Bless current mapping as v1.
239
class BzrGitMappingv1(BzrGitMapping):
240
    revid_prefix = 'git-v1'
241
    experimental = False
242
0.200.393 by Jelmer Vernooij
Provide __str__ implementation for mapping, fix docstring for ForeignGit.
243
    def __str__(self):
244
        return self.revid_prefix
245
0.200.190 by Jelmer Vernooij
Bless current mapping as v1.
246
247
class BzrGitMappingExperimental(BzrGitMappingv1):
0.200.104 by Jelmer Vernooij
Use bzr-foreign function names for converting between git and bzr revids.
248
    revid_prefix = 'git-experimental'
249
    experimental = True
0.200.97 by Jelmer Vernooij
use mapping object.
250
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
251
    def _decode_commit_message(self, rev, message):
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
252
        message = self._extract_hg_metadata(rev, message)
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
253
        return message.decode("utf-8", "replace")
254
255
    def _encode_commit_message(self, rev, message):
256
        ret = message.encode("utf-8")
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
257
        ret += self._generate_hg_message_tail(rev)
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
258
        return ret
259
0.200.97 by Jelmer Vernooij
use mapping object.
260
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
261
class GitMappingRegistry(VcsMappingRegistry):
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
262
    """Registry with available git mappings."""
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
263
264
    def revision_id_bzr_to_foreign(self, bzr_revid):
265
        if not bzr_revid.startswith("git-"):
266
            raise errors.InvalidRevisionId(bzr_revid, None)
267
        (mapping_version, git_sha) = bzr_revid.split(":", 1)
268
        mapping = self.get(mapping_version)
269
        return mapping.revision_id_bzr_to_foreign(bzr_revid)
270
271
    parse_revision_id = revision_id_bzr_to_foreign
272
273
274
mapping_registry = GitMappingRegistry()
275
mapping_registry.register_lazy('git-v1', "bzrlib.plugins.git.mapping",
276
                                   "BzrGitMappingv1")
277
mapping_registry.register_lazy('git-experimental', "bzrlib.plugins.git.mapping",
278
                                   "BzrGitMappingExperimental")
0.200.637 by Jelmer Vernooij
Allow single place for configuration of default mapping.
279
mapping_registry.set_default('git-v1')
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
280
281
282
class ForeignGit(ForeignVcs):
0.200.393 by Jelmer Vernooij
Provide __str__ implementation for mapping, fix docstring for ForeignGit.
283
    """The Git Stupid Content Tracker"""
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
284
285
    def __init__(self):
286
        super(ForeignGit, self).__init__(mapping_registry)
287
0.200.198 by Jelmer Vernooij
Cope with move of show_foreign_revid.
288
    @classmethod
289
    def show_foreign_revid(cls, foreign_revid):
290
        return { "git commit": foreign_revid }
291
292
293
foreign_git = ForeignGit()
0.200.637 by Jelmer Vernooij
Allow single place for configuration of default mapping.
294
default_mapping = mapping_registry.get_default()()
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
295
296
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
297
def text_to_blob(texts, entry):
0.231.2 by Jelmer Vernooij
Add -Dverify flag (not fully implemented yet).
298
    from dulwich.objects import Blob
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
299
    text = texts.get_record_stream([(entry.file_id, entry.revision)], 'unordered', True).next().get_bytes_as('fulltext')
0.231.2 by Jelmer Vernooij
Add -Dverify flag (not fully implemented yet).
300
    blob = Blob()
301
    blob._text = text
302
    return blob
303
304
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
305
def symlink_to_blob(entry):
306
    from dulwich.objects import Blob
307
    blob = Blob()
308
    blob._text = entry.symlink_target
309
    return blob
310
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
311
0.200.521 by Jelmer Vernooij
Abstract out kind mapping a bit, initial work on support tree-references.
312
def mode_is_executable(mode):
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
313
    """Check if mode should be considered executable."""
0.200.521 by Jelmer Vernooij
Abstract out kind mapping a bit, initial work on support tree-references.
314
    return bool(mode & 0111)
315
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
316
0.200.521 by Jelmer Vernooij
Abstract out kind mapping a bit, initial work on support tree-references.
317
def mode_kind(mode):
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
318
    """Determine the Bazaar inventory kind based on Unix file mode."""
0.200.521 by Jelmer Vernooij
Abstract out kind mapping a bit, initial work on support tree-references.
319
    entry_kind = (mode & 0700000) / 0100000
320
    if entry_kind == 0:
321
        return 'directory'
322
    elif entry_kind == 1:
323
        file_kind = (mode & 070000) / 010000
324
        if file_kind == 0:
325
            return 'file'
326
        elif file_kind == 2:
327
            return 'symlink'
328
        elif file_kind == 6:
329
            return 'tree-reference'
330
        else:
331
            raise AssertionError(
332
                "Unknown file kind %d, perms=%o." % (file_kind, mode,))
333
    else:
334
        raise AssertionError(
335
            "Unknown kind, perms=%r." % (mode,))
336
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
337
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
338
def object_mode(kind, executable):
339
    if kind == 'directory':
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
340
        return stat.S_IFDIR
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
341
    elif kind == 'symlink':
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
342
        return stat.S_IFLNK
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
343
    elif kind == 'file':
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
344
        mode = stat.S_IFREG | 0644
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
345
        if executable:
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
346
            mode |= 0111
347
        return mode
348
    else:
349
        raise AssertionError
350
351
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
352
def entry_mode(entry):
353
    """Determine the git file mode for an inventory entry."""
354
    return object_mode(entry.kind, entry.executable)
355
356
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
357
def directory_to_tree(entry, lookup_ie_sha1, unusual_modes):
0.200.589 by Jelmer Vernooij
Fix handling of empty trees.
358
    from dulwich.objects import Tree
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
359
    tree = Tree()
360
    for name in sorted(entry.children.keys()):
361
        ie = entry.children[name]
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
362
        try:
363
            mode = unusual_modes[ie.file_id]
364
        except KeyError:
365
            mode = entry_mode(ie)
0.200.588 by Jelmer Vernooij
Cope with empty directories that are not allowed in git.
366
        hexsha = lookup_ie_sha1(ie)
0.200.589 by Jelmer Vernooij
Fix handling of empty trees.
367
        if hexsha is not None:
368
            tree.add(mode, name.encode("utf-8"), hexsha)
369
    if entry.parent_id is not None and len(tree) == 0:
370
        # Only the root can be an empty tree
371
        return None
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
372
    tree.serialize()
373
    return tree
374
375
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
376
def extract_unusual_modes(rev):
377
    try:
378
        foreign_revid, mapping = mapping_registry.parse_revision_id(rev.revision_id)
379
    except errors.InvalidRevisionId:
380
        return {}
381
    else:
382
        return mapping.export_unusual_file_modes(rev)
383
384
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
385
def inventory_to_tree_and_blobs(inventory, texts, mapping, unusual_modes, cur=None):
0.200.355 by Jelmer Vernooij
Allow paranoia checking with -Dverify.
386
    """Convert a Bazaar tree to a Git tree.
387
388
    :return: Yields tuples with object sha1, object and path
389
    """
0.231.2 by Jelmer Vernooij
Add -Dverify flag (not fully implemented yet).
390
    from dulwich.objects import Tree
0.200.213 by Jelmer Vernooij
Move functions to mapping.
391
    import stat
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
392
    stack = []
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
393
    if cur is None:
394
        cur = ""
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
395
    tree = Tree()
396
0.200.220 by Jelmer Vernooij
yield the right path for the tree root.
397
    # stack contains the set of trees that we haven't 
398
    # finished constructing
0.200.349 by Jelmer Vernooij
Specify inventory and texts to inventory_to_tree_and_blobs rather than full repository.
399
    for path, entry in inventory.iter_entries():
0.200.356 by Jelmer Vernooij
Fix nasty bug in inventory_to_trees_and_blobs
400
        while stack and not path.startswith(osutils.pathjoin(cur, "")):
401
            # We've hit a file that's not a child of the previous path
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
402
            tree.serialize()
0.200.318 by Jelmer Vernooij
Use .id rather than .sha().hexdigest().
403
            sha = tree.id
0.200.361 by Jelmer Vernooij
Fix existing object lookup issues when pulling from remote branches.
404
            yield sha, tree, cur.encode("utf-8")
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
405
            mode = unusual_modes.get(cur.encode("utf-8"), stat.S_IFDIR)
406
            t = (mode, urlutils.basename(cur).encode('UTF-8'), sha)
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
407
            cur, tree = stack.pop()
408
            tree.add(*t)
409
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
410
        if entry.kind == "directory":
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
411
            stack.append((cur, tree))
412
            cur = path
413
            tree = Tree()
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
414
        else:
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
415
            if entry.kind == "file":
416
                blob = text_to_blob(texts, entry)
417
            elif entry.kind == "symlink":
418
                blob = symlink_to_blob(entry)
419
            else:
420
                raise AssertionError("Unknown kind %s" % entry.kind)
421
            sha = blob.id
0.200.361 by Jelmer Vernooij
Fix existing object lookup issues when pulling from remote branches.
422
            yield sha, blob, path.encode("utf-8")
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
423
            name = urlutils.basename(path).encode("utf-8")
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
424
            mode = unusual_modes.get(path.encode("utf-8"), entry_mode(entry))
425
            tree.add(mode, name, sha)
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
426
427
    while len(stack) > 1:
428
        tree.serialize()
0.200.318 by Jelmer Vernooij
Use .id rather than .sha().hexdigest().
429
        sha = tree.id
0.200.361 by Jelmer Vernooij
Fix existing object lookup issues when pulling from remote branches.
430
        yield sha, tree, cur.encode("utf-8")
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
431
        mode = unusual_modes.get(cur.encode('utf-8'), stat.S_IFDIR)
432
        t = (mode, urlutils.basename(cur).encode('UTF-8'), sha)
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
433
        cur, tree = stack.pop()
434
        tree.add(*t)
435
436
    tree.serialize()
0.200.361 by Jelmer Vernooij
Fix existing object lookup issues when pulling from remote branches.
437
    yield tree.id, tree, cur.encode("utf-8")
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
438