/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
 
from bzrlib import (
22
 
    errors,
23
 
    foreign,
24
 
    urlutils,
25
 
    )
26
 
from bzrlib.inventory import (
27
 
    ROOT_ID,
28
 
    )
 
19
from bzrlib import errors, foreign
 
20
from bzrlib.inventory import ROOT_ID
29
21
from bzrlib.foreign import (
30
 
    ForeignVcs, 
31
 
    VcsMappingRegistry, 
32
 
    ForeignRevision,
33
 
    )
34
 
from bzrlib.plugins.git.foreign import (
35
 
    escape_commit_message,
36
 
    )
 
22
        ForeignRevision,
 
23
        )
37
24
 
38
25
 
39
26
def escape_file_id(file_id):
48
35
    """Class that maps between Git and Bazaar semantics."""
49
36
    experimental = False
50
37
 
51
 
    def __init__(self):
52
 
        super(BzrGitMapping, self).__init__(foreign_git)
53
 
 
54
 
    def __eq__(self, other):
55
 
        return type(self) == type(other) and self.revid_prefix == other.revid_prefix
56
 
 
57
 
    @classmethod
58
 
    def revision_id_foreign_to_bzr(cls, git_rev_id):
 
38
    def revision_id_foreign_to_bzr(self, git_rev_id):
59
39
        """Convert a git revision id handle to a Bazaar revision id."""
60
 
        return "%s:%s" % (cls.revid_prefix, git_rev_id)
 
40
        return "%s:%s" % (self.revid_prefix, git_rev_id)
61
41
 
62
 
    @classmethod
63
 
    def revision_id_bzr_to_foreign(cls, bzr_rev_id):
 
42
    def revision_id_bzr_to_foreign(self, bzr_rev_id):
64
43
        """Convert a Bazaar revision id to a git revision id handle."""
65
 
        if not bzr_rev_id.startswith("%s:" % cls.revid_prefix):
66
 
            raise errors.InvalidRevisionId(bzr_rev_id, cls)
67
 
        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 }
68
50
 
69
51
    def generate_file_id(self, path):
70
 
        # Git paths are just bytestrings
71
 
        # We must just hope they are valid UTF-8..
72
 
        assert isinstance(path, str)
73
52
        if path == "":
74
53
            return ROOT_ID
75
 
        return escape_file_id(path)
76
 
 
77
 
    def parse_file_id(self, file_id):
78
 
        if file_id == ROOT_ID:
79
 
            return ""
80
 
        return unescape_file_id(file_id)
 
54
        return escape_file_id(path.encode('utf-8'))
81
55
 
82
56
    def import_commit(self, commit):
83
57
        """Convert a git commit to a bzr revision.
88
62
            raise AssertionError("Commit object can't be None")
89
63
        rev = ForeignRevision(commit.id, self, self.revision_id_foreign_to_bzr(commit.id))
90
64
        rev.parent_ids = tuple([self.revision_id_foreign_to_bzr(p) for p in commit.parents])
91
 
        rev.message = escape_commit_message(commit.message.decode("utf-8", "replace"))
92
 
        rev.committer = escape_commit_message(str(commit.committer).decode("utf-8", "replace"))
 
65
        rev.message = commit.message.decode("utf-8", "replace")
 
66
        rev.committer = str(commit.committer).decode("utf-8", "replace")
93
67
        if commit.committer != commit.author:
94
 
            rev.properties['author'] = escape_commit_message(str(commit.author).decode("utf-8", "replace"))
 
68
            rev.properties['author'] = str(commit.author).decode("utf-8", "replace")
95
69
        rev.timestamp = commit.commit_time
96
70
        rev.timezone = 0
97
71
        return rev
98
72
 
99
73
 
100
 
class BzrGitMappingv1(BzrGitMapping):
101
 
    revid_prefix = 'git-v1'
102
 
    experimental = False
103
 
 
104
 
 
105
 
class BzrGitMappingExperimental(BzrGitMappingv1):
 
74
class BzrGitMappingExperimental(BzrGitMapping):
106
75
    revid_prefix = 'git-experimental'
107
76
    experimental = True
108
77
 
109
78
 
110
 
class GitMappingRegistry(VcsMappingRegistry):
111
 
 
112
 
    def revision_id_bzr_to_foreign(self, bzr_revid):
113
 
        if not bzr_revid.startswith("git-"):
114
 
            raise errors.InvalidRevisionId(bzr_revid, None)
115
 
        (mapping_version, git_sha) = bzr_revid.split(":", 1)
116
 
        mapping = self.get(mapping_version)
117
 
        return mapping.revision_id_bzr_to_foreign(bzr_revid)
118
 
 
119
 
    parse_revision_id = revision_id_bzr_to_foreign
120
 
 
121
 
 
122
 
mapping_registry = GitMappingRegistry()
123
 
mapping_registry.register_lazy('git-v1', "bzrlib.plugins.git.mapping",
124
 
                                   "BzrGitMappingv1")
125
 
mapping_registry.register_lazy('git-experimental', "bzrlib.plugins.git.mapping",
126
 
                                   "BzrGitMappingExperimental")
127
 
 
128
 
 
129
 
class ForeignGit(ForeignVcs):
130
 
    """Foreign Git."""
131
 
 
132
 
    def __init__(self):
133
 
        super(ForeignGit, self).__init__(mapping_registry)
134
 
 
135
 
    @classmethod
136
 
    def show_foreign_revid(cls, foreign_revid):
137
 
        return { "git commit": foreign_revid }
138
 
 
139
 
 
140
 
foreign_git = ForeignGit()
141
 
default_mapping = BzrGitMappingv1()
142
 
 
143
 
 
144
 
def text_to_blob(text):
145
 
    from dulwich.objects import Blob
146
 
    blob = Blob()
147
 
    blob._text = text
148
 
    return blob
149
 
 
150
 
 
151
 
def inventory_to_tree_and_blobs(repo, mapping, revision_id):
152
 
    from dulwich.objects import Tree
153
 
    from bzrlib.inventory import InventoryDirectory, InventoryFile
154
 
    import stat
155
 
    stack = []
156
 
    cur = ""
157
 
    tree = Tree()
158
 
 
159
 
    inv = repo.get_inventory(revision_id)
160
 
 
161
 
    # stack contains the set of trees that we haven't 
162
 
    # finished constructing
163
 
    for path, entry in inv.iter_entries():
164
 
        while stack and not path.startswith(cur):
165
 
            tree.serialize()
166
 
            sha = tree.id
167
 
            yield sha, tree, cur
168
 
            t = (stat.S_IFDIR, urlutils.basename(cur).encode('UTF-8'), sha)
169
 
            cur, tree = stack.pop()
170
 
            tree.add(*t)
171
 
 
172
 
        if type(entry) == InventoryDirectory:
173
 
            stack.append((cur, tree))
174
 
            cur = path
175
 
            tree = Tree()
176
 
 
177
 
        if type(entry) == InventoryFile:
178
 
            #FIXME: We can make potentially make this Lazy to avoid shaing lots of stuff
179
 
            # and having all these objects in memory at once
180
 
            text = repo.texts.get_record_stream([(entry.file_id, entry.revision)], 'unordered', True).next().get_bytes_as('fulltext')
181
 
            blob = text_to_blob(text)
182
 
            sha = blob.id
183
 
            yield sha, blob, path
184
 
 
185
 
            name = urlutils.basename(path).encode("utf-8")
186
 
            mode = stat.S_IFREG | 0644
187
 
            if entry.executable:
188
 
                mode |= 0111
189
 
            tree.add(mode, name, sha)
190
 
 
191
 
    while len(stack) > 1:
192
 
        tree.serialize()
193
 
        sha = tree.id
194
 
        yield sha, tree, cur
195
 
        t = (stat.S_IFDIR, urlutils.basename(cur).encode('UTF-8'), sha)
196
 
        cur, tree = stack.pop()
197
 
        tree.add(*t)
198
 
 
199
 
    tree.serialize()
200
 
    yield tree.id, tree, cur
201
 
 
202
 
 
203
 
def revision_to_commit(rev, tree_sha, parent_lookup):
204
 
    """Turn a Bazaar revision in to a Git commit
205
 
 
206
 
    :param tree_sha: Tree sha for the commit
207
 
    :param parent_lookup: Function for looking up the GIT sha equiv of a bzr revision
208
 
    :return dulwich.objects.Commit represent the revision:
209
 
    """
210
 
    from dulwich.objects import Commit
211
 
    commit = Commit()
212
 
    commit._tree = tree_sha
213
 
    for p in rev.parent_ids:
214
 
        git_p = parent_lookup(p)
215
 
        if git_p is not None:
216
 
            assert len(git_p) == 40, "unexpected length for %r" % git_p
217
 
            commit._parents.append(git_p)
218
 
    commit._message = rev.message.encode("utf-8")
219
 
    commit._committer = rev.committer.encode("utf-8")
220
 
    commit._author = rev.get_apparent_authors()[0].encode("utf-8")
221
 
    commit._commit_time = long(rev.timestamp)
222
 
    commit.serialize()
223
 
    return commit
 
79
default_mapping = BzrGitMappingExperimental()