/brz/remove-bazaar

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