/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 fetch.py

Merge new bzr-foreign.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
from bzrlib import osutils, ui, urlutils
18
 
from bzrlib.errors import InvalidRevisionId, NoSuchRevision
 
18
from bzrlib.errors import InvalidRevisionId
19
19
from bzrlib.inventory import Inventory
20
20
from bzrlib.repository import InterRepository
21
21
from bzrlib.trace import info
22
22
from bzrlib.tsort import topo_sort
23
23
 
 
24
from bzrlib.plugins.git import git
24
25
from bzrlib.plugins.git.repository import (
25
26
        LocalGitRepository, 
26
27
        GitRepository, 
27
28
        GitFormat,
28
29
        )
29
 
from bzrlib.plugins.git.converter import GitObjectConverter
30
30
from bzrlib.plugins.git.remote import RemoteGitRepository
31
31
 
32
 
import dulwich as git
33
32
from dulwich.client import SimpleFetchGraphWalker
34
33
from dulwich.objects import Commit
35
34
 
37
36
 
38
37
 
39
38
class BzrFetchGraphWalker(object):
40
 
    """GraphWalker implementation that uses a Bazaar repository."""
41
39
 
42
40
    def __init__(self, repository, mapping):
43
41
        self.repository = repository
46
44
        self.heads = set(repository.all_revision_ids())
47
45
        self.parents = {}
48
46
 
49
 
    def __iter__(self):
50
 
        return iter(self.next, None)
51
 
 
52
47
    def ack(self, sha):
53
48
        revid = self.mapping.revision_id_foreign_to_bzr(sha)
54
49
        self.remove(revid)
69
64
            self.heads.update([p for p in ps if not p in self.done])
70
65
            try:
71
66
                self.done.add(ret)
72
 
                return self.mapping.revision_id_bzr_to_foreign(ret)[0]
 
67
                return self.mapping.revision_id_bzr_to_foreign(ret)
73
68
            except InvalidRevisionId:
74
69
                pass
75
70
        return None
76
71
 
77
72
 
78
 
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, gitmap, executable):
 
73
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, executable):
79
74
    """Import a git blob object into a bzr repository.
80
75
 
81
76
    :param repo: bzr repository
92
87
    ie.text_size = len(blob.data)
93
88
    ie.text_sha1 = osutils.sha_string(blob.data)
94
89
    ie.executable = executable
95
 
    gitmap._idmap.add_entry(blob.sha().hexdigest(), "blob", (ie.file_id, ie.revision))
96
 
 
97
 
 
98
 
def import_git_tree(repo, mapping, path, tree, inv, parent_invs, 
99
 
                    gitmap, lookup_object):
 
90
 
 
91
 
 
92
def import_git_tree(repo, mapping, path, tree, inv, parent_invs, lookup_object):
100
93
    """Import a git tree object into a bzr repository.
101
94
 
102
95
    :param repo: A Bzr repository object
111
104
        [])
112
105
    ie = inv.add_path(path, "directory", file_id)
113
106
    ie.revision = text_revision
114
 
    gitmap._idmap.add_entry(tree.sha().hexdigest(), "tree", (file_id, text_revision))
115
107
    for mode, name, hexsha in tree.entries():
116
108
        entry_kind = (mode & 0700000) / 0100000
117
109
        basename = name.decode("utf-8")
121
113
            child_path = urlutils.join(path, name)
122
114
        if entry_kind == 0:
123
115
            tree = lookup_object(hexsha)
124
 
            import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, gitmap, lookup_object)
 
116
            import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, lookup_object)
125
117
        elif entry_kind == 1:
126
118
            blob = lookup_object(hexsha)
127
119
            fs_mode = mode & 0777
128
 
            import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, gitmap, bool(fs_mode & 0111))
 
120
            import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, bool(fs_mode & 0111))
129
121
        else:
130
122
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
131
123
 
132
124
 
133
 
def import_git_objects(repo, mapping, object_iter, target_git_object_retriever, 
134
 
        pb=None):
 
125
def import_git_objects(repo, mapping, object_iter, pb=None):
135
126
    """Import a set of git objects into a bzr repository.
136
127
 
137
128
    :param repo: Bazaar repository
139
130
    :param object_iter: Iterator over Git objects.
140
131
    """
141
132
    # TODO: a more (memory-)efficient implementation of this
 
133
    objects = {}
 
134
    for i, o in enumerate(object_iter):
 
135
        if pb is not None:
 
136
            pb.update("fetching objects", i) 
 
137
        objects[o.id] = o
142
138
    graph = []
143
139
    root_trees = {}
144
140
    revisions = {}
145
141
    # Find and convert commit objects
146
 
    for o in object_iter.iterobjects():
 
142
    for o in objects.itervalues():
147
143
        if isinstance(o, Commit):
148
144
            rev = mapping.import_commit(o)
149
 
            root_trees[rev.revision_id] = object_iter[o.tree]
 
145
            root_trees[rev.revision_id] = objects[o.tree]
150
146
            revisions[rev.revision_id] = rev
151
147
            graph.append((rev.revision_id, rev.parent_ids))
152
 
            target_git_object_retriever._idmap.add_entry(o.sha().hexdigest(), "commit", (rev.revision_id, o._tree))
153
148
    # Order the revisions
154
149
    # Create the inventory objects
155
150
    for i, revid in enumerate(topo_sort(graph)):
163
158
        inv = Inventory()
164
159
        inv.revision_id = rev.revision_id
165
160
        def lookup_object(sha):
166
 
            if sha in object_iter:
167
 
                return object_iter[sha]
168
 
            return target_git_object_retriever[sha]
 
161
            if sha in objects:
 
162
                return objects[sha]
 
163
            return reconstruct_git_object(repo, mapping, sha)
169
164
        parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
170
165
        import_git_tree(repo, mapping, "", root_tree, inv, parent_invs, 
171
 
            target_git_object_retriever, lookup_object)
 
166
            lookup_object)
172
167
        repo.add_revision(rev.revision_id, rev, inv)
173
168
 
174
169
 
 
170
def reconstruct_git_commit(repo, rev):
 
171
    raise NotImplementedError(self.reconstruct_git_commit)
 
172
 
 
173
 
 
174
def reconstruct_git_object(repo, mapping, sha):
 
175
    # Commit
 
176
    revid = mapping.revision_id_foreign_to_bzr(sha)
 
177
    try:
 
178
        rev = repo.get_revision(revid)
 
179
    except NoSuchRevision:
 
180
        pass
 
181
    else:
 
182
        return reconstruct_git_commit(rev)
 
183
 
 
184
    # TODO: Tree
 
185
    # TODO: Blob
 
186
    raise KeyError("No such object %s" % sha)
 
187
 
 
188
 
175
189
class InterGitNonGitRepository(InterRepository):
176
190
 
177
191
    _matching_repo_format = GitFormat()
184
198
        """See InterRepository.copy_content."""
185
199
        self.fetch(revision_id, pb, find_ghosts=False)
186
200
 
187
 
    def fetch_objects(self, determine_wants, mapping, pb=None):
 
201
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
 
202
              mapping=None):
 
203
        if mapping is None:
 
204
            mapping = self.source.get_mapping()
188
205
        def progress(text):
189
 
            pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
 
206
            pb.note("git: %s", text)
 
207
        def determine_wants(heads):
 
208
            if revision_id is None:
 
209
                ret = heads.values()
 
210
            else:
 
211
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
 
212
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
190
213
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
191
214
        create_pb = None
192
215
        if pb is None:
193
216
            create_pb = pb = ui.ui_factory.nested_progress_bar()
194
 
        target_git_object_retriever = GitObjectConverter(self.target, mapping)
195
 
        
196
217
        try:
197
218
            self.target.lock_write()
198
219
            try:
199
220
                self.target.start_write_group()
200
221
                try:
201
 
                    objects_iter = self.source.fetch_objects(determine_wants, 
202
 
                                graph_walker, 
203
 
                                target_git_object_retriever.__getitem__, 
204
 
                                progress)
205
 
                    import_git_objects(self.target, mapping, objects_iter, 
206
 
                            target_git_object_retriever, pb)
 
222
                    import_git_objects(self.target, mapping,
 
223
                        iter(self.source.fetch_objects(determine_wants, graph_walker, 
 
224
                            progress)), pb)
207
225
                finally:
208
226
                    self.target.commit_write_group()
209
227
            finally:
212
230
            if create_pb:
213
231
                create_pb.finished()
214
232
 
215
 
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
216
 
              mapping=None):
217
 
        if mapping is None:
218
 
            mapping = self.source.get_mapping()
219
 
        def determine_wants(heads):
220
 
            if revision_id is None:
221
 
                ret = heads.values()
222
 
            else:
223
 
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
224
 
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
225
 
        return self.fetch_objects(determine_wants, mapping, pb)
226
 
 
227
233
    @staticmethod
228
234
    def is_compatible(source, target):
229
235
        """Be compatible with GitRepository."""
255
261
        if revision_id is None:
256
262
            determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
257
263
        else:
258
 
            args = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
 
264
            args = [mapping.revision_id_bzr_to_foreign(revision_id)]
259
265
            determine_wants = lambda x: [y for y in args if not y in r.object_store]
260
266
 
261
267
        graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)