/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Ā upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
from bzrlib import osutils, urlutils
 
17
from bzrlib import osutils, ui, urlutils
18
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
from bzrlib.tsort import topo_sort
22
23
 
23
24
from bzrlib.plugins.git import git
24
 
from bzrlib.plugins.git.repository import LocalGitRepository, GitRepository, GitFormat
 
25
from bzrlib.plugins.git.repository import (
 
26
        LocalGitRepository, 
 
27
        GitRepository, 
 
28
        GitFormat,
 
29
        )
25
30
from bzrlib.plugins.git.remote import RemoteGitRepository
26
31
 
 
32
from dulwich.client import SimpleFetchGraphWalker
27
33
from dulwich.objects import Commit
28
34
 
29
35
from cStringIO import StringIO
44
50
 
45
51
    def remove(self, revid):
46
52
        self.done.add(revid)
47
 
        if ref in self.heads:
 
53
        if revid in self.heads:
48
54
            self.heads.remove(revid)
49
55
        if revid in self.parents:
50
56
            for p in self.parents[revid]:
64
70
        return None
65
71
 
66
72
 
67
 
def import_git_blob(repo, mapping, path, blob, inv):
 
73
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, executable):
68
74
    """Import a git blob object into a bzr repository.
69
75
 
70
76
    :param repo: bzr repository
72
78
    :param blob: A git blob
73
79
    """
74
80
    file_id = mapping.generate_file_id(path)
75
 
    repo.texts.add_lines((file_id, blob.id),
76
 
        [], #FIXME 
 
81
    text_revision = inv.revision_id
 
82
    repo.texts.add_lines((file_id, text_revision),
 
83
        [(file_id, p[file_id].revision) for p in parent_invs if file_id in p],
77
84
        osutils.split_lines(blob.data))
78
85
    ie = inv.add_path(path, "file", file_id)
79
 
 
80
 
 
81
 
def import_git_tree(repo, mapping, path, tree, inv, lookup_object):
 
86
    ie.revision = text_revision
 
87
    ie.text_size = len(blob.data)
 
88
    ie.text_sha1 = osutils.sha_string(blob.data)
 
89
    ie.executable = executable
 
90
 
 
91
 
 
92
def import_git_tree(repo, mapping, path, tree, inv, parent_invs, lookup_object):
82
93
    """Import a git tree object into a bzr repository.
83
94
 
84
95
    :param repo: A Bzr repository object
87
98
    :param inv: Inventory object
88
99
    """
89
100
    file_id = mapping.generate_file_id(path)
90
 
    repo.texts.add_lines((file_id, tree.id),
91
 
        [], #FIXME 
 
101
    text_revision = inv.revision_id
 
102
    repo.texts.add_lines((file_id, text_revision),
 
103
        [(file_id, p[file_id].revision) for p in parent_invs if file_id in p],
92
104
        [])
93
 
    inv.add_path(path, "directory", file_id)
 
105
    ie = inv.add_path(path, "directory", file_id)
 
106
    ie.revision = text_revision
94
107
    for mode, name, hexsha in tree.entries():
95
108
        entry_kind = (mode & 0700000) / 0100000
96
109
        basename = name.decode("utf-8")
100
113
            child_path = urlutils.join(path, name)
101
114
        if entry_kind == 0:
102
115
            tree = lookup_object(hexsha)
103
 
            import_git_tree(repo, mapping, child_path, tree, inv, lookup_object)
 
116
            import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, lookup_object)
104
117
        elif entry_kind == 1:
105
118
            blob = lookup_object(hexsha)
106
 
            import_git_blob(repo, mapping, child_path, blob, inv)
 
119
            fs_mode = mode & 0777
 
120
            import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, bool(fs_mode & 0111))
107
121
        else:
108
122
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
109
123
 
110
124
 
111
 
def import_git_objects(repo, mapping, object_iter):
 
125
def import_git_objects(repo, mapping, num_objects, object_iter, pb=None):
112
126
    """Import a set of git objects into a bzr repository.
113
127
 
114
128
    :param repo: Bazaar repository
115
129
    :param mapping: Mapping to use
 
130
    :param num_objects: Number of objects.
116
131
    :param object_iter: Iterator over Git objects.
117
132
    """
118
133
    # TODO: a more (memory-)efficient implementation of this
119
134
    objects = {}
120
 
    for o in object_iter:
 
135
    for i, o in enumerate(object_iter):
 
136
        if pb is not None:
 
137
            pb.update("fetching objects", i, num_objects) 
121
138
        objects[o.id] = o
 
139
    graph = []
122
140
    root_trees = {}
 
141
    revisions = {}
123
142
    # Find and convert commit objects
124
143
    for o in objects.itervalues():
125
144
        if isinstance(o, Commit):
126
145
            rev = mapping.import_commit(o)
127
 
            root_trees[rev] = objects[o.tree]
 
146
            root_trees[rev.revision_id] = objects[o.tree]
 
147
            revisions[rev.revision_id] = rev
 
148
            graph.append((rev.revision_id, rev.parent_ids))
 
149
    # Order the revisions
128
150
    # Create the inventory objects
129
 
    for rev, root_tree in root_trees.iteritems():
 
151
    for i, revid in enumerate(topo_sort(graph)):
 
152
        if pb is not None:
 
153
            pb.update("fetching revisions", i, len(graph))
 
154
        root_tree = root_trees[revid]
 
155
        rev = revisions[revid]
130
156
        # We have to do this here, since we have to walk the tree and 
131
157
        # we need to make sure to import the blobs / trees with the riht 
132
158
        # path; this may involve adding them more than once.
136
162
            if sha in objects:
137
163
                return objects[sha]
138
164
            return reconstruct_git_object(repo, mapping, sha)
139
 
        import_git_tree(repo, mapping, "", root_tree, inv, lookup_object)
 
165
        parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
 
166
        import_git_tree(repo, mapping, "", root_tree, inv, parent_invs, 
 
167
            lookup_object)
140
168
        repo.add_revision(rev.revision_id, rev, inv)
141
169
 
142
170
 
159
187
    raise KeyError("No such object %s" % sha)
160
188
 
161
189
 
162
 
class InterGitRepository(InterRepository):
 
190
class InterGitNonGitRepository(InterRepository):
163
191
 
164
192
    _matching_repo_format = GitFormat()
165
193
 
176
204
        if mapping is None:
177
205
            mapping = self.source.get_mapping()
178
206
        def progress(text):
179
 
            if pb is not None:
180
 
                pb.note("git: %s" % text)
181
 
            else:
182
 
                info("git: %s" % text)
 
207
            pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
183
208
        def determine_wants(heads):
184
209
            if revision_id is None:
185
210
                ret = heads.values()
187
212
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
188
213
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
189
214
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
190
 
        self.target.lock_write()
 
215
        create_pb = None
 
216
        if pb is None:
 
217
            create_pb = pb = ui.ui_factory.nested_progress_bar()
191
218
        try:
192
 
            self.target.start_write_group()
 
219
            self.target.lock_write()
193
220
            try:
194
 
                import_git_objects(self.target, mapping,
195
 
                    iter(self.source.fetch_objects(determine_wants, graph_walker, 
196
 
                        progress)))
 
221
                self.target.start_write_group()
 
222
                try:
 
223
                    (num_objects, objects_iter) = \
 
224
                            self.source.fetch_objects(determine_wants, 
 
225
                                graph_walker, progress)
 
226
                    import_git_objects(self.target, mapping, num_objects, 
 
227
                                       objects_iter, pb)
 
228
                finally:
 
229
                    self.target.commit_write_group()
197
230
            finally:
198
 
                self.target.commit_write_group()
 
231
                self.target.unlock()
199
232
        finally:
200
 
            self.target.unlock()
 
233
            if create_pb:
 
234
                create_pb.finished()
201
235
 
202
236
    @staticmethod
203
237
    def is_compatible(source, target):
204
238
        """Be compatible with GitRepository."""
205
239
        # FIXME: Also check target uses VersionedFile
206
 
        return (isinstance(source, LocalGitRepository) and 
207
 
                target.supports_rich_root())
 
240
        return (isinstance(source, GitRepository) and 
 
241
                target.supports_rich_root() and
 
242
                not isinstance(target, GitRepository))
 
243
 
 
244
 
 
245
class InterGitRepository(InterRepository):
 
246
 
 
247
    _matching_repo_format = GitFormat()
 
248
 
 
249
    @staticmethod
 
250
    def _get_repo_format_to_test():
 
251
        return None
 
252
 
 
253
    def copy_content(self, revision_id=None, pb=None):
 
254
        """See InterRepository.copy_content."""
 
255
        self.fetch(revision_id, pb, find_ghosts=False)
 
256
 
 
257
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
 
258
              mapping=None):
 
259
        if mapping is None:
 
260
            mapping = self.source.get_mapping()
 
261
        def progress(text):
 
262
            info("git: %s", text)
 
263
        r = self.target._git
 
264
        if revision_id is None:
 
265
            determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
 
266
        else:
 
267
            args = [mapping.revision_id_bzr_to_foreign(revision_id)]
 
268
            determine_wants = lambda x: [y for y in args if not y in r.object_store]
 
269
 
 
270
        graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
 
271
        f, commit = r.object_store.add_pack()
 
272
        try:
 
273
            self.source._git.fetch_pack(path, determine_wants, graphwalker, f.write, progress)
 
274
            f.close()
 
275
            commit()
 
276
        except:
 
277
            f.close()
 
278
            raise
 
279
 
 
280
    @staticmethod
 
281
    def is_compatible(source, target):
 
282
        """Be compatible with GitRepository."""
 
283
        return (isinstance(source, GitRepository) and 
 
284
                isinstance(target, GitRepository))