/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

Add FOSDEM roundtripping notes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
from bzrlib.trace import info
22
22
from bzrlib.tsort import topo_sort
23
23
 
24
 
from bzrlib.plugins.git import git
25
24
from bzrlib.plugins.git.repository import (
26
25
        LocalGitRepository, 
27
26
        GitRepository, 
29
28
        )
30
29
from bzrlib.plugins.git.remote import RemoteGitRepository
31
30
 
 
31
import dulwich as git
 
32
from dulwich.client import SimpleFetchGraphWalker
32
33
from dulwich.objects import Commit
33
34
 
34
35
from cStringIO import StringIO
35
36
 
36
37
 
37
38
class BzrFetchGraphWalker(object):
 
39
    """GraphWalker implementation that uses a Bazaar repository."""
38
40
 
39
41
    def __init__(self, repository, mapping):
40
42
        self.repository = repository
43
45
        self.heads = set(repository.all_revision_ids())
44
46
        self.parents = {}
45
47
 
 
48
    def __iter__(self):
 
49
        return iter(self.next, None)
 
50
 
46
51
    def ack(self, sha):
47
52
        revid = self.mapping.revision_id_foreign_to_bzr(sha)
48
53
        self.remove(revid)
49
54
 
50
55
    def remove(self, revid):
51
56
        self.done.add(revid)
52
 
        if ref in self.heads:
 
57
        if revid in self.heads:
53
58
            self.heads.remove(revid)
54
59
        if revid in self.parents:
55
60
            for p in self.parents[revid]:
63
68
            self.heads.update([p for p in ps if not p in self.done])
64
69
            try:
65
70
                self.done.add(ret)
66
 
                return self.mapping.revision_id_bzr_to_foreign(ret)
 
71
                return self.mapping.revision_id_bzr_to_foreign(ret)[0]
67
72
            except InvalidRevisionId:
68
73
                pass
69
74
        return None
129
134
    :param object_iter: Iterator over Git objects.
130
135
    """
131
136
    # TODO: a more (memory-)efficient implementation of this
132
 
    objects = {}
133
 
    for i, o in enumerate(object_iter):
134
 
        if pb is not None:
135
 
            pb.update("fetching objects", i) 
136
 
        objects[o.id] = o
137
137
    graph = []
138
138
    root_trees = {}
139
139
    revisions = {}
140
140
    # Find and convert commit objects
141
 
    for o in objects.itervalues():
 
141
    for o in object_iter.iterobjects():
142
142
        if isinstance(o, Commit):
143
143
            rev = mapping.import_commit(o)
144
 
            root_trees[rev.revision_id] = objects[o.tree]
 
144
            root_trees[rev.revision_id] = object_iter[o.tree]
145
145
            revisions[rev.revision_id] = rev
146
146
            graph.append((rev.revision_id, rev.parent_ids))
147
147
    # Order the revisions
157
157
        inv = Inventory()
158
158
        inv.revision_id = rev.revision_id
159
159
        def lookup_object(sha):
160
 
            if sha in objects:
161
 
                return objects[sha]
 
160
            if sha in object_iter:
 
161
                return object_iter[sha]
162
162
            return reconstruct_git_object(repo, mapping, sha)
163
163
        parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
164
 
        import_git_tree(repo, mapping, "", root_tree, inv, parent_invs, lookup_object)
 
164
        import_git_tree(repo, mapping, "", root_tree, inv, parent_invs, 
 
165
            lookup_object)
165
166
        repo.add_revision(rev.revision_id, rev, inv)
166
167
 
167
168
 
184
185
    raise KeyError("No such object %s" % sha)
185
186
 
186
187
 
187
 
class InterGitRepository(InterRepository):
 
188
class InterGitNonGitRepository(InterRepository):
188
189
 
189
190
    _matching_repo_format = GitFormat()
190
191
 
201
202
        if mapping is None:
202
203
            mapping = self.source.get_mapping()
203
204
        def progress(text):
204
 
            pb.note("git: %s", text)
 
205
            pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
205
206
        def determine_wants(heads):
206
207
            if revision_id is None:
207
208
                ret = heads.values()
208
209
            else:
209
 
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
 
210
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
210
211
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
211
212
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
212
213
        create_pb = None
217
218
            try:
218
219
                self.target.start_write_group()
219
220
                try:
220
 
                    import_git_objects(self.target, mapping,
221
 
                        iter(self.source.fetch_objects(determine_wants, graph_walker, 
222
 
                            progress)), pb)
 
221
                    objects_iter = self.source.fetch_objects(determine_wants, 
 
222
                                graph_walker, progress)
 
223
                    import_git_objects(self.target, mapping, objects_iter, pb)
223
224
                finally:
224
225
                    self.target.commit_write_group()
225
226
            finally:
233
234
        """Be compatible with GitRepository."""
234
235
        # FIXME: Also check target uses VersionedFile
235
236
        return (isinstance(source, GitRepository) and 
236
 
                target.supports_rich_root())
 
237
                target.supports_rich_root() and
 
238
                not isinstance(target, GitRepository))
 
239
 
 
240
 
 
241
class InterGitRepository(InterRepository):
 
242
 
 
243
    _matching_repo_format = GitFormat()
 
244
 
 
245
    @staticmethod
 
246
    def _get_repo_format_to_test():
 
247
        return None
 
248
 
 
249
    def copy_content(self, revision_id=None, pb=None):
 
250
        """See InterRepository.copy_content."""
 
251
        self.fetch(revision_id, pb, find_ghosts=False)
 
252
 
 
253
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
 
254
              mapping=None):
 
255
        if mapping is None:
 
256
            mapping = self.source.get_mapping()
 
257
        def progress(text):
 
258
            info("git: %s", text)
 
259
        r = self.target._git
 
260
        if revision_id is None:
 
261
            determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
 
262
        else:
 
263
            args = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
 
264
            determine_wants = lambda x: [y for y in args if not y in r.object_store]
 
265
 
 
266
        graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
 
267
        f, commit = r.object_store.add_pack()
 
268
        try:
 
269
            self.source._git.fetch_pack(path, determine_wants, graphwalker, f.write, progress)
 
270
            f.close()
 
271
            commit()
 
272
        except:
 
273
            f.close()
 
274
            raise
 
275
 
 
276
    @staticmethod
 
277
    def is_compatible(source, target):
 
278
        """Be compatible with GitRepository."""
 
279
        return (isinstance(source, GitRepository) and 
 
280
                isinstance(target, GitRepository))