/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
 
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):
 
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
 
    inv.add_path(path, "file", file_id)
79
 
 
80
 
 
81
 
def import_git_tree(repo, mapping, path, tree, inv, lookup_object):
 
85
    ie = inv.add_path(path, "file", file_id)
 
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")
99
112
        else:
100
113
            child_path = urlutils.join(path, name)
101
114
        if entry_kind == 0:
102
 
            import_git_tree(repo, mapping, child_path, lookup_object, inv)
 
115
            tree = lookup_object(hexsha)
 
116
            import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, lookup_object)
103
117
        elif entry_kind == 1:
104
 
            import_git_blob(repo, mapping, child_path, lookup_object, inv)
 
118
            blob = lookup_object(hexsha)
 
119
            fs_mode = mode & 0777
 
120
            import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, bool(fs_mode & 0111))
105
121
        else:
106
122
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
107
123
 
108
124
 
109
 
def import_git_objects(repo, mapping, object_iter):
 
125
def import_git_objects(repo, mapping, num_objects, object_iter, pb=None):
110
126
    """Import a set of git objects into a bzr repository.
111
127
 
112
128
    :param repo: Bazaar repository
113
129
    :param mapping: Mapping to use
 
130
    :param num_objects: Number of objects.
114
131
    :param object_iter: Iterator over Git objects.
115
132
    """
116
133
    # TODO: a more (memory-)efficient implementation of this
117
134
    objects = {}
118
 
    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) 
119
138
        objects[o.id] = o
 
139
    graph = []
120
140
    root_trees = {}
 
141
    revisions = {}
121
142
    # Find and convert commit objects
122
 
    for o in objects.iterkeys():
 
143
    for o in objects.itervalues():
123
144
        if isinstance(o, Commit):
124
145
            rev = mapping.import_commit(o)
125
 
            root_trees[rev] = objects[o.tree_sha]
 
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
126
150
    # Create the inventory objects
127
 
    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]
128
156
        # We have to do this here, since we have to walk the tree and 
129
157
        # we need to make sure to import the blobs / trees with the riht 
130
158
        # path; this may involve adding them more than once.
131
159
        inv = Inventory()
 
160
        inv.revision_id = rev.revision_id
132
161
        def lookup_object(sha):
133
162
            if sha in objects:
134
163
                return objects[sha]
135
164
            return reconstruct_git_object(repo, mapping, sha)
136
 
        import_git_tree(repo, mapping, "", 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)
137
168
        repo.add_revision(rev.revision_id, rev, inv)
138
169
 
139
170
 
156
187
    raise KeyError("No such object %s" % sha)
157
188
 
158
189
 
159
 
class InterGitRepository(InterRepository):
 
190
class InterGitNonGitRepository(InterRepository):
160
191
 
161
192
    _matching_repo_format = GitFormat()
162
193
 
173
204
        if mapping is None:
174
205
            mapping = self.source.get_mapping()
175
206
        def progress(text):
176
 
            if pb is not None:
177
 
                pb.note("git: %s" % text)
178
 
            else:
179
 
                info("git: %s" % text)
 
207
            pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
180
208
        def determine_wants(heads):
181
209
            if revision_id is None:
182
210
                ret = heads.values()
184
212
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
185
213
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
186
214
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
187
 
        self.target.lock_write()
 
215
        create_pb = None
 
216
        if pb is None:
 
217
            create_pb = pb = ui.ui_factory.nested_progress_bar()
188
218
        try:
189
 
            import_git_objects(self.target, mapping,
190
 
                self.source.fetch_objects(determine_wants, graph_walker, 
191
 
                    progress))
 
219
            self.target.lock_write()
 
220
            try:
 
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()
 
230
            finally:
 
231
                self.target.unlock()
192
232
        finally:
193
 
            self.target.unlock()
 
233
            if create_pb:
 
234
                create_pb.finished()
194
235
 
195
236
    @staticmethod
196
237
    def is_compatible(source, target):
197
238
        """Be compatible with GitRepository."""
198
239
        # FIXME: Also check target uses VersionedFile
199
 
        return (isinstance(source, LocalGitRepository) and 
200
 
                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))