/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
0.252.32 by Jelmer Vernooij
update copyright
2
# Copyright (C) 2008-2010 Jelmer Vernooij <jelmer@samba.org>
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
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.200.1594 by Jelmer Vernooij
Use absolute_import everywhere.
21
from __future__ import absolute_import
22
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
23
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.
24
import stat
25
0.200.292 by Jelmer Vernooij
Fix formatting.
26
from bzrlib import (
0.200.926 by Jelmer Vernooij
Fix formatting, drop support for Bazaar < 2.0.
27
    bencode,
0.200.292 by Jelmer Vernooij
Fix formatting.
28
    errors,
29
    foreign,
0.200.490 by Jelmer Vernooij
Warn about unusual modes and escaped XML-invalid characters.
30
    trace,
0.200.292 by Jelmer Vernooij
Fix formatting.
31
    )
32
from bzrlib.inventory import (
33
    ROOT_ID,
34
    )
0.200.152 by Jelmer Vernooij
Fix syntax errors.
35
from bzrlib.foreign import (
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
36
    ForeignVcs,
37
    VcsMappingRegistry,
0.200.292 by Jelmer Vernooij
Fix formatting.
38
    ForeignRevision,
39
    )
0.200.701 by Jelmer Vernooij
Fix check in git repos.
40
from bzrlib.revision import (
41
    NULL_REVISION,
42
    )
0.200.1598 by Jelmer Vernooij
Print proper error when unknown fields are encountered.
43
from bzrlib.plugins.git.errors import (
44
    NoPushSupport,
45
    UnknownCommitExtra,
46
    )
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
47
from bzrlib.plugins.git.hg import (
48
    format_hg_metadata,
49
    extract_hg_metadata,
50
    )
0.252.2 by Jelmer Vernooij
Add functions for adding metadata to revision messages.
51
from bzrlib.plugins.git.roundtrip import (
52
    extract_bzr_metadata,
0.252.4 by Jelmer Vernooij
More work on roundtripping.
53
    inject_bzr_metadata,
0.200.1324 by Jelmer Vernooij
More work on roundtripping support.
54
    CommitSupplement,
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
55
    deserialize_fileid_map,
56
    serialize_fileid_map,
0.252.2 by Jelmer Vernooij
Add functions for adding metadata to revision messages.
57
    )
0.200.309 by Jelmer Vernooij
Add XML escaping to work around serialization bug in bzr.
58
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.
59
DEFAULT_FILE_MODE = stat.S_IFREG | 0644
0.200.345 by Jelmer Vernooij
Keep track of file modes to use.
60
0.206.1 by Jelmer Vernooij
Use foreign utility functions.
61
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
62
def escape_file_id(file_id):
0.200.1419 by Jelmer Vernooij
Escape/unescape ^L characters.
63
    return file_id.replace('_', '__').replace(' ', '_s').replace('\x0c', '_c')
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
64
65
66
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.
67
    ret = []
68
    i = 0
69
    while i < len(file_id):
70
        if file_id[i] != '_':
71
            ret.append(file_id[i])
72
        else:
73
            if file_id[i+1] == '_':
74
                ret.append("_")
75
            elif file_id[i+1] == 's':
76
                ret.append(" ")
0.200.1419 by Jelmer Vernooij
Escape/unescape ^L characters.
77
            elif file_id[i+1] == 'c':
78
                ret.append("\x0c")
0.200.390 by Jelmer Vernooij
Fix file id unescape function when there are other underscores in the file id.
79
            else:
0.200.826 by Jelmer Vernooij
Fix some long lines.
80
                raise AssertionError("unknown escape character %s" %
81
                    file_id[i+1])
0.200.390 by Jelmer Vernooij
Fix file id unescape function when there are other underscores in the file id.
82
            i += 1
83
        i += 1
84
    return "".join(ret)
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
85
86
0.200.376 by Jelmer Vernooij
Make sure author and committer names pushed to git contain < and >, otherwise the git parser barfs.
87
def fix_person_identifier(text):
88
    if "<" in text and ">" in text:
0.200.1625 by Jelmer Vernooij
Cope with missing space before <
89
        if not " <" in text and text.count("<") == 1:
90
            text = text.replace("<", " <")
0.200.376 by Jelmer Vernooij
Make sure author and committer names pushed to git contain < and >, otherwise the git parser barfs.
91
        return text
92
    return "%s <%s>" % (text, text)
93
94
0.200.490 by Jelmer Vernooij
Warn about unusual modes and escaped XML-invalid characters.
95
def warn_escaped(commit, num_escaped):
96
    trace.warning("Escaped %d XML-invalid characters in %s. Will be unable "
97
                  "to regenerate the SHA map.", num_escaped, commit)
98
99
100
def warn_unusual_mode(commit, path, mode):
0.200.826 by Jelmer Vernooij
Fix some long lines.
101
    trace.mutter("Unusual file mode %o for %s in %s. Storing as revision "
102
                 "property. ", mode, path, commit)
0.200.490 by Jelmer Vernooij
Warn about unusual modes and escaped XML-invalid characters.
103
104
0.206.1 by Jelmer Vernooij
Use foreign utility functions.
105
class BzrGitMapping(foreign.VcsMapping):
0.200.97 by Jelmer Vernooij
use mapping object.
106
    """Class that maps between Git and Bazaar semantics."""
107
    experimental = False
108
0.200.915 by Jelmer Vernooij
Cope with the fact that the old format didn't export file ids.
109
    BZR_FILE_IDS_FILE = None
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
110
0.200.915 by Jelmer Vernooij
Cope with the fact that the old format didn't export file ids.
111
    BZR_DUMMY_FILE = None
0.252.26 by Jelmer Vernooij
Add is_control_file method to BzrGitMapping.
112
0.200.1328 by Jelmer Vernooij
More test fixes.
113
    def is_special_file(self, filename):
114
        return (filename in (self.BZR_FILE_IDS_FILE, self.BZR_DUMMY_FILE))
115
0.200.198 by Jelmer Vernooij
Cope with move of show_foreign_revid.
116
    def __init__(self):
0.200.1263 by Jelmer Vernooij
Fix foreign_vcs_git.
117
        super(BzrGitMapping, self).__init__(foreign_vcs_git)
0.200.198 by Jelmer Vernooij
Cope with move of show_foreign_revid.
118
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
119
    def __eq__(self, other):
0.200.1020 by Jelmer Vernooij
Store testament-sha1 in metadata.
120
        return (type(self) == type(other) and
0.200.726 by Jelmer Vernooij
Factor out conversion of branch names to refs.
121
                self.revid_prefix == other.revid_prefix)
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
122
123
    @classmethod
124
    def revision_id_foreign_to_bzr(cls, git_rev_id):
0.200.97 by Jelmer Vernooij
use mapping object.
125
        """Convert a git revision id handle to a Bazaar revision id."""
0.200.891 by Jelmer Vernooij
Use ZERO_SHA constant where possible.
126
        from dulwich.protocol import ZERO_SHA
127
        if git_rev_id == ZERO_SHA:
0.200.769 by Jelmer Vernooij
Cope with open_branch() actually checking whether there is a branch present.
128
            return NULL_REVISION
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
129
        return "%s:%s" % (cls.revid_prefix, git_rev_id)
0.200.97 by Jelmer Vernooij
use mapping object.
130
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
131
    @classmethod
132
    def revision_id_bzr_to_foreign(cls, bzr_rev_id):
0.200.97 by Jelmer Vernooij
use mapping object.
133
        """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.
134
        if not bzr_rev_id.startswith("%s:" % cls.revid_prefix):
135
            raise errors.InvalidRevisionId(bzr_rev_id, cls)
136
        return bzr_rev_id[len(cls.revid_prefix)+1:], cls()
0.200.97 by Jelmer Vernooij
use mapping object.
137
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
138
    def generate_file_id(self, path):
0.200.297 by Jelmer Vernooij
Cope with non-ascii characters in filenames (needs a test..).
139
        # Git paths are just bytestrings
140
        # We must just hope they are valid UTF-8..
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
141
        if path == "":
142
            return ROOT_ID
0.200.973 by Jelmer Vernooij
Add tests for generate_file_id.
143
        if type(path) is unicode:
144
            path = path.encode("utf-8")
0.200.297 by Jelmer Vernooij
Cope with non-ascii characters in filenames (needs a test..).
145
        return escape_file_id(path)
0.200.150 by Jelmer Vernooij
Abstract away file id generation.
146
0.252.26 by Jelmer Vernooij
Add is_control_file method to BzrGitMapping.
147
    def is_control_file(self, path):
148
        return path in (self.BZR_FILE_IDS_FILE, self.BZR_DUMMY_FILE)
149
0.230.2 by Jelmer Vernooij
Fix versionedfiles.
150
    def parse_file_id(self, file_id):
151
        if file_id == ROOT_ID:
152
            return ""
153
        return unescape_file_id(file_id)
154
0.252.31 by Jelmer Vernooij
Properly escape revids when using them in ref names.
155
    def revid_as_refname(self, revid):
156
        import urllib
157
        return "refs/bzr/%s" % urllib.quote(revid)
158
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
159
    def import_unusual_file_modes(self, rev, unusual_file_modes):
160
        if unusual_file_modes:
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
161
            ret = [(path, unusual_file_modes[path])
162
                   for path in sorted(unusual_file_modes.keys())]
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
163
            rev.properties['file-modes'] = bencode.bencode(ret)
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
164
0.200.547 by Jelmer Vernooij
Support getting unusual file modes out of revision properties.
165
    def export_unusual_file_modes(self, rev):
166
        try:
0.200.894 by Jelmer Vernooij
Simplify formatting a bit.
167
            file_modes = rev.properties['file-modes']
0.200.547 by Jelmer Vernooij
Support getting unusual file modes out of revision properties.
168
        except KeyError:
169
            return {}
0.200.894 by Jelmer Vernooij
Simplify formatting a bit.
170
        else:
171
            return dict([(self.generate_file_id(path), mode) for (path, mode) in bencode.bdecode(file_modes.encode("utf-8"))])
0.200.547 by Jelmer Vernooij
Support getting unusual file modes out of revision properties.
172
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
173
    def _generate_git_svn_metadata(self, rev, encoding):
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
174
        try:
0.200.894 by Jelmer Vernooij
Simplify formatting a bit.
175
            git_svn_id = rev.properties["git-svn-id"]
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
176
        except KeyError:
177
            return ""
0.200.894 by Jelmer Vernooij
Simplify formatting a bit.
178
        else:
179
            return "\ngit-svn-id: %s\n" % git_svn_id.encode(encoding)
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
180
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
181
    def _generate_hg_message_tail(self, rev):
182
        extra = {}
183
        renames = []
0.200.639 by Jelmer Vernooij
Support renames in hg-git messages as well.
184
        branch = 'default'
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
185
        for name in rev.properties:
186
            if name == 'hg:extra:branch':
187
                branch = rev.properties['hg:extra:branch']
188
            elif name.startswith('hg:extra'):
0.200.826 by Jelmer Vernooij
Fix some long lines.
189
                extra[name[len('hg:extra:'):]] = base64.b64decode(
190
                    rev.properties[name])
0.200.639 by Jelmer Vernooij
Support renames in hg-git messages as well.
191
            elif name == 'hg:renames':
0.200.826 by Jelmer Vernooij
Fix some long lines.
192
                renames = bencode.bdecode(base64.b64decode(
193
                    rev.properties['hg:renames']))
0.200.639 by Jelmer Vernooij
Support renames in hg-git messages as well.
194
            # TODO: Export other properties as 'bzr:' extras?
0.200.660 by Jelmer Vernooij
Fix encoding issues.
195
        ret = format_hg_metadata(renames, branch, extra)
196
        assert isinstance(ret, str)
197
        return ret
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
198
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
199
    def _extract_git_svn_metadata(self, rev, message):
200
        lines = message.split("\n")
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
201
        if not (lines[-1] == "" and len(lines) >= 2 and lines[-2].startswith("git-svn-id:")):
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
202
            return message
0.200.652 by Jelmer Vernooij
Split out git-svn-id parser as separate function, implement ForeignGit.serialize_foreign_revid.
203
        git_svn_id = lines[-2].split(": ", 1)[1]
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
204
        rev.properties['git-svn-id'] = git_svn_id
0.200.652 by Jelmer Vernooij
Split out git-svn-id parser as separate function, implement ForeignGit.serialize_foreign_revid.
205
        (url, rev, uuid) = parse_git_svn_id(git_svn_id)
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
206
        # FIXME: Convert this to converted-from property somehow..
0.200.660 by Jelmer Vernooij
Fix encoding issues.
207
        ret = "\n".join(lines[:-2])
208
        assert isinstance(ret, str)
209
        return ret
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
210
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
211
    def _extract_hg_metadata(self, rev, message):
212
        (message, renames, branch, extra) = extract_hg_metadata(message)
213
        if branch is not None:
214
            rev.properties['hg:extra:branch'] = branch
215
        for name, value in extra.iteritems():
216
            rev.properties['hg:extra:' + name] = base64.b64encode(value)
0.200.639 by Jelmer Vernooij
Support renames in hg-git messages as well.
217
        if renames:
0.200.826 by Jelmer Vernooij
Fix some long lines.
218
            rev.properties['hg:renames'] = base64.b64encode(bencode.bencode(
219
                [(new, old) for (old, new) in renames.iteritems()]))
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
220
        return message
221
0.252.2 by Jelmer Vernooij
Add functions for adding metadata to revision messages.
222
    def _extract_bzr_metadata(self, rev, message):
223
        (message, metadata) = extract_bzr_metadata(message)
0.252.4 by Jelmer Vernooij
More work on roundtripping.
224
        return message, metadata
0.252.2 by Jelmer Vernooij
Add functions for adding metadata to revision messages.
225
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
226
    def _decode_commit_message(self, rev, message, encoding):
0.200.1324 by Jelmer Vernooij
More work on roundtripping support.
227
        return message.decode(encoding), CommitSupplement()
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
228
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
229
    def _encode_commit_message(self, rev, message, encoding):
230
        return message.encode(encoding)
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
231
0.252.22 by Jelmer Vernooij
Fix file id map (de)serialization.
232
    def export_fileid_map(self, fileid_map):
233
        """Export a file id map to a fileid map.
234
235
        :param fileid_map: File id map, mapping paths to file ids
236
        :return: A Git blob object
237
        """
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
238
        from dulwich.objects import Blob
239
        b = Blob()
240
        b.set_raw_chunks(serialize_fileid_map(fileid_map))
241
        return b
0.252.22 by Jelmer Vernooij
Fix file id map (de)serialization.
242
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
243
    def export_commit(self, rev, tree_sha, parent_lookup, lossy,
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
244
                      verifiers):
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
245
        """Turn a Bazaar revision in to a Git commit
246
247
        :param tree_sha: Tree sha for the commit
0.200.826 by Jelmer Vernooij
Fix some long lines.
248
        :param parent_lookup: Function for looking up the GIT sha equiv of a
249
            bzr revision
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
250
        :param lossy: Whether to store roundtripping information.
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
251
        :param verifiers: Verifiers info
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
252
        :return dulwich.objects.Commit represent the revision:
253
        """
254
        from dulwich.objects import Commit
255
        commit = Commit()
256
        commit.tree = tree_sha
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
257
        if not lossy:
0.200.1324 by Jelmer Vernooij
More work on roundtripping support.
258
            metadata = CommitSupplement()
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
259
            metadata.verifiers = verifiers
0.252.8 by Jelmer Vernooij
Support ghost revisions while roundtripping.
260
        else:
261
            metadata = None
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
262
        parents = []
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
263
        for p in rev.parent_ids:
0.200.705 by Jelmer Vernooij
Cope with imports.
264
            try:
265
                git_p = parent_lookup(p)
266
            except KeyError:
267
                git_p = None
0.252.8 by Jelmer Vernooij
Support ghost revisions while roundtripping.
268
                if metadata is not None:
269
                    metadata.explicit_parent_ids = rev.parent_ids
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
270
            if git_p is not None:
271
                assert len(git_p) == 40, "unexpected length for %r" % git_p
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
272
                parents.append(git_p)
273
        commit.parents = parents
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
274
        try:
275
            encoding = rev.properties['git-explicit-encoding']
276
        except KeyError:
277
            encoding = rev.properties.get('git-implicit-encoding', 'utf-8')
278
        commit.encoding = rev.properties.get('git-explicit-encoding')
279
        commit.committer = fix_person_identifier(rev.committer.encode(
280
            encoding))
281
        commit.author = fix_person_identifier(
282
            rev.get_apparent_authors()[0].encode(encoding))
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
283
        commit.commit_time = long(rev.timestamp)
284
        if 'author-timestamp' in rev.properties:
285
            commit.author_time = long(rev.properties['author-timestamp'])
286
        else:
287
            commit.author_time = commit.commit_time
0.200.884 by Jelmer Vernooij
Cope with -0000 as timezone in Git commits.
288
        commit._commit_timezone_neg_utc = "commit-timezone-neg-utc" in rev.properties
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
289
        commit.commit_timezone = rev.timezone
0.200.884 by Jelmer Vernooij
Cope with -0000 as timezone in Git commits.
290
        commit._author_timezone_neg_utc = "author-timezone-neg-utc" in rev.properties
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
291
        if 'author-timezone' in rev.properties:
292
            commit.author_timezone = int(rev.properties['author-timezone'])
293
        else:
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
294
            commit.author_timezone = commit.commit_timezone
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
295
        commit.message = self._encode_commit_message(rev, rev.message, 
296
            encoding)
0.252.40 by Jelmer Vernooij
Checks for roundtripping.
297
        assert type(commit.message) == str
0.252.8 by Jelmer Vernooij
Support ghost revisions while roundtripping.
298
        if metadata is not None:
0.252.4 by Jelmer Vernooij
More work on roundtripping.
299
            try:
300
                mapping_registry.parse_revision_id(rev.revision_id)
301
            except errors.InvalidRevisionId:
302
                metadata.revision_id = rev.revision_id
0.252.10 by Jelmer Vernooij
Support roundtripping custom revision properties.
303
            mapping_properties = set(
304
                ['author', 'author-timezone', 'author-timezone-neg-utc',
305
                 'commit-timezone-neg-utc', 'git-implicit-encoding',
0.252.15 by Jelmer Vernooij
Add file-modes to list of mapping properties.
306
                 'git-explicit-encoding', 'author-timestamp', 'file-modes'])
0.252.10 by Jelmer Vernooij
Support roundtripping custom revision properties.
307
            for k, v in rev.properties.iteritems():
308
                if not k in mapping_properties:
309
                    metadata.properties[k] = v
0.200.1510 by Jelmer Vernooij
Fix tests.
310
        if not lossy:
311
            if self.roundtripping:
312
                commit.message = inject_bzr_metadata(commit.message, metadata, 
313
                                                     encoding)
314
            else:
315
                raise NoPushSupport()
0.252.40 by Jelmer Vernooij
Checks for roundtripping.
316
        assert type(commit.message) == str
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
317
        return commit
318
0.252.22 by Jelmer Vernooij
Fix file id map (de)serialization.
319
    def import_fileid_map(self, blob):
320
        """Convert a git file id map blob.
321
322
        :param blob: Git blob object with fileid map
323
        :return: Dictionary mapping paths to file ids
324
        """
0.252.35 by Jelmer Vernooij
Ignore control files in inventories.
325
        return deserialize_fileid_map(blob.data)
0.252.22 by Jelmer Vernooij
Fix file id map (de)serialization.
326
0.252.44 by Jelmer Vernooij
Properly look up Bazaar revision ids for revision parents in case they are round-tripped.
327
    def import_commit(self, commit, lookup_parent_revid):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
328
        """Convert a git commit to a bzr revision.
329
0.200.1021 by Jelmer Vernooij
Put testament sha1 in revisions.
330
        :return: a `bzrlib.revision.Revision` object, foreign revid and a
331
            testament sha1
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
332
        """
333
        if commit is None:
334
            raise AssertionError("Commit object can't be None")
0.200.1598 by Jelmer Vernooij
Print proper error when unknown fields are encountered.
335
        if commit.extra:
336
            raise UnknownCommitExtra(commit, [item[0] for item in commit.extra])
0.200.826 by Jelmer Vernooij
Fix some long lines.
337
        rev = ForeignRevision(commit.id, self,
338
                self.revision_id_foreign_to_bzr(commit.id))
0.252.4 by Jelmer Vernooij
More work on roundtripping.
339
        rev.git_metadata = None
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
340
        def decode_using_encoding(rev, commit, encoding):
341
            rev.committer = str(commit.committer).decode(encoding)
342
            if commit.committer != commit.author:
343
                rev.properties['author'] = str(commit.author).decode(encoding)
0.252.4 by Jelmer Vernooij
More work on roundtripping.
344
            rev.message, rev.git_metadata = self._decode_commit_message(
345
                rev, commit.message, encoding)
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
346
        if commit.encoding is not None:
347
            rev.properties['git-explicit-encoding'] = commit.encoding
348
            decode_using_encoding(rev, commit, commit.encoding)
349
        else:
350
            for encoding in ('utf-8', 'latin1'):
351
                try:
352
                    decode_using_encoding(rev, commit, encoding)
353
                except UnicodeDecodeError:
354
                    pass
355
                else:
356
                    if encoding != 'utf-8':
357
                        rev.properties['git-implicit-encoding'] = encoding
358
                    break
0.200.350 by Jelmer Vernooij
Support author_time
359
        if commit.commit_time != commit.author_time:
360
            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.
361
        if commit.commit_timezone != commit.author_timezone:
0.200.826 by Jelmer Vernooij
Fix some long lines.
362
            rev.properties['author-timezone'] = "%d" % commit.author_timezone
0.200.884 by Jelmer Vernooij
Cope with -0000 as timezone in Git commits.
363
        if commit._author_timezone_neg_utc:
364
            rev.properties['author-timezone-neg-utc'] = ""
365
        if commit._commit_timezone_neg_utc:
366
            rev.properties['commit-timezone-neg-utc'] = ""
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
367
        rev.timestamp = commit.commit_time
0.200.440 by Jelmer Vernooij
Remove silly mapping of timezones; dulwich uses offsets now as well.
368
        rev.timezone = commit.commit_timezone
0.261.5 by Jelmer Vernooij
Fix looking up of parents during fetch.
369
        rev.parent_ids = None
0.252.4 by Jelmer Vernooij
More work on roundtripping.
370
        if rev.git_metadata is not None:
0.252.6 by Jelmer Vernooij
Roundtripping support for revision ids works.
371
            md = rev.git_metadata
0.200.1021 by Jelmer Vernooij
Put testament sha1 in revisions.
372
            roundtrip_revid = md.revision_id
0.252.8 by Jelmer Vernooij
Support ghost revisions while roundtripping.
373
            if md.explicit_parent_ids:
374
                rev.parent_ids = md.explicit_parent_ids
0.252.10 by Jelmer Vernooij
Support roundtripping custom revision properties.
375
            rev.properties.update(md.properties)
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
376
            verifiers = md.verifiers
0.200.1021 by Jelmer Vernooij
Put testament sha1 in revisions.
377
        else:
378
            roundtrip_revid = None
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
379
            verifiers = {}
0.261.5 by Jelmer Vernooij
Fix looking up of parents during fetch.
380
        if rev.parent_ids is None:
381
            rev.parent_ids = tuple([lookup_parent_revid(p) for p in commit.parents])
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
382
        return rev, roundtrip_revid, verifiers
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
383
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
384
    def get_fileid_map(self, lookup_object, tree_sha):
385
        """Obtain a fileid map for a particular tree.
386
387
        :param lookup_object: Function for looking up an object
388
        :param tree_sha: SHA of the root tree
389
        :return: GitFileIdMap instance
390
        """
391
        try:
392
            file_id_map_sha = lookup_object(tree_sha)[self.BZR_FILE_IDS_FILE][1]
393
        except KeyError:
394
            file_ids = {}
395
        else:
396
            file_ids = self.import_fileid_map(lookup_object(file_id_map_sha))
397
        return GitFileIdMap(file_ids, self)
398
0.200.97 by Jelmer Vernooij
use mapping object.
399
0.200.190 by Jelmer Vernooij
Bless current mapping as v1.
400
class BzrGitMappingv1(BzrGitMapping):
401
    revid_prefix = 'git-v1'
402
    experimental = False
403
0.200.393 by Jelmer Vernooij
Provide __str__ implementation for mapping, fix docstring for ForeignGit.
404
    def __str__(self):
405
        return self.revid_prefix
406
0.200.190 by Jelmer Vernooij
Bless current mapping as v1.
407
408
class BzrGitMappingExperimental(BzrGitMappingv1):
0.200.104 by Jelmer Vernooij
Use bzr-foreign function names for converting between git and bzr revids.
409
    revid_prefix = 'git-experimental'
410
    experimental = True
0.200.912 by Jelmer Vernooij
Merge roundtrip support.
411
    roundtripping = True
0.200.97 by Jelmer Vernooij
use mapping object.
412
0.200.915 by Jelmer Vernooij
Cope with the fact that the old format didn't export file ids.
413
    BZR_FILE_IDS_FILE = '.bzrfileids'
414
415
    BZR_DUMMY_FILE = '.bzrdummy'
416
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
417
    def _decode_commit_message(self, rev, message, encoding):
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
418
        message = self._extract_hg_metadata(rev, message)
0.200.643 by Jelmer Vernooij
Attempt to parse git-svn-id metadata.
419
        message = self._extract_git_svn_metadata(rev, message)
0.252.4 by Jelmer Vernooij
More work on roundtripping.
420
        message, metadata = self._extract_bzr_metadata(rev, message)
421
        return message.decode(encoding), metadata
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
422
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
423
    def _encode_commit_message(self, rev, message, encoding):
424
        ret = message.encode(encoding)
0.200.638 by Jelmer Vernooij
Abstract support for hg-git metadata.
425
        ret += self._generate_hg_message_tail(rev)
0.200.727 by Jelmer Vernooij
Cope with different encodings better, rather than just stripping out
426
        ret += self._generate_git_svn_metadata(rev, encoding)
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
427
        return ret
428
0.252.44 by Jelmer Vernooij
Properly look up Bazaar revision ids for revision parents in case they are round-tripped.
429
    def import_commit(self, commit, lookup_parent_revid):
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
430
        rev, roundtrip_revid, verifiers = super(BzrGitMappingExperimental, self).import_commit(commit, lookup_parent_revid)
0.200.642 by Jelmer Vernooij
In experimental mappings, set 'converted_revision' property.
431
        rev.properties['converted_revision'] = "git %s\n" % commit.id
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
432
        return rev, roundtrip_revid, verifiers
0.200.642 by Jelmer Vernooij
In experimental mappings, set 'converted_revision' property.
433
0.200.97 by Jelmer Vernooij
use mapping object.
434
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
435
class GitMappingRegistry(VcsMappingRegistry):
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
436
    """Registry with available git mappings."""
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
437
438
    def revision_id_bzr_to_foreign(self, bzr_revid):
0.200.701 by Jelmer Vernooij
Fix check in git repos.
439
        if bzr_revid == NULL_REVISION:
0.200.892 by Jelmer Vernooij
Lazy import ZERO_SHA.
440
            from dulwich.protocol import ZERO_SHA
0.200.891 by Jelmer Vernooij
Use ZERO_SHA constant where possible.
441
            return ZERO_SHA, None
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
442
        if not bzr_revid.startswith("git-"):
443
            raise errors.InvalidRevisionId(bzr_revid, None)
444
        (mapping_version, git_sha) = bzr_revid.split(":", 1)
445
        mapping = self.get(mapping_version)
446
        return mapping.revision_id_bzr_to_foreign(bzr_revid)
447
448
    parse_revision_id = revision_id_bzr_to_foreign
449
450
451
mapping_registry = GitMappingRegistry()
452
mapping_registry.register_lazy('git-v1', "bzrlib.plugins.git.mapping",
0.200.826 by Jelmer Vernooij
Fix some long lines.
453
    "BzrGitMappingv1")
454
mapping_registry.register_lazy('git-experimental',
455
    "bzrlib.plugins.git.mapping", "BzrGitMappingExperimental")
0.200.1507 by Jelmer Vernooij
Add note on experimental mapping format.
456
# Uncomment the next line to enable the experimental bzr-git mappings.
457
# This will make sure all bzr metadata is pushed into git, allowing for
458
# full roundtripping later.
459
# NOTE: THIS IS EXPERIMENTAL. IT MAY EAT YOUR DATA OR CORRUPT
460
# YOUR BZR OR GIT REPOSITORIES. USE WITH CARE.
0.200.1416 by Jelmer Vernooij
Don't use experimental mapping by default.
461
#mapping_registry.set_default('git-experimental')
462
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.
463
464
465
class ForeignGit(ForeignVcs):
0.200.393 by Jelmer Vernooij
Provide __str__ implementation for mapping, fix docstring for ForeignGit.
466
    """The Git Stupid Content Tracker"""
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
467
0.243.1 by Jelmer Vernooij
Use foreign branch testing infrastructure.
468
    @property
469
    def branch_format(self):
470
        from bzrlib.plugins.git.branch import GitBranchFormat
471
        return GitBranchFormat()
472
0.200.657 by Jelmer Vernooij
Provide repository_format attribute, as required by newer foreign VCS tests in bzrlib.
473
    @property
474
    def repository_format(self):
475
        from bzrlib.plugins.git.repository import GitRepositoryFormat
476
        return GitRepositoryFormat()
477
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
478
    def __init__(self):
479
        super(ForeignGit, self).__init__(mapping_registry)
0.200.646 by Jelmer Vernooij
Store abbreviation in foreign branch.
480
        self.abbreviation = "git"
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
481
0.200.198 by Jelmer Vernooij
Cope with move of show_foreign_revid.
482
    @classmethod
0.200.652 by Jelmer Vernooij
Split out git-svn-id parser as separate function, implement ForeignGit.serialize_foreign_revid.
483
    def serialize_foreign_revid(self, foreign_revid):
484
        return foreign_revid
485
486
    @classmethod
0.200.198 by Jelmer Vernooij
Cope with move of show_foreign_revid.
487
    def show_foreign_revid(cls, foreign_revid):
488
        return { "git commit": foreign_revid }
489
490
0.200.1263 by Jelmer Vernooij
Fix foreign_vcs_git.
491
foreign_vcs_git = ForeignGit()
0.200.637 by Jelmer Vernooij
Allow single place for configuration of default mapping.
492
default_mapping = mapping_registry.get_default()()
0.200.212 by Jelmer Vernooij
Move conversion functions to mapping, use fetch_objects() from repository if present.
493
494
0.275.1 by Jelmer Vernooij
Use root_inventory.
495
def symlink_to_blob(symlink_target):
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
496
    from dulwich.objects import Blob
497
    blob = Blob()
0.200.795 by Jelmer Vernooij
simplify sha extraction for blobs, process multiple blobs at once.
498
    if type(symlink_target) == unicode:
499
        symlink_target = symlink_target.encode('utf-8')
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
500
    blob.data = symlink_target
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
501
    return blob
502
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
503
0.200.521 by Jelmer Vernooij
Abstract out kind mapping a bit, initial work on support tree-references.
504
def mode_is_executable(mode):
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
505
    """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.
506
    return bool(mode & 0111)
507
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
508
0.200.521 by Jelmer Vernooij
Abstract out kind mapping a bit, initial work on support tree-references.
509
def mode_kind(mode):
0.200.546 by Jelmer Vernooij
Add more docstrings, support storing unusual file modes.
510
    """Determine the Bazaar inventory kind based on Unix file mode."""
0.200.1538 by Jelmer Vernooij
More work on tree-reference support.
511
    if mode is None:
512
        return None
0.200.521 by Jelmer Vernooij
Abstract out kind mapping a bit, initial work on support tree-references.
513
    entry_kind = (mode & 0700000) / 0100000
514
    if entry_kind == 0:
515
        return 'directory'
516
    elif entry_kind == 1:
517
        file_kind = (mode & 070000) / 010000
518
        if file_kind == 0:
519
            return 'file'
520
        elif file_kind == 2:
521
            return 'symlink'
522
        elif file_kind == 6:
523
            return 'tree-reference'
524
        else:
525
            raise AssertionError(
526
                "Unknown file kind %d, perms=%o." % (file_kind, mode,))
527
    else:
528
        raise AssertionError(
529
            "Unknown kind, perms=%r." % (mode,))
530
0.200.354 by Jelmer Vernooij
Support symlinks in conversion to git.
531
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
532
def object_mode(kind, executable):
533
    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.
534
        return stat.S_IFDIR
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
535
    elif kind == 'symlink':
0.245.1 by INADA Naoki
Handle executable mode for symlink.
536
        mode = stat.S_IFLNK
537
        if executable:
0.200.703 by Jelmer Vernooij
Merge support for executable symlinks.
538
            mode |= 0111
0.245.1 by INADA Naoki
Handle executable mode for symlink.
539
        return mode
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
540
    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.
541
        mode = stat.S_IFREG | 0644
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
542
        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.
543
            mode |= 0111
544
        return mode
0.200.665 by Jelmer Vernooij
Add more checks for submodules.
545
    elif kind == 'tree-reference':
546
        from dulwich.objects import S_IFGITLINK
547
        return S_IFGITLINK
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.
548
    else:
549
        raise AssertionError
550
551
0.238.6 by Jelmer Vernooij
Support sending git am-style patches with "bzr send --format=git".
552
def entry_mode(entry):
553
    """Determine the git file mode for an inventory entry."""
554
    return object_mode(entry.kind, entry.executable)
555
556
0.275.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
557
def directory_to_tree(children, lookup_ie_sha1, unusual_modes, empty_file_name,
558
                      allow_empty=False):
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
559
    """Create a Git Tree object from a Bazaar directory.
560
0.275.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
561
    :param children: Children inventory entries
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
562
    :param lookup_ie_sha1: Lookup the Git SHA1 for a inventory entry
563
    :param unusual_modes: Dictionary with unusual file modes by file ids
564
    :param empty_file_name: Name to use for dummy files in empty directories,
565
        None to ignore empty directories.
566
    """
567
    from dulwich.objects import Blob, 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.
568
    tree = Tree()
0.275.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
569
    for name, value in children.iteritems():
570
        ie = children[name]
0.200.549 by Jelmer Vernooij
Fix storing of unusual file modes.
571
        try:
572
            mode = unusual_modes[ie.file_id]
573
        except KeyError:
574
            mode = entry_mode(ie)
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
575
        hexsha = lookup_ie_sha1(ie)
0.200.589 by Jelmer Vernooij
Fix handling of empty trees.
576
        if hexsha is not None:
0.200.1152 by Jelmer Vernooij
Require dulwich 0.7.1.
577
            tree.add(name.encode("utf-8"), mode, hexsha)
0.275.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
578
    if not allow_empty and len(tree) == 0:
0.200.589 by Jelmer Vernooij
Fix handling of empty trees.
579
        # Only the root can be an empty tree
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
580
        if empty_file_name is not None:
0.200.1152 by Jelmer Vernooij
Require dulwich 0.7.1.
581
            tree.add(empty_file_name, stat.S_IFREG | 0644, Blob().id)
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
582
        else:
583
            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.
584
    return tree
585
586
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
587
def extract_unusual_modes(rev):
588
    try:
0.200.826 by Jelmer Vernooij
Fix some long lines.
589
        foreign_revid, mapping = mapping_registry.parse_revision_id(
590
            rev.revision_id)
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
591
    except errors.InvalidRevisionId:
592
        return {}
593
    else:
594
        return mapping.export_unusual_file_modes(rev)
595
596
0.200.652 by Jelmer Vernooij
Split out git-svn-id parser as separate function, implement ForeignGit.serialize_foreign_revid.
597
def parse_git_svn_id(text):
598
    (head, uuid) = text.rsplit(" ", 1)
599
    (full_url, rev) = head.rsplit("@", 1)
0.200.653 by Jelmer Vernooij
Fix typo in git-svn-id parser, return revnum as integer.
600
    return (full_url, int(rev), uuid)
0.252.33 by Jelmer Vernooij
Fix file id map lookups.
601
602
603
class GitFileIdMap(object):
604
605
    def __init__(self, file_ids, mapping):
606
        self.file_ids = file_ids
607
        self.paths = None
608
        self.mapping = mapping
609
0.200.1569 by Jelmer Vernooij
Implement GitRevisionTree.all_file_ids().
610
    def all_file_ids(self):
611
        return self.file_ids.values()
612
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
613
    def set_file_id(self, path, file_id):
0.200.1209 by Jelmer Vernooij
Check for types in file id map.
614
        assert type(path) is str
615
        assert type(file_id) is str
0.200.1201 by Jelmer Vernooij
Implement _set_root_id.
616
        self.file_ids[path] = file_id
617
0.252.33 by Jelmer Vernooij
Fix file id map lookups.
618
    def lookup_file_id(self, path):
0.200.984 by Jelmer Vernooij
Handle non-ascii characters in filenames.
619
        assert type(path) is str
0.252.33 by Jelmer Vernooij
Fix file id map lookups.
620
        try:
0.200.973 by Jelmer Vernooij
Add tests for generate_file_id.
621
            file_id = self.file_ids[path]
0.252.33 by Jelmer Vernooij
Fix file id map lookups.
622
        except KeyError:
0.200.973 by Jelmer Vernooij
Add tests for generate_file_id.
623
            file_id = self.mapping.generate_file_id(path)
624
        assert type(file_id) is str
625
        return file_id
0.252.33 by Jelmer Vernooij
Fix file id map lookups.
626
627
    def lookup_path(self, file_id):
628
        if self.paths is None:
629
            self.paths = {}
630
            for k, v in self.file_ids.iteritems():
631
                self.paths[v] = k
632
        try:
0.200.984 by Jelmer Vernooij
Handle non-ascii characters in filenames.
633
            path = self.paths[file_id]
0.252.33 by Jelmer Vernooij
Fix file id map lookups.
634
        except KeyError:
635
            return self.mapping.parse_file_id(file_id)
0.200.984 by Jelmer Vernooij
Handle non-ascii characters in filenames.
636
        else:
637
            assert type(path) is str
638
            return path
0.200.1202 by Jelmer Vernooij
Implement has_or_had_id.
639
640
    def copy(self):
641
        return self.__class__(dict(self.file_ids), self.mapping)