/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

Fix branch cloning.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2007 Canonical Ltd
2
 
# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@samba.org>
3
 
# Copyright (C) 2008 John Carr
4
2
#
5
3
# This program is free software; you can redistribute it and/or modify
6
4
# it under the terms of the GNU General Public License as published by
18
16
 
19
17
"""Converters, etc for going between Bazaar and Git ids."""
20
18
 
21
 
import stat
22
 
 
23
 
from bzrlib import (
24
 
    errors,
25
 
    foreign,
26
 
    osutils,
27
 
    urlutils,
28
 
    )
29
 
from bzrlib.inventory import (
30
 
    ROOT_ID,
31
 
    )
 
19
from bzrlib import errors, foreign
 
20
from bzrlib.inventory import ROOT_ID
32
21
from bzrlib.foreign import (
33
 
    ForeignVcs, 
34
 
    VcsMappingRegistry, 
35
 
    ForeignRevision,
36
 
    )
37
 
from bzrlib.xml_serializer import (
38
 
    escape_invalid_chars,
39
 
    )
40
 
 
41
 
DEFAULT_FILE_MODE = stat.S_IFREG | 0644
 
22
        ForeignRevision,
 
23
        )
42
24
 
43
25
 
44
26
def escape_file_id(file_id):
53
35
    """Class that maps between Git and Bazaar semantics."""
54
36
    experimental = False
55
37
 
56
 
    def __init__(self):
57
 
        super(BzrGitMapping, self).__init__(foreign_git)
58
 
 
59
 
    def __eq__(self, other):
60
 
        return type(self) == type(other) and self.revid_prefix == other.revid_prefix
61
 
 
62
 
    @classmethod
63
 
    def revision_id_foreign_to_bzr(cls, git_rev_id):
 
38
    def revision_id_foreign_to_bzr(self, git_rev_id):
64
39
        """Convert a git revision id handle to a Bazaar revision id."""
65
 
        return "%s:%s" % (cls.revid_prefix, git_rev_id)
 
40
        return "%s:%s" % (self.revid_prefix, git_rev_id)
66
41
 
67
 
    @classmethod
68
 
    def revision_id_bzr_to_foreign(cls, bzr_rev_id):
 
42
    def revision_id_bzr_to_foreign(self, bzr_rev_id):
69
43
        """Convert a Bazaar revision id to a git revision id handle."""
70
 
        if not bzr_rev_id.startswith("%s:" % cls.revid_prefix):
71
 
            raise errors.InvalidRevisionId(bzr_rev_id, cls)
72
 
        return bzr_rev_id[len(cls.revid_prefix)+1:], cls()
 
44
        if not bzr_rev_id.startswith("%s:" % self.revid_prefix):
 
45
            raise errors.InvalidRevisionId(bzr_rev_id, self)
 
46
        return bzr_rev_id[len(self.revid_prefix)+1:]
 
47
 
 
48
    def show_foreign_revid(self, foreign_revid):
 
49
        return { "git commit": foreign_revid }
73
50
 
74
51
    def generate_file_id(self, path):
75
 
        # Git paths are just bytestrings
76
 
        # We must just hope they are valid UTF-8..
77
 
        assert isinstance(path, str)
78
52
        if path == "":
79
53
            return ROOT_ID
80
 
        return escape_file_id(path)
81
 
 
82
 
    def parse_file_id(self, file_id):
83
 
        if file_id == ROOT_ID:
84
 
            return ""
85
 
        return unescape_file_id(file_id)
 
54
        return escape_file_id(path.encode('utf-8'))
86
55
 
87
56
    def import_commit(self, commit):
88
57
        """Convert a git commit to a bzr revision.
93
62
            raise AssertionError("Commit object can't be None")
94
63
        rev = ForeignRevision(commit.id, self, self.revision_id_foreign_to_bzr(commit.id))
95
64
        rev.parent_ids = tuple([self.revision_id_foreign_to_bzr(p) for p in commit.parents])
96
 
        rev.message = escape_invalid_chars(commit.message.decode("utf-8", "replace"))[0]
97
 
        rev.committer = escape_invalid_chars(str(commit.committer).decode("utf-8", "replace"))[0]
 
65
        rev.message = commit.message.decode("utf-8", "replace")
 
66
        rev.committer = str(commit.committer).decode("utf-8", "replace")
98
67
        if commit.committer != commit.author:
99
 
            rev.properties['author'] = escape_invalid_chars(str(commit.author).decode("utf-8", "replace"))[0]
100
 
 
101
 
        if commit.commit_time != commit.author_time:
102
 
            rev.properties['author-timestamp'] = str(commit.author_time)
103
 
        if commit.commit_timezone != commit.author_timezone:
104
 
            rev.properties['author-timezone'] = str(commit.author_timezone)
 
68
            rev.properties['author'] = str(commit.author).decode("utf-8", "replace")
105
69
        rev.timestamp = commit.commit_time
106
 
        rev.timezone = commit.commit_timezone
 
70
        rev.timezone = 0
107
71
        return rev
108
72
 
109
73
 
110
 
class BzrGitMappingv1(BzrGitMapping):
111
 
    revid_prefix = 'git-v1'
112
 
    experimental = False
113
 
 
114
 
 
115
 
class BzrGitMappingExperimental(BzrGitMappingv1):
 
74
class BzrGitMappingExperimental(BzrGitMapping):
116
75
    revid_prefix = 'git-experimental'
117
76
    experimental = True
118
77
 
119
78
 
120
 
class GitMappingRegistry(VcsMappingRegistry):
121
 
 
122
 
    def revision_id_bzr_to_foreign(self, bzr_revid):
123
 
        if not bzr_revid.startswith("git-"):
124
 
            raise errors.InvalidRevisionId(bzr_revid, None)
125
 
        (mapping_version, git_sha) = bzr_revid.split(":", 1)
126
 
        mapping = self.get(mapping_version)
127
 
        return mapping.revision_id_bzr_to_foreign(bzr_revid)
128
 
 
129
 
    parse_revision_id = revision_id_bzr_to_foreign
130
 
 
131
 
 
132
 
mapping_registry = GitMappingRegistry()
133
 
mapping_registry.register_lazy('git-v1', "bzrlib.plugins.git.mapping",
134
 
                                   "BzrGitMappingv1")
135
 
mapping_registry.register_lazy('git-experimental', "bzrlib.plugins.git.mapping",
136
 
                                   "BzrGitMappingExperimental")
137
 
 
138
 
 
139
 
class ForeignGit(ForeignVcs):
140
 
    """Foreign Git."""
141
 
 
142
 
    def __init__(self):
143
 
        super(ForeignGit, self).__init__(mapping_registry)
144
 
 
145
 
    @classmethod
146
 
    def show_foreign_revid(cls, foreign_revid):
147
 
        return { "git commit": foreign_revid }
148
 
 
149
 
 
150
 
foreign_git = ForeignGit()
151
 
default_mapping = BzrGitMappingv1()
152
 
 
153
 
 
154
 
def text_to_blob(texts, entry):
155
 
    from dulwich.objects import Blob
156
 
    text = texts.get_record_stream([(entry.file_id, entry.revision)], 'unordered', True).next().get_bytes_as('fulltext')
157
 
    blob = Blob()
158
 
    blob._text = text
159
 
    return blob
160
 
 
161
 
 
162
 
def symlink_to_blob(entry):
163
 
    from dulwich.objects import Blob
164
 
    blob = Blob()
165
 
    blob._text = entry.symlink_target
166
 
    return blob
167
 
 
168
 
 
169
 
def entry_mode(entry):
170
 
    if entry.kind == 'directory':
171
 
        return stat.S_IFDIR
172
 
    elif entry.kind == 'symlink':
173
 
        return stat.S_IFLNK
174
 
    elif entry.kind == 'file':
175
 
        mode = stat.S_IFREG | 0644
176
 
        if entry.executable:
177
 
            mode |= 0111
178
 
        return mode
179
 
    else:
180
 
        raise AssertionError
181
 
 
182
 
 
183
 
def directory_to_tree(entry, lookup_ie_sha1):
184
 
    from dulwich.objects import Tree
185
 
    tree = Tree()
186
 
    for name in sorted(entry.children.keys()):
187
 
        ie = entry.children[name]
188
 
        tree.add(entry_mode(ie), name.encode("utf-8"), lookup_ie_sha1(ie))
189
 
    tree.serialize()
190
 
    return tree
191
 
 
192
 
 
193
 
def inventory_to_tree_and_blobs(inventory, texts, mapping, cur=None):
194
 
    """Convert a Bazaar tree to a Git tree.
195
 
 
196
 
    :return: Yields tuples with object sha1, object and path
197
 
    """
198
 
    from dulwich.objects import Tree
199
 
    import stat
200
 
    stack = []
201
 
    if cur is None:
202
 
        cur = ""
203
 
    tree = Tree()
204
 
 
205
 
    # stack contains the set of trees that we haven't 
206
 
    # finished constructing
207
 
    for path, entry in inventory.iter_entries():
208
 
        while stack and not path.startswith(osutils.pathjoin(cur, "")):
209
 
            # We've hit a file that's not a child of the previous path
210
 
            tree.serialize()
211
 
            sha = tree.id
212
 
            yield sha, tree, cur.encode("utf-8")
213
 
            t = (stat.S_IFDIR, urlutils.basename(cur).encode('UTF-8'), sha)
214
 
            cur, tree = stack.pop()
215
 
            tree.add(*t)
216
 
 
217
 
        if entry.kind == "directory":
218
 
            stack.append((cur, tree))
219
 
            cur = path
220
 
            tree = Tree()
221
 
        else:
222
 
            if entry.kind == "file":
223
 
                blob = text_to_blob(texts, entry)
224
 
            elif entry.kind == "symlink":
225
 
                blob = symlink_to_blob(entry)
226
 
            else:
227
 
                raise AssertionError("Unknown kind %s" % entry.kind)
228
 
            sha = blob.id
229
 
            yield sha, blob, path.encode("utf-8")
230
 
            name = urlutils.basename(path).encode("utf-8")
231
 
            tree.add(entry_mode(entry), name, sha)
232
 
 
233
 
    while len(stack) > 1:
234
 
        tree.serialize()
235
 
        sha = tree.id
236
 
        yield sha, tree, cur.encode("utf-8")
237
 
        t = (stat.S_IFDIR, urlutils.basename(cur).encode('UTF-8'), sha)
238
 
        cur, tree = stack.pop()
239
 
        tree.add(*t)
240
 
 
241
 
    tree.serialize()
242
 
    yield tree.id, tree, cur.encode("utf-8")
243
 
 
244
 
 
245
 
def revision_to_commit(rev, tree_sha, parent_lookup):
246
 
    """Turn a Bazaar revision in to a Git commit
247
 
 
248
 
    :param tree_sha: Tree sha for the commit
249
 
    :param parent_lookup: Function for looking up the GIT sha equiv of a bzr revision
250
 
    :return dulwich.objects.Commit represent the revision:
251
 
    """
252
 
    from dulwich.objects import Commit
253
 
    commit = Commit()
254
 
    commit._tree = tree_sha
255
 
    for p in rev.parent_ids:
256
 
        git_p = parent_lookup(p)
257
 
        if git_p is not None:
258
 
            assert len(git_p) == 40, "unexpected length for %r" % git_p
259
 
            commit._parents.append(git_p)
260
 
    commit._message = rev.message.encode("utf-8")
261
 
    commit._committer = rev.committer.encode("utf-8")
262
 
    commit._author = rev.get_apparent_authors()[0].encode("utf-8")
263
 
    commit._commit_time = long(rev.timestamp)
264
 
    if 'author-timestamp' in rev.properties:
265
 
        commit._author_time = long(rev.properties['author-timestamp'])
266
 
    else:
267
 
        commit._author_time = commit._commit_time
268
 
    commit._commit_timezone = rev.timezone
269
 
    if 'author-timezone' in rev.properties:
270
 
        commit._author_timezone = int(rev.properties['author-timezone'])
271
 
    else:
272
 
        commit._author_timezone = commit._commit_timezone
273
 
    commit.serialize()
274
 
    return commit
 
79
default_mapping = BzrGitMappingExperimental()