/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
19
from dulwich.client import SimpleFetchGraphWalker
20
from dulwich.objects import Commit
21
22
from bzrlib import (
23
    osutils,
24
    ui,
25
    urlutils,
26
    )
27
from bzrlib.errors import (
28
    InvalidRevisionId,
29
    NoSuchRevision,
30
    )
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
31
from bzrlib.inventory import Inventory
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
32
from bzrlib.repository import InterRepository
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
33
from bzrlib.trace import info
0.200.158 by Jelmer Vernooij
fetch works \o/
34
from bzrlib.tsort import topo_sort
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
35
0.200.169 by Jelmer Vernooij
Fix branch cloning.
36
from bzrlib.plugins.git.repository import (
37
        LocalGitRepository, 
38
        GitRepository, 
39
        GitFormat,
40
        )
0.200.230 by Jelmer Vernooij
Implement sha cache.
41
from bzrlib.plugins.git.converter import GitObjectConverter
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
42
from bzrlib.plugins.git.remote import RemoteGitRepository
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
43
44
45
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
46
class BzrFetchGraphWalker(object):
0.200.196 by Jelmer Vernooij
Add simple tests and docstrings for GraphWalker.
47
    """GraphWalker implementation that uses a Bazaar repository."""
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
48
49
    def __init__(self, repository, mapping):
50
        self.repository = repository
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
51
        self.mapping = mapping
52
        self.done = set()
53
        self.heads = set(repository.all_revision_ids())
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
54
        self.parents = {}
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
55
0.200.196 by Jelmer Vernooij
Add simple tests and docstrings for GraphWalker.
56
    def __iter__(self):
57
        return iter(self.next, None)
58
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
59
    def ack(self, sha):
60
        revid = self.mapping.revision_id_foreign_to_bzr(sha)
61
        self.remove(revid)
62
63
    def remove(self, revid):
64
        self.done.add(revid)
0.200.177 by Jelmer Vernooij
Add git-import command.
65
        if revid in self.heads:
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
66
            self.heads.remove(revid)
67
        if revid in self.parents:
68
            for p in self.parents[revid]:
69
                self.remove(p)
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
70
71
    def next(self):
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
72
        while self.heads:
73
            ret = self.heads.pop()
74
            ps = self.repository.get_parent_map([ret])[ret]
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
75
            self.parents[ret] = ps
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
76
            self.heads.update([p for p in ps if not p in self.done])
77
            try:
78
                self.done.add(ret)
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
79
                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.
80
            except InvalidRevisionId:
81
                pass
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
82
        return None
83
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
84
0.200.231 by Jelmer Vernooij
Partially fix pull.
85
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, gitmap, executable):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
86
    """Import a git blob object into a bzr repository.
87
88
    :param repo: bzr repository
89
    :param path: Path in the tree
90
    :param blob: A git blob
91
    """
92
    file_id = mapping.generate_file_id(path)
0.200.158 by Jelmer Vernooij
fetch works \o/
93
    text_revision = inv.revision_id
94
    repo.texts.add_lines((file_id, text_revision),
95
        [(file_id, p[file_id].revision) for p in parent_invs if file_id in p],
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
96
        osutils.split_lines(blob.data))
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
97
    ie = inv.add_path(path, "file", file_id)
0.200.158 by Jelmer Vernooij
fetch works \o/
98
    ie.revision = text_revision
99
    ie.text_size = len(blob.data)
100
    ie.text_sha1 = osutils.sha_string(blob.data)
0.200.159 by Jelmer Vernooij
Fix branch tests.
101
    ie.executable = executable
0.200.231 by Jelmer Vernooij
Partially fix pull.
102
    gitmap._idmap.add_entry(blob.sha().hexdigest(), "blob", (ie.file_id, ie.revision))
103
104
105
def import_git_tree(repo, mapping, path, tree, inv, parent_invs, 
106
                    gitmap, lookup_object):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
107
    """Import a git tree object into a bzr repository.
108
109
    :param repo: A Bzr repository object
110
    :param path: Path in the tree
111
    :param tree: A git tree object
112
    :param inv: Inventory object
113
    """
114
    file_id = mapping.generate_file_id(path)
0.200.158 by Jelmer Vernooij
fetch works \o/
115
    text_revision = inv.revision_id
116
    repo.texts.add_lines((file_id, text_revision),
117
        [(file_id, p[file_id].revision) for p in parent_invs if file_id in p],
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
118
        [])
0.200.158 by Jelmer Vernooij
fetch works \o/
119
    ie = inv.add_path(path, "directory", file_id)
120
    ie.revision = text_revision
0.200.231 by Jelmer Vernooij
Partially fix pull.
121
    gitmap._idmap.add_entry(tree.sha().hexdigest(), "tree", (file_id, text_revision))
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
122
    for mode, name, hexsha in tree.entries():
123
        entry_kind = (mode & 0700000) / 0100000
124
        basename = name.decode("utf-8")
125
        if path == "":
126
            child_path = name
127
        else:
128
            child_path = urlutils.join(path, name)
129
        if entry_kind == 0:
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
130
            tree = lookup_object(hexsha)
0.200.231 by Jelmer Vernooij
Partially fix pull.
131
            import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, gitmap, lookup_object)
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
132
        elif entry_kind == 1:
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
133
            blob = lookup_object(hexsha)
0.200.159 by Jelmer Vernooij
Fix branch tests.
134
            fs_mode = mode & 0777
0.200.231 by Jelmer Vernooij
Partially fix pull.
135
            import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, gitmap, bool(fs_mode & 0111))
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
136
        else:
137
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
138
139
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
140
def import_git_objects(repo, mapping, object_iter, target_git_object_retriever, 
141
        pb=None):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
142
    """Import a set of git objects into a bzr repository.
143
144
    :param repo: Bazaar repository
145
    :param mapping: Mapping to use
146
    :param object_iter: Iterator over Git objects.
147
    """
148
    # TODO: a more (memory-)efficient implementation of this
0.200.158 by Jelmer Vernooij
fetch works \o/
149
    graph = []
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
150
    root_trees = {}
0.200.158 by Jelmer Vernooij
fetch works \o/
151
    revisions = {}
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
152
    # Find and convert commit objects
0.200.217 by Jelmer Vernooij
Avoid reading everything into memory when accessing objects.
153
    for o in object_iter.iterobjects():
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
154
        if isinstance(o, Commit):
155
            rev = mapping.import_commit(o)
0.200.217 by Jelmer Vernooij
Avoid reading everything into memory when accessing objects.
156
            root_trees[rev.revision_id] = object_iter[o.tree]
0.200.158 by Jelmer Vernooij
fetch works \o/
157
            revisions[rev.revision_id] = rev
158
            graph.append((rev.revision_id, rev.parent_ids))
0.200.231 by Jelmer Vernooij
Partially fix pull.
159
            target_git_object_retriever._idmap.add_entry(o.sha().hexdigest(), "commit", (rev.revision_id, o._tree))
0.200.158 by Jelmer Vernooij
fetch works \o/
160
    # Order the revisions
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
161
    # Create the inventory objects
0.200.158 by Jelmer Vernooij
fetch works \o/
162
    for i, revid in enumerate(topo_sort(graph)):
163
        if pb is not None:
164
            pb.update("fetching revisions", i, len(graph))
165
        root_tree = root_trees[revid]
166
        rev = revisions[revid]
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
167
        # We have to do this here, since we have to walk the tree and 
168
        # we need to make sure to import the blobs / trees with the riht 
169
        # path; this may involve adding them more than once.
170
        inv = Inventory()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
171
        inv.revision_id = rev.revision_id
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
172
        def lookup_object(sha):
0.200.217 by Jelmer Vernooij
Avoid reading everything into memory when accessing objects.
173
            if sha in object_iter:
174
                return object_iter[sha]
0.200.230 by Jelmer Vernooij
Implement sha cache.
175
            return target_git_object_retriever[sha]
0.200.158 by Jelmer Vernooij
fetch works \o/
176
        parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
0.200.170 by Jelmer Vernooij
Merge new dulwich.
177
        import_git_tree(repo, mapping, "", root_tree, inv, parent_invs, 
0.200.231 by Jelmer Vernooij
Partially fix pull.
178
            target_git_object_retriever, lookup_object)
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
179
        repo.add_revision(rev.revision_id, rev, inv)
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
180
181
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
182
class InterGitNonGitRepository(InterRepository):
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
183
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
184
    _matching_repo_format = GitFormat()
185
186
    @staticmethod
187
    def _get_repo_format_to_test():
188
        return None
189
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
190
    def copy_content(self, revision_id=None, pb=None):
191
        """See InterRepository.copy_content."""
192
        self.fetch(revision_id, pb, find_ghosts=False)
193
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
194
    def fetch_objects(self, determine_wants, mapping, pb=None):
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
195
        def progress(text):
0.217.41 by John Carr
Don't fill screen with muttering
196
            pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
197
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
198
        create_pb = None
199
        if pb is None:
200
            create_pb = pb = ui.ui_factory.nested_progress_bar()
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
201
        target_git_object_retriever = GitObjectConverter(self.target, mapping)
202
        
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
203
        try:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
204
            self.target.lock_write()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
205
            try:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
206
                self.target.start_write_group()
207
                try:
0.200.216 by Jelmer Vernooij
Use ObjectIterator interface.
208
                    objects_iter = self.source.fetch_objects(determine_wants, 
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
209
                                graph_walker, 
210
                                target_git_object_retriever.__getitem__, 
211
                                progress)
212
                    import_git_objects(self.target, mapping, objects_iter, 
213
                            target_git_object_retriever, pb)
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
214
                finally:
215
                    self.target.commit_write_group()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
216
            finally:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
217
                self.target.unlock()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
218
        finally:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
219
            if create_pb:
220
                create_pb.finished()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
221
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
222
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
223
              mapping=None, fetch_spec=None):
0.200.247 by Jelmer Vernooij
Fix git-import.
224
        self.fetch_refs(revision_id=revision_id, pb=pb, find_ghosts=find_ghosts,
225
                mapping=mapping, fetch_spec=fetch_spec)
226
227
    def fetch_refs(self, revision_id=None, pb=None, find_ghosts=False, 
228
              mapping=None, fetch_spec=None):
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
229
        if mapping is None:
230
            mapping = self.source.get_mapping()
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
231
        if revision_id is not None:
232
            interesting_heads = [revision_id]
233
        elif fetch_spec is not None:
234
            interesting_heads = fetch_spec.heads
235
        else:
236
            interesting_heads = None
0.200.247 by Jelmer Vernooij
Fix git-import.
237
        self._refs = {}
238
        def determine_wants(refs):
239
            self._refs = refs
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
240
            if interesting_heads is None:
0.200.247 by Jelmer Vernooij
Fix git-import.
241
                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.
242
            else:
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
243
                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.
244
            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.
245
        self.fetch_objects(determine_wants, mapping, pb)
246
        return self._refs
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
247
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
248
    @staticmethod
249
    def is_compatible(source, target):
250
        """Be compatible with GitRepository."""
251
        # FIXME: Also check target uses VersionedFile
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
252
        return (isinstance(source, GitRepository) and 
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
253
                target.supports_rich_root() and
254
                not isinstance(target, GitRepository))
255
256
257
class InterGitRepository(InterRepository):
258
259
    _matching_repo_format = GitFormat()
260
261
    @staticmethod
262
    def _get_repo_format_to_test():
263
        return None
264
265
    def copy_content(self, revision_id=None, pb=None):
266
        """See InterRepository.copy_content."""
267
        self.fetch(revision_id, pb, find_ghosts=False)
268
269
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
270
              mapping=None, fetch_spec=None):
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
271
        if mapping is None:
272
            mapping = self.source.get_mapping()
273
        def progress(text):
274
            info("git: %s", text)
275
        r = self.target._git
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
276
        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.
277
            args = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
278
        elif fetch_spec is not None:
279
            args = [mapping.revision_id_bzr_to_foreign(revid)[0] for revid in fetch_spec.heads]
0.200.247 by Jelmer Vernooij
Fix git-import.
280
        if fetch_spec is None and revision_id is None:
281
            determine_wants = r.object_store.determine_wants_all
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
282
        else:
0.200.247 by Jelmer Vernooij
Fix git-import.
283
            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.
284
285
        graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
286
        f, commit = r.object_store.add_pack()
287
        try:
288
            self.source._git.fetch_pack(path, determine_wants, graphwalker, f.write, progress)
289
            f.close()
290
            commit()
291
        except:
292
            f.close()
293
            raise
294
295
    @staticmethod
296
    def is_compatible(source, target):
297
        """Be compatible with GitRepository."""
298
        return (isinstance(source, GitRepository) and 
299
                isinstance(target, GitRepository))