/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.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
18
from bzrlib.errors import InvalidRevisionId
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.141 by Jelmer Vernooij
Separate out local and remote fetching.
29
from bzrlib.plugins.git.remote import RemoteGitRepository
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
30
0.200.193 by Jelmer Vernooij
Cope with newer *system* dulwich
31
import dulwich as git
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
32
from dulwich.client import SimpleFetchGraphWalker
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
33
from dulwich.objects import Commit
34
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
35
from cStringIO import StringIO
36
37
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
38
class BzrFetchGraphWalker(object):
0.200.196 by Jelmer Vernooij
Add simple tests and docstrings for GraphWalker.
39
    """GraphWalker implementation that uses a Bazaar repository."""
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
40
41
    def __init__(self, repository, mapping):
42
        self.repository = repository
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
43
        self.mapping = mapping
44
        self.done = set()
45
        self.heads = set(repository.all_revision_ids())
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
46
        self.parents = {}
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
47
0.200.196 by Jelmer Vernooij
Add simple tests and docstrings for GraphWalker.
48
    def __iter__(self):
49
        return iter(self.next, None)
50
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
51
    def ack(self, sha):
52
        revid = self.mapping.revision_id_foreign_to_bzr(sha)
53
        self.remove(revid)
54
55
    def remove(self, revid):
56
        self.done.add(revid)
0.200.177 by Jelmer Vernooij
Add git-import command.
57
        if revid in self.heads:
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
58
            self.heads.remove(revid)
59
        if revid in self.parents:
60
            for p in self.parents[revid]:
61
                self.remove(p)
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
62
63
    def next(self):
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
64
        while self.heads:
65
            ret = self.heads.pop()
66
            ps = self.repository.get_parent_map([ret])[ret]
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
67
            self.parents[ret] = ps
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
68
            self.heads.update([p for p in ps if not p in self.done])
69
            try:
70
                self.done.add(ret)
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
71
                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.
72
            except InvalidRevisionId:
73
                pass
0.216.4 by Jelmer Vernooij
Add basic pack fetch infrastructure.
74
        return None
75
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
76
0.200.159 by Jelmer Vernooij
Fix branch tests.
77
def import_git_blob(repo, mapping, path, blob, inv, parent_invs, executable):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
78
    """Import a git blob object into a bzr repository.
79
80
    :param repo: bzr repository
81
    :param path: Path in the tree
82
    :param blob: A git blob
83
    """
84
    file_id = mapping.generate_file_id(path)
0.200.158 by Jelmer Vernooij
fetch works \o/
85
    text_revision = inv.revision_id
86
    repo.texts.add_lines((file_id, text_revision),
87
        [(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.
88
        osutils.split_lines(blob.data))
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
89
    ie = inv.add_path(path, "file", file_id)
0.200.158 by Jelmer Vernooij
fetch works \o/
90
    ie.revision = text_revision
91
    ie.text_size = len(blob.data)
92
    ie.text_sha1 = osutils.sha_string(blob.data)
0.200.159 by Jelmer Vernooij
Fix branch tests.
93
    ie.executable = executable
0.200.158 by Jelmer Vernooij
fetch works \o/
94
95
96
def import_git_tree(repo, mapping, path, tree, inv, parent_invs, lookup_object):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
97
    """Import a git tree object into a bzr repository.
98
99
    :param repo: A Bzr repository object
100
    :param path: Path in the tree
101
    :param tree: A git tree object
102
    :param inv: Inventory object
103
    """
104
    file_id = mapping.generate_file_id(path)
0.200.158 by Jelmer Vernooij
fetch works \o/
105
    text_revision = inv.revision_id
106
    repo.texts.add_lines((file_id, text_revision),
107
        [(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.
108
        [])
0.200.158 by Jelmer Vernooij
fetch works \o/
109
    ie = inv.add_path(path, "directory", file_id)
110
    ie.revision = text_revision
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
111
    for mode, name, hexsha in tree.entries():
112
        entry_kind = (mode & 0700000) / 0100000
113
        basename = name.decode("utf-8")
114
        if path == "":
115
            child_path = name
116
        else:
117
            child_path = urlutils.join(path, name)
118
        if entry_kind == 0:
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
119
            tree = lookup_object(hexsha)
0.200.158 by Jelmer Vernooij
fetch works \o/
120
            import_git_tree(repo, mapping, child_path, tree, inv, parent_invs, lookup_object)
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
121
        elif entry_kind == 1:
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
122
            blob = lookup_object(hexsha)
0.200.159 by Jelmer Vernooij
Fix branch tests.
123
            fs_mode = mode & 0777
124
            import_git_blob(repo, mapping, child_path, blob, inv, parent_invs, bool(fs_mode & 0111))
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
125
        else:
126
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
127
128
0.200.188 by Jelmer Vernooij
Merge dulwich.
129
def import_git_objects(repo, mapping, num_objects, object_iter, pb=None):
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
130
    """Import a set of git objects into a bzr repository.
131
132
    :param repo: Bazaar repository
133
    :param mapping: Mapping to use
0.200.188 by Jelmer Vernooij
Merge dulwich.
134
    :param num_objects: Number of objects.
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
135
    :param object_iter: Iterator over Git objects.
136
    """
137
    # TODO: a more (memory-)efficient implementation of this
138
    objects = {}
0.200.193 by Jelmer Vernooij
Cope with newer *system* dulwich
139
    for i, (o, _) in enumerate(object_iter):
0.200.158 by Jelmer Vernooij
fetch works \o/
140
        if pb is not None:
0.200.188 by Jelmer Vernooij
Merge dulwich.
141
            pb.update("fetching objects", i, num_objects) 
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
142
        objects[o.id] = o
0.200.158 by Jelmer Vernooij
fetch works \o/
143
    graph = []
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
144
    root_trees = {}
0.200.158 by Jelmer Vernooij
fetch works \o/
145
    revisions = {}
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
146
    # Find and convert commit objects
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
147
    for o in objects.itervalues():
0.200.151 by Jelmer Vernooij
Support converting git objects to bzr objects.
148
        if isinstance(o, Commit):
149
            rev = mapping.import_commit(o)
0.200.158 by Jelmer Vernooij
fetch works \o/
150
            root_trees[rev.revision_id] = objects[o.tree]
151
            revisions[rev.revision_id] = rev
152
            graph.append((rev.revision_id, rev.parent_ids))
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.153 by Jelmer Vernooij
Merge new dulwich.
166
            if sha in objects:
167
                return objects[sha]
168
            return reconstruct_git_object(repo, mapping, 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, 
171
            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.153 by Jelmer Vernooij
Merge new dulwich.
175
def reconstruct_git_commit(repo, rev):
176
    raise NotImplementedError(self.reconstruct_git_commit)
177
178
179
def reconstruct_git_object(repo, mapping, sha):
180
    # Commit
181
    revid = mapping.revision_id_foreign_to_bzr(sha)
182
    try:
183
        rev = repo.get_revision(revid)
184
    except NoSuchRevision:
185
        pass
186
    else:
187
        return reconstruct_git_commit(rev)
188
189
    # TODO: Tree
190
    # TODO: Blob
191
    raise KeyError("No such object %s" % sha)
192
193
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
194
class InterGitNonGitRepository(InterRepository):
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
195
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
196
    _matching_repo_format = GitFormat()
197
198
    @staticmethod
199
    def _get_repo_format_to_test():
200
        return None
201
0.200.135 by Jelmer Vernooij
Add stub for fetching data.
202
    def copy_content(self, revision_id=None, pb=None):
203
        """See InterRepository.copy_content."""
204
        self.fetch(revision_id, pb, find_ghosts=False)
205
206
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
207
              mapping=None):
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
208
        if mapping is None:
209
            mapping = self.source.get_mapping()
0.200.140 by Jelmer Vernooij
Support negotiating with remote git repository and receiving pack.
210
        def progress(text):
0.217.41 by John Carr
Don't fill screen with muttering
211
            pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
212
        def determine_wants(heads):
213
            if revision_id is None:
214
                ret = heads.values()
215
            else:
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
216
                ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
0.200.147 by Jelmer Vernooij
Merge new dulwich; fetching objects from local repository works now; they aren't converted yet though.
217
            return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
218
        graph_walker = BzrFetchGraphWalker(self.target, mapping)
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
219
        create_pb = None
220
        if pb is None:
221
            create_pb = pb = ui.ui_factory.nested_progress_bar()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
222
        try:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
223
            self.target.lock_write()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
224
            try:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
225
                self.target.start_write_group()
226
                try:
0.200.188 by Jelmer Vernooij
Merge dulwich.
227
                    (num_objects, objects_iter) = \
228
                            self.source.fetch_objects(determine_wants, 
0.200.189 by Jelmer Vernooij
Fix syntax error.
229
                                graph_walker, progress)
0.200.188 by Jelmer Vernooij
Merge dulwich.
230
                    import_git_objects(self.target, mapping, num_objects, 
231
                                       objects_iter, pb)
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
232
                finally:
233
                    self.target.commit_write_group()
0.200.157 by Jelmer Vernooij
Fix some bit of fetching.
234
            finally:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
235
                self.target.unlock()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
236
        finally:
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
237
            if create_pb:
238
                create_pb.finished()
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
239
240
    @staticmethod
241
    def is_compatible(source, target):
242
        """Be compatible with GitRepository."""
243
        # FIXME: Also check target uses VersionedFile
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
244
        return (isinstance(source, GitRepository) and 
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
245
                target.supports_rich_root() and
246
                not isinstance(target, GitRepository))
247
248
249
class InterGitRepository(InterRepository):
250
251
    _matching_repo_format = GitFormat()
252
253
    @staticmethod
254
    def _get_repo_format_to_test():
255
        return None
256
257
    def copy_content(self, revision_id=None, pb=None):
258
        """See InterRepository.copy_content."""
259
        self.fetch(revision_id, pb, find_ghosts=False)
260
261
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
262
              mapping=None):
263
        if mapping is None:
264
            mapping = self.source.get_mapping()
265
        def progress(text):
266
            info("git: %s", text)
267
        r = self.target._git
268
        if revision_id is None:
269
            determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
270
        else:
0.200.195 by Jelmer Vernooij
Return mapping in revision_id_bzr_to_foreign() as required by the interface.
271
            args = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
272
            determine_wants = lambda x: [y for y in args if not y in r.object_store]
273
274
        graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
275
        f, commit = r.object_store.add_pack()
276
        try:
277
            self.source._git.fetch_pack(path, determine_wants, graphwalker, f.write, progress)
278
            f.close()
279
            commit()
280
        except:
281
            f.close()
282
            raise
283
284
    @staticmethod
285
    def is_compatible(source, target):
286
        """Be compatible with GitRepository."""
287
        return (isinstance(source, GitRepository) and 
288
                isinstance(target, GitRepository))