/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 tests, split up InterGitNonGitRepository.

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