/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
1
# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
17
from cStringIO import StringIO
18
import dulwich as git
0.200.261 by Jelmer Vernooij
More formatting fixes.
19
from dulwich.client import (
20
    SimpleFetchGraphWalker,
21
    )
22
from dulwich.objects import (
23
    Commit,
24
    )
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
25
26
from bzrlib import (
27
    osutils,
0.200.261 by Jelmer Vernooij
More formatting fixes.
28
    trace,
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
29
    ui,
30
    urlutils,
31
    )
32
from bzrlib.errors import (
33
    InvalidRevisionId,
34
    NoSuchRevision,
35
    )
0.200.261 by Jelmer Vernooij
More formatting fixes.
36
from bzrlib.inventory import (
37
    Inventory,
38
    )
39
from bzrlib.repository import (
40
    InterRepository,
41
    )
0.200.158 by Jelmer Vernooij
fetch works \o/
42
from bzrlib.tsort import topo_sort
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
43
0.200.261 by Jelmer Vernooij
More formatting fixes.
44
from bzrlib.plugins.git.converter import (
45
    GitObjectConverter,
46
    )
0.200.169 by Jelmer Vernooij
Fix branch cloning.
47
from bzrlib.plugins.git.repository import (
0.200.261 by Jelmer Vernooij
More formatting fixes.
48
    LocalGitRepository, 
49
    GitRepository, 
50
    GitFormat,
51
    )
52
from bzrlib.plugins.git.remote import (
53
    RemoteGitRepository,
54
    )
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
55
56
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
57
class BzrFetchGraphWalker(object):
0.200.196 by Jelmer Vernooij
Add simple tests and docstrings for GraphWalker.
58
    """GraphWalker implementation that uses a Bazaar repository."""
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
59
60
    def __init__(self, repository, mapping):
61
        self.repository = repository
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
62
        self.mapping = mapping
63
        self.done = set()
64
        self.heads = set(repository.all_revision_ids())
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
65
        self.parents = {}
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
66
0.200.196 by Jelmer Vernooij
Add simple tests and docstrings for GraphWalker.
67
    def __iter__(self):
68
        return iter(self.next, None)
69
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
70
    def ack(self, sha):
71
        revid = self.mapping.revision_id_foreign_to_bzr(sha)
72
        self.remove(revid)
73
74
    def remove(self, revid):
75
        self.done.add(revid)
0.200.177 by Jelmer Vernooij
Add git-import command.
76
        if revid in self.heads:
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
77
            self.heads.remove(revid)
78
        if revid in self.parents:
79
            for p in self.parents[revid]:
80
                self.remove(p)
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
81
82
    def next(self):
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
83
        while self.heads:
84
            ret = self.heads.pop()
85
            ps = self.repository.get_parent_map([ret])[ret]
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
86
            self.parents[ret] = ps
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
87
            self.heads.update([p for p in ps if not p in self.done])
88
            try:
89
                self.done.add(ret)
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
90
                return self.mapping.revision_id_bzr_to_foreign(ret)[0]
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
91
            except InvalidRevisionId:
92
                pass
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
93
        return None
94
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
95
0.200.264 by Jelmer Vernooij
Add more tests.
96
def import_git_blob(texts, mapping, path, blob, inv, parent_invs, shagitmap,
0.200.261 by Jelmer Vernooij
More formatting fixes.
97
    executable):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
98
    """Import a git blob object into a bzr repository.
99
0.200.261 by Jelmer Vernooij
More formatting fixes.
100
    :param texts: VersionedFiles to add to
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
101
    :param path: Path in the tree
102
    :param blob: A git blob
0.200.286 by Jelmer Vernooij
Prevent creating repeated directory texts.
103
    :return: Inventory entry
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
104
    """
105
    file_id = mapping.generate_file_id(path)
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
106
    ie = inv.add_path(path, "file", file_id)
0.200.158 by Jelmer Vernooij
fetch works \o/
107
    ie.text_size = len(blob.data)
108
    ie.text_sha1 = osutils.sha_string(blob.data)
0.200.159 by Jelmer Vernooij
Fix branch tests.
109
    ie.executable = executable
0.200.283 by Jelmer Vernooij
Avoid storing repeated texts for blobs.
110
    # See if this is the same revision as one of the parents unchanged
111
    parent_keys = []
112
    for pinv in parent_invs:
0.200.285 by Jelmer Vernooij
Simplify blob import code.
113
        if not file_id in pinv:
114
            continue
115
        if pinv[file_id].text_sha1 == ie.text_sha1:
0.200.283 by Jelmer Vernooij
Avoid storing repeated texts for blobs.
116
            ie.revision = pinv[file_id].revision
0.200.286 by Jelmer Vernooij
Prevent creating repeated directory texts.
117
            return ie
118
        parent_keys.append((file_id, pinv[file_id].revision))
0.200.283 by Jelmer Vernooij
Avoid storing repeated texts for blobs.
119
    ie.revision = inv.revision_id
120
    assert file_id is not None
121
    assert ie.revision is not None
0.200.285 by Jelmer Vernooij
Simplify blob import code.
122
    texts.add_lines((file_id, ie.revision), parent_keys,
0.200.283 by Jelmer Vernooij
Avoid storing repeated texts for blobs.
123
        osutils.split_lines(blob.data))
0.200.264 by Jelmer Vernooij
Add more tests.
124
    shagitmap.add_entry(blob.sha().hexdigest(), "blob",
0.200.261 by Jelmer Vernooij
More formatting fixes.
125
        (ie.file_id, ie.revision))
0.200.286 by Jelmer Vernooij
Prevent creating repeated directory texts.
126
    return ie
0.200.261 by Jelmer Vernooij
More formatting fixes.
127
128
0.200.264 by Jelmer Vernooij
Add more tests.
129
def import_git_tree(texts, mapping, path, tree, inv, parent_invs, shagitmap,
0.200.261 by Jelmer Vernooij
More formatting fixes.
130
    lookup_object):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
131
    """Import a git tree object into a bzr repository.
132
0.200.261 by Jelmer Vernooij
More formatting fixes.
133
    :param texts: VersionedFiles object to add to
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
134
    :param path: Path in the tree
135
    :param tree: A git tree object
136
    :param inv: Inventory object
137
    """
138
    file_id = mapping.generate_file_id(path)
0.200.158 by Jelmer Vernooij
fetch works \o/
139
    ie = inv.add_path(path, "directory", file_id)
0.200.287 by Jelmer Vernooij
Skip tree sha's already in the git sha map.
140
    parent_keys = []
141
    for pinv in parent_invs:
142
        if not file_id in pinv:
143
            continue
144
        try:
145
            if shagitmap.lookup_tree(path, pinv.revision_id) == tree.id:
146
                ie.revision = pinv[file_id].revision
147
                return
148
        except KeyError:
149
            pass
150
        parent_keys.append((file_id, pinv[file_id].revision))
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
151
    for mode, name, hexsha in tree.entries():
152
        entry_kind = (mode & 0700000) / 0100000
153
        basename = name.decode("utf-8")
154
        if path == "":
155
            child_path = name
156
        else:
157
            child_path = urlutils.join(path, name)
0.200.264 by Jelmer Vernooij
Add more tests.
158
        obj = lookup_object(hexsha)
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
159
        if entry_kind == 0:
0.200.264 by Jelmer Vernooij
Add more tests.
160
            import_git_tree(texts, mapping, child_path, obj, inv, parent_invs,
161
                shagitmap, lookup_object)
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
162
        elif entry_kind == 1:
0.200.159 by Jelmer Vernooij
Fix branch tests.
163
            fs_mode = mode & 0777
0.200.264 by Jelmer Vernooij
Add more tests.
164
            import_git_blob(texts, mapping, child_path, obj, inv, parent_invs,
165
                shagitmap, bool(fs_mode & 0111))
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
166
        else:
167
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
0.200.286 by Jelmer Vernooij
Prevent creating repeated directory texts.
168
    ie.revision = inv.revision_id
169
    texts.add_lines((file_id, ie.revision), parent_keys, [])
170
    shagitmap.add_entry(tree.id, "tree", (file_id, ie.revision))
171
    return ie
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
172
173
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
174
def import_git_objects(repo, mapping, object_iter, target_git_object_retriever, 
175
        pb=None):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
176
    """Import a set of git objects into a bzr repository.
177
178
    :param repo: Bazaar repository
179
    :param mapping: Mapping to use
180
    :param object_iter: Iterator over Git objects.
181
    """
182
    # TODO: a more (memory-)efficient implementation of this
0.200.158 by Jelmer Vernooij
fetch works \o/
183
    graph = []
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
184
    root_trees = {}
0.200.158 by Jelmer Vernooij
fetch works \o/
185
    revisions = {}
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
186
    # Find and convert commit objects
0.200.217 by Jelmer Vernooij
Avoid reading everything into memory when accessing objects.
187
    for o in object_iter.iterobjects():
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
188
        if isinstance(o, Commit):
189
            rev = mapping.import_commit(o)
0.200.217 by Jelmer Vernooij
Avoid reading everything into memory when accessing objects.
190
            root_trees[rev.revision_id] = object_iter[o.tree]
0.200.158 by Jelmer Vernooij
fetch works \o/
191
            revisions[rev.revision_id] = rev
192
            graph.append((rev.revision_id, rev.parent_ids))
0.200.261 by Jelmer Vernooij
More formatting fixes.
193
            target_git_object_retriever._idmap.add_entry(o.sha().hexdigest(),
194
                "commit", (rev.revision_id, o._tree))
0.200.158 by Jelmer Vernooij
fetch works \o/
195
    # Order the revisions
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
196
    # Create the inventory objects
0.200.158 by Jelmer Vernooij
fetch works \o/
197
    for i, revid in enumerate(topo_sort(graph)):
198
        if pb is not None:
199
            pb.update("fetching revisions", i, len(graph))
200
        root_tree = root_trees[revid]
201
        rev = revisions[revid]
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
202
        # We have to do this here, since we have to walk the tree and 
203
        # we need to make sure to import the blobs / trees with the riht 
204
        # path; this may involve adding them more than once.
205
        inv = Inventory()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
206
        inv.revision_id = rev.revision_id
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
207
        def lookup_object(sha):
0.200.217 by Jelmer Vernooij
Avoid reading everything into memory when accessing objects.
208
            if sha in object_iter:
209
                return object_iter[sha]
0.200.230 by Jelmer Vernooij
Implement sha cache.
210
            return target_git_object_retriever[sha]
0.200.158 by Jelmer Vernooij
fetch works \o/
211
        parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
0.200.261 by Jelmer Vernooij
More formatting fixes.
212
        import_git_tree(repo.texts, mapping, "", root_tree, inv, parent_invs, 
0.200.264 by Jelmer Vernooij
Add more tests.
213
            target_git_object_retriever._idmap, lookup_object)
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
214
        repo.add_revision(rev.revision_id, rev, inv)
0.200.272 by Jelmer Vernooij
Actually store idmap.
215
    target_git_object_retriever._idmap.commit()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
216
217
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
218
class InterGitNonGitRepository(InterRepository):
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
219
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
220
    _matching_repo_format = GitFormat()
221
222
    @staticmethod
223
    def _get_repo_format_to_test():
224
        return None
225
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
226
    def copy_content(self, revision_id=None, pb=None):
227
        """See InterRepository.copy_content."""
228
        self.fetch(revision_id, pb, find_ghosts=False)
229
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
230
    def fetch_objects(self, determine_wants, mapping, pb=None):
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
231
        def progress(text):
0.217.41 by John Carr
Don't fill screen with muttering
232
            pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
233
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
234
        create_pb = None
235
        if pb is None:
236
            create_pb = pb = ui.ui_factory.nested_progress_bar()
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
237
        target_git_object_retriever = GitObjectConverter(self.target, mapping)
238
        
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
239
        try:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
240
            self.target.lock_write()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
241
            try:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
242
                self.target.start_write_group()
243
                try:
0.200.216 by Jelmer Vernooij
Use ObjectIterator interface.
244
                    objects_iter = self.source.fetch_objects(determine_wants, 
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
245
                                graph_walker, 
246
                                target_git_object_retriever.__getitem__, 
247
                                progress)
248
                    import_git_objects(self.target, mapping, objects_iter, 
249
                            target_git_object_retriever, pb)
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
250
                finally:
251
                    self.target.commit_write_group()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
252
            finally:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
253
                self.target.unlock()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
254
        finally:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
255
            if create_pb:
256
                create_pb.finished()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
257
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
258
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
259
              mapping=None, fetch_spec=None):
0.200.247 by Jelmer Vernooij
Fix git-import.
260
        self.fetch_refs(revision_id=revision_id, pb=pb, find_ghosts=find_ghosts,
261
                mapping=mapping, fetch_spec=fetch_spec)
262
263
    def fetch_refs(self, revision_id=None, pb=None, find_ghosts=False, 
264
              mapping=None, fetch_spec=None):
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
265
        if mapping is None:
266
            mapping = self.source.get_mapping()
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
267
        if revision_id is not None:
268
            interesting_heads = [revision_id]
269
        elif fetch_spec is not None:
270
            interesting_heads = fetch_spec.heads
271
        else:
272
            interesting_heads = None
0.200.247 by Jelmer Vernooij
Fix git-import.
273
        self._refs = {}
274
        def determine_wants(refs):
275
            self._refs = refs
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
276
            if interesting_heads is None:
0.200.247 by Jelmer Vernooij
Fix git-import.
277
                ret = [sha for (ref, sha) in refs.iteritems() if not ref.endswith("^{}")]
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
278
            else:
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
279
                ret = [mapping.revision_id_bzr_to_foreign(revid)[0] for revid in interesting_heads]
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
280
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
0.200.247 by Jelmer Vernooij
Fix git-import.
281
        self.fetch_objects(determine_wants, mapping, pb)
282
        return self._refs
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
283
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
284
    @staticmethod
285
    def is_compatible(source, target):
286
        """Be compatible with GitRepository."""
287
        # FIXME: Also check target uses VersionedFile
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
288
        return (isinstance(source, GitRepository) and 
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
289
                target.supports_rich_root() and
290
                not isinstance(target, GitRepository))
291
292
293
class InterGitRepository(InterRepository):
294
295
    _matching_repo_format = GitFormat()
296
297
    @staticmethod
298
    def _get_repo_format_to_test():
299
        return None
300
301
    def copy_content(self, revision_id=None, pb=None):
302
        """See InterRepository.copy_content."""
303
        self.fetch(revision_id, pb, find_ghosts=False)
304
305
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
306
              mapping=None, fetch_spec=None):
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
307
        if mapping is None:
308
            mapping = self.source.get_mapping()
309
        def progress(text):
0.200.261 by Jelmer Vernooij
More formatting fixes.
310
            trace.info("git: %s", text)
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
311
        r = self.target._git
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
312
        if revision_id is not None:
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
313
            args = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
314
        elif fetch_spec is not None:
315
            args = [mapping.revision_id_bzr_to_foreign(revid)[0] for revid in fetch_spec.heads]
0.200.247 by Jelmer Vernooij
Fix git-import.
316
        if fetch_spec is None and revision_id is None:
317
            determine_wants = r.object_store.determine_wants_all
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
318
        else:
0.200.247 by Jelmer Vernooij
Fix git-import.
319
            determine_wants = lambda x: [y for y in args if not y in r.object_store]
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
320
321
        graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
322
        f, commit = r.object_store.add_pack()
323
        try:
324
            self.source._git.fetch_pack(path, determine_wants, graphwalker, f.write, progress)
325
            f.close()
326
            commit()
327
        except:
328
            f.close()
329
            raise
330
331
    @staticmethod
332
    def is_compatible(source, target):
333
        """Be compatible with GitRepository."""
334
        return (isinstance(source, GitRepository) and 
335
                isinstance(target, GitRepository))