/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to mapping.py

Add tests for revspec.

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
    VcsMappingRegistry,
41
41
    ForeignRevision,
42
42
    )
 
43
from bzrlib.revision import (
 
44
    NULL_REVISION,
 
45
    )
43
46
from bzrlib.plugins.git.hg import (
44
47
    format_hg_metadata,
45
48
    extract_hg_metadata,
116
119
        super(BzrGitMapping, self).__init__(foreign_git)
117
120
 
118
121
    def __eq__(self, other):
119
 
        return type(self) == type(other) and self.revid_prefix == other.revid_prefix
 
122
        return (type(self) == type(other) and 
 
123
                self.revid_prefix == other.revid_prefix)
120
124
 
121
125
    @classmethod
122
126
    def revision_id_foreign_to_bzr(cls, git_rev_id):
123
127
        """Convert a git revision id handle to a Bazaar revision id."""
 
128
        if git_rev_id == "0" * 40:
 
129
            return NULL_REVISION
124
130
        return "%s:%s" % (cls.revid_prefix, git_rev_id)
125
131
 
126
132
    @classmethod
144
150
 
145
151
    def import_unusual_file_modes(self, rev, unusual_file_modes):
146
152
        if unusual_file_modes:
147
 
            ret = [(name, unusual_file_modes[name]) for name in sorted(unusual_file_modes.keys())]
 
153
            ret = [(name, unusual_file_modes[name])
 
154
                   for name in sorted(unusual_file_modes.keys())]
148
155
            rev.properties['file-modes'] = bencode.bencode(ret)
149
156
 
150
157
    def export_unusual_file_modes(self, rev):
153
160
        except KeyError:
154
161
            return {}
155
162
 
156
 
    def _generate_git_svn_metadata(self, rev):
 
163
    def _generate_git_svn_metadata(self, rev, encoding):
157
164
        try:
158
 
            return "\ngit-svn-id: %s\n" % rev.properties["git-svn-id"].encode("utf-8")
 
165
            return "\ngit-svn-id: %s\n" % rev.properties["git-svn-id"].encode(encoding)
159
166
        except KeyError:
160
167
            return ""
161
168
 
197
204
            rev.properties['hg:renames'] = base64.b64encode(bencode.bencode([(new, old) for (old, new) in renames.iteritems()]))
198
205
        return message
199
206
 
200
 
    def _decode_commit_message(self, rev, message):
201
 
        return message.decode("utf-8", "replace")
 
207
    def _decode_commit_message(self, rev, message, encoding):
 
208
        return message.decode(encoding)
202
209
 
203
 
    def _encode_commit_message(self, rev, message):
204
 
        return message.encode("utf-8")
 
210
    def _encode_commit_message(self, rev, message, encoding):
 
211
        return message.encode(encoding)
205
212
 
206
213
    def export_commit(self, rev, tree_sha, parent_lookup):
207
214
        """Turn a Bazaar revision in to a Git commit
214
221
        commit = Commit()
215
222
        commit.tree = tree_sha
216
223
        for p in rev.parent_ids:
217
 
            git_p = parent_lookup(p)
 
224
            try:
 
225
                git_p = parent_lookup(p)
 
226
            except KeyError:
 
227
                git_p = None
218
228
            if git_p is not None:
219
229
                assert len(git_p) == 40, "unexpected length for %r" % git_p
220
230
                commit.parents.append(git_p)
221
 
        commit.committer = fix_person_identifier(rev.committer.encode("utf-8"))
222
 
        commit.author = fix_person_identifier(rev.get_apparent_authors()[0].encode("utf-8"))
 
231
        try:
 
232
            encoding = rev.properties['git-explicit-encoding']
 
233
        except KeyError:
 
234
            encoding = rev.properties.get('git-implicit-encoding', 'utf-8')
 
235
        commit.encoding = rev.properties.get('git-explicit-encoding')
 
236
        commit.committer = fix_person_identifier(rev.committer.encode(
 
237
            encoding))
 
238
        commit.author = fix_person_identifier(
 
239
            rev.get_apparent_authors()[0].encode(encoding))
223
240
        commit.commit_time = long(rev.timestamp)
224
241
        if 'author-timestamp' in rev.properties:
225
242
            commit.author_time = long(rev.properties['author-timestamp'])
230
247
            commit.author_timezone = int(rev.properties['author-timezone'])
231
248
        else:
232
249
            commit.author_timezone = commit.commit_timezone
233
 
        commit.message = self._encode_commit_message(rev, rev.message)
 
250
        commit.message = self._encode_commit_message(rev, rev.message, 
 
251
            encoding)
234
252
        return commit
235
253
 
236
254
    def import_commit(self, commit):
242
260
            raise AssertionError("Commit object can't be None")
243
261
        rev = ForeignRevision(commit.id, self, self.revision_id_foreign_to_bzr(commit.id))
244
262
        rev.parent_ids = tuple([self.revision_id_foreign_to_bzr(p) for p in commit.parents])
245
 
        rev.committer = str(commit.committer).decode("utf-8", "replace")
246
 
        if commit.committer != commit.author:
247
 
            rev.properties['author'] = str(commit.author).decode("utf-8", "replace")
248
 
 
 
263
        def decode_using_encoding(rev, commit, encoding):
 
264
            rev.committer = str(commit.committer).decode(encoding)
 
265
            if commit.committer != commit.author:
 
266
                rev.properties['author'] = str(commit.author).decode(encoding)
 
267
            rev.message = self._decode_commit_message(rev, commit.message, 
 
268
                encoding)
 
269
        if commit.encoding is not None:
 
270
            rev.properties['git-explicit-encoding'] = commit.encoding
 
271
            decode_using_encoding(rev, commit, commit.encoding)
 
272
        else:
 
273
            for encoding in ('utf-8', 'latin1'):
 
274
                try:
 
275
                    decode_using_encoding(rev, commit, encoding)
 
276
                except UnicodeDecodeError:
 
277
                    pass
 
278
                else:
 
279
                    if encoding != 'utf-8':
 
280
                        rev.properties['git-implicit-encoding'] = encoding
 
281
                    break
249
282
        if commit.commit_time != commit.author_time:
250
283
            rev.properties['author-timestamp'] = str(commit.author_time)
251
284
        if commit.commit_timezone != commit.author_timezone:
252
285
            rev.properties['author-timezone'] = "%d" % (commit.author_timezone, )
253
286
        rev.timestamp = commit.commit_time
254
287
        rev.timezone = commit.commit_timezone
255
 
        rev.message = self._decode_commit_message(rev, commit.message)
256
288
        return rev
257
289
 
258
290
 
268
300
    revid_prefix = 'git-experimental'
269
301
    experimental = True
270
302
 
271
 
    def _decode_commit_message(self, rev, message):
 
303
    def _decode_commit_message(self, rev, message, encoding):
272
304
        message = self._extract_hg_metadata(rev, message)
273
305
        message = self._extract_git_svn_metadata(rev, message)
274
 
        return message.decode("utf-8", "replace")
 
306
        return message.decode(encoding)
275
307
 
276
 
    def _encode_commit_message(self, rev, message):
277
 
        ret = message.encode("utf-8")
 
308
    def _encode_commit_message(self, rev, message, encoding):
 
309
        ret = message.encode(encoding)
278
310
        ret += self._generate_hg_message_tail(rev)
279
 
        ret += self._generate_git_svn_metadata(rev)
 
311
        ret += self._generate_git_svn_metadata(rev, encoding)
280
312
        return ret
281
313
 
282
314
    def import_commit(self, commit):
289
321
    """Registry with available git mappings."""
290
322
 
291
323
    def revision_id_bzr_to_foreign(self, bzr_revid):
 
324
        if bzr_revid == NULL_REVISION:
 
325
            return "0" * 20, None
292
326
        if not bzr_revid.startswith("git-"):
293
327
            raise errors.InvalidRevisionId(bzr_revid, None)
294
328
        (mapping_version, git_sha) = bzr_revid.split(":", 1)
336
370
default_mapping = mapping_registry.get_default()()
337
371
 
338
372
 
339
 
def text_to_blob(texts, entry):
340
 
    from dulwich.objects import Blob
341
 
    text = texts.get_record_stream([(entry.file_id, entry.revision)], 'unordered', True).next().get_bytes_as('fulltext')
342
 
    blob = Blob()
343
 
    blob._text = text
344
 
    return blob
345
 
 
346
 
 
347
373
def symlink_to_blob(entry):
348
374
    from dulwich.objects import Blob
349
375
    blob = Blob()
350
 
    blob._text = entry.symlink_target
 
376
    symlink_target = entry.symlink_target
 
377
    if type(symlink_target) == unicode:
 
378
        symlink_target = symlink_target.encode('utf-8')
 
379
    blob.data = symlink_target
351
380
    return blob
352
381
 
353
382
 
381
410
    if kind == 'directory':
382
411
        return stat.S_IFDIR
383
412
    elif kind == 'symlink':
384
 
        return stat.S_IFLNK
 
413
        mode = stat.S_IFLNK
 
414
        if executable:
 
415
            mode |= 0111
 
416
        return mode
385
417
    elif kind == 'file':
386
418
        mode = stat.S_IFREG | 0644
387
419
        if executable:
402
434
def directory_to_tree(entry, lookup_ie_sha1, unusual_modes):
403
435
    from dulwich.objects import Tree
404
436
    tree = Tree()
405
 
    for name in sorted(entry.children.keys()):
 
437
    for name, value in entry.children.iteritems():
406
438
        ie = entry.children[name]
407
439
        try:
408
440
            mode = unusual_modes[ie.file_id]
414
446
    if entry.parent_id is not None and len(tree) == 0:
415
447
        # Only the root can be an empty tree
416
448
        return None
417
 
    tree.serialize()
418
449
    return tree
419
450
 
420
451
 
444
475
    for path, entry in inventory.iter_entries():
445
476
        while stack and not path.startswith(osutils.pathjoin(cur, "")):
446
477
            # We've hit a file that's not a child of the previous path
447
 
            tree.serialize()
448
478
            sha = tree.id
449
479
            yield sha, tree, cur.encode("utf-8")
450
480
            mode = unusual_modes.get(cur.encode("utf-8"), stat.S_IFDIR)
458
488
            tree = Tree()
459
489
        else:
460
490
            if entry.kind == "file":
461
 
                blob = text_to_blob(texts, entry)
 
491
                from dulwich.objects import Blob
 
492
                text = texts.get_record_stream([(entry.file_id, entry.revision)], 'unordered', True).next().get_bytes_as('fulltext')
 
493
                blob = Blob()
 
494
                blob.data = text
462
495
            elif entry.kind == "symlink":
463
496
                blob = symlink_to_blob(entry)
464
497
            else:
470
503
            tree.add(mode, name, sha)
471
504
 
472
505
    while len(stack) > 1:
473
 
        tree.serialize()
474
506
        sha = tree.id
475
507
        yield sha, tree, cur.encode("utf-8")
476
508
        mode = unusual_modes.get(cur.encode('utf-8'), stat.S_IFDIR)
478
510
        cur, tree = stack.pop()
479
511
        tree.add(*t)
480
512
 
481
 
    tree.serialize()
482
513
    yield tree.id, tree, cur.encode("utf-8")
483
514
 
484
515