/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

Fix branch cloning.

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
 
27
32
from dulwich.objects import Commit
64
69
        return None
65
70
 
66
71
 
67
 
def import_git_blob(repo, mapping, path, blob):
 
72
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, executable):
68
73
    """Import a git blob object into a bzr repository.
69
74
 
70
75
    :param repo: bzr repository
72
77
    :param blob: A git blob
73
78
    """
74
79
    file_id = mapping.generate_file_id(path)
75
 
    repo.texts.add_lines((file_id, blob.id),
76
 
        [], #FIXME 
 
80
    text_revision = inv.revision_id
 
81
    repo.texts.add_lines((file_id, text_revision),
 
82
        [(file_id, p[file_id].revision) for p in parent_invs if file_id in p],
77
83
        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):
 
84
    ie = inv.add_path(path, "file", file_id)
 
85
    ie.revision = text_revision
 
86
    ie.text_size = len(blob.data)
 
87
    ie.text_sha1 = osutils.sha_string(blob.data)
 
88
    ie.executable = executable
 
89
 
 
90
 
 
91
def import_git_tree(repo, mapping, path, tree, inv, parent_invs, lookup_object):
82
92
    """Import a git tree object into a bzr repository.
83
93
 
84
94
    :param repo: A Bzr repository object
87
97
    :param inv: Inventory object
88
98
    """
89
99
    file_id = mapping.generate_file_id(path)
90
 
    repo.texts.add_lines((file_id, tree.id),
91
 
        [], #FIXME 
 
100
    text_revision = inv.revision_id
 
101
    repo.texts.add_lines((file_id, text_revision),
 
102
        [(file_id, p[file_id].revision) for p in parent_invs if file_id in p],
92
103
        [])
93
 
    inv.add_path(path, "directory", file_id)
 
104
    ie = inv.add_path(path, "directory", file_id)
 
105
    ie.revision = text_revision
94
106
    for mode, name, hexsha in tree.entries():
95
107
        entry_kind = (mode & 0700000) / 0100000
96
108
        basename = name.decode("utf-8")
99
111
        else:
100
112
            child_path = urlutils.join(path, name)
101
113
        if entry_kind == 0:
102
 
            import_git_tree(repo, mapping, child_path, lookup_object, inv)
 
114
            tree = lookup_object(hexsha)
 
115
            import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, lookup_object)
103
116
        elif entry_kind == 1:
104
 
            import_git_blob(repo, mapping, child_path, lookup_object, inv)
 
117
            blob = lookup_object(hexsha)
 
118
            fs_mode = mode & 0777
 
119
            import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, bool(fs_mode & 0111))
105
120
        else:
106
121
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
107
122
 
108
123
 
109
 
def import_git_objects(repo, mapping, object_iter):
 
124
def import_git_objects(repo, mapping, object_iter, pb=None):
110
125
    """Import a set of git objects into a bzr repository.
111
126
 
112
127
    :param repo: Bazaar repository
115
130
    """
116
131
    # TODO: a more (memory-)efficient implementation of this
117
132
    objects = {}
118
 
    for o in object_iter:
 
133
    for i, o in enumerate(object_iter):
 
134
        if pb is not None:
 
135
            pb.update("fetching objects", i) 
119
136
        objects[o.id] = o
 
137
    graph = []
120
138
    root_trees = {}
 
139
    revisions = {}
121
140
    # Find and convert commit objects
122
 
    for o in objects.iterkeys():
 
141
    for o in objects.itervalues():
123
142
        if isinstance(o, Commit):
124
143
            rev = mapping.import_commit(o)
125
 
            root_trees[rev] = objects[o.tree_sha]
 
144
            root_trees[rev.revision_id] = objects[o.tree]
 
145
            revisions[rev.revision_id] = rev
 
146
            graph.append((rev.revision_id, rev.parent_ids))
 
147
    # Order the revisions
126
148
    # Create the inventory objects
127
 
    for rev, root_tree in root_trees.iteritems():
 
149
    for i, revid in enumerate(topo_sort(graph)):
 
150
        if pb is not None:
 
151
            pb.update("fetching revisions", i, len(graph))
 
152
        root_tree = root_trees[revid]
 
153
        rev = revisions[revid]
128
154
        # We have to do this here, since we have to walk the tree and 
129
155
        # we need to make sure to import the blobs / trees with the riht 
130
156
        # path; this may involve adding them more than once.
131
157
        inv = Inventory()
 
158
        inv.revision_id = rev.revision_id
132
159
        def lookup_object(sha):
133
160
            if sha in objects:
134
161
                return objects[sha]
135
162
            return reconstruct_git_object(repo, mapping, sha)
136
 
        import_git_tree(repo, mapping, "", tree, inv, lookup_object)
 
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)
137
165
        repo.add_revision(rev.revision_id, rev, inv)
138
166
 
139
167
 
173
201
        if mapping is None:
174
202
            mapping = self.source.get_mapping()
175
203
        def progress(text):
176
 
            if pb is not None:
177
 
                pb.note("git: %s" % text)
178
 
            else:
179
 
                info("git: %s" % text)
 
204
            pb.note("git: %s", text)
180
205
        def determine_wants(heads):
181
206
            if revision_id is None:
182
207
                ret = heads.values()
184
209
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
185
210
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
186
211
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
187
 
        self.target.lock_write()
 
212
        create_pb = None
 
213
        if pb is None:
 
214
            create_pb = pb = ui.ui_factory.nested_progress_bar()
188
215
        try:
189
 
            import_git_objects(self.target, mapping,
190
 
                self.source.fetch_objects(determine_wants, graph_walker, 
191
 
                    progress))
 
216
            self.target.lock_write()
 
217
            try:
 
218
                self.target.start_write_group()
 
219
                try:
 
220
                    import_git_objects(self.target, mapping,
 
221
                        iter(self.source.fetch_objects(determine_wants, graph_walker, 
 
222
                            progress)), pb)
 
223
                finally:
 
224
                    self.target.commit_write_group()
 
225
            finally:
 
226
                self.target.unlock()
192
227
        finally:
193
 
            self.target.unlock()
 
228
            if create_pb:
 
229
                create_pb.finished()
194
230
 
195
231
    @staticmethod
196
232
    def is_compatible(source, target):
197
233
        """Be compatible with GitRepository."""
198
234
        # FIXME: Also check target uses VersionedFile
199
 
        return (isinstance(source, LocalGitRepository) and 
 
235
        return (isinstance(source, GitRepository) and 
200
236
                target.supports_rich_root())