/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
1
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
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
17
"""Push implementation that simply prints message saying push is not supported."""
18
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
19
from dulwich.client import (
20
    SimpleFetchGraphWalker,
21
    )
22
from dulwich.repo import (
23
    MissingObjectFinder,
24
    )
25
0.200.357 by Jelmer Vernooij
Move push code to push.py.
26
from bzrlib import (
27
    ui,
28
    )
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
29
from bzrlib.repository import (
30
    InterRepository,
31
    )
0.200.371 by Jelmer Vernooij
Add progress bar when determining revisions to dpush
32
from bzrlib.revision import (
33
    NULL_REVISION,
34
    )
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
35
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
36
from bzrlib.plugins.git.converter import (
37
    BazaarObjectStore,
38
    )
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
39
from bzrlib.plugins.git.errors import (
40
    NoPushSupport,
41
    )
42
from bzrlib.plugins.git.repository import (
43
    GitRepository,
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
44
    LocalGitRepository,
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
45
    GitRepositoryFormat,
46
    )
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
47
from bzrlib.plugins.git.remote import (
48
    RemoteGitRepository,
49
    )
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
50
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
51
52
class MissingObjectsIterator(object):
53
    """Iterate over git objects that are missing from a target repository.
54
55
    """
56
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
57
    def __init__(self, source, mapping, pb=None):
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
58
        """Create a new missing objects iterator.
59
60
        """
61
        self.source = source
62
        self._object_store = BazaarObjectStore(self.source, mapping)
63
        self._revids = set()
64
        self._sent_shas = set()
65
        self._pending = []
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
66
        self.pb = pb
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
67
68
    def import_revisions(self, revids):
69
        self._revids.update(revids)
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
70
        for i, revid in enumerate(revids):
71
            if self.pb:
72
                self.pb.update("pushing revisions", i, len(revids))
73
            git_commit = self.import_revision(revid)
74
            yield (revid, git_commit)
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
75
76
    def need_sha(self, sha):
77
        if sha in self._sent_shas:
78
            return False
79
        (type, (fileid, revid)) = self._object_store._idmap.lookup_git_sha(sha)
80
        assert type in ("blob", "tree")
81
        if revid in self._revids:
82
            # Not sent yet, and part of the set of revisions to send
83
            return True
84
        # Not changed in the revisions to send, so either not necessary
85
        # or already present remotely (as git doesn't do ghosts)
86
        return False
87
88
    def queue(self, sha, obj, path, ie=None, inv=None):
89
        if obj is None:
90
            obj = (ie, inv)
91
        self._pending.append((obj, path))
92
        self._sent_shas.add(sha)
93
94
    def import_revision(self, revid):
95
        """Import the gist of a revision into this Git repository.
96
97
        """
98
        inv = self.source.get_inventory(revid)
99
        todo = [inv.root]
100
        tree_sha = None
101
        while todo:
102
            ie = todo.pop()
103
            (sha, object) = self._object_store._get_ie_object_or_sha1(ie, inv)
104
            if ie.parent_id is None:
105
                tree_sha = sha
106
            if not self.need_sha(sha):
107
                continue
108
            self.queue(sha, object, inv.id2path(ie.file_id), ie, inv)
109
            if ie.kind == "directory":
110
                todo.extend(ie.children.values())
111
        assert tree_sha is not None
112
        commit = self._object_store._get_commit(revid, tree_sha)
113
        self.queue(commit.id, commit, None)
114
        return commit.id
115
116
    def __len__(self):
117
        return len(self._pending)
118
119
    def __iter__(self):
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
120
        for i, (object, path) in enumerate(self._pending):
121
            if self.pb:
122
                self.pb.update("writing pack objects", i, len(self))
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
123
            if isinstance(object, tuple):
124
                object = self._object_store._get_ie_object(*object)
125
            yield (object, path)   
126
127
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
128
class InterToGitRepository(InterRepository):
129
    """InterRepository that copies into a Git repository."""
130
131
    _matching_repo_format = GitRepositoryFormat()
132
0.200.435 by Jelmer Vernooij
Remember mapping per InterRepository.
133
    def __init__(self, source, target):
134
        super(InterToGitRepository, self).__init__(source, target)
135
        self.mapping = self.target.get_mapping()
136
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
137
    @staticmethod
138
    def _get_repo_format_to_test():
139
        return None
140
141
    def copy_content(self, revision_id=None, pb=None):
142
        """See InterRepository.copy_content."""
143
        self.fetch(revision_id, pb, find_ghosts=False)
144
145
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
146
            fetch_spec=None):
147
        raise NoPushSupport()
148
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
149
150
class InterToLocalGitRepository(InterToGitRepository):
151
0.200.371 by Jelmer Vernooij
Add progress bar when determining revisions to dpush
152
    def missing_revisions(self, stop_revision):
153
        if stop_revision is None:
154
            raise NotImplementedError
0.200.357 by Jelmer Vernooij
Move push code to push.py.
155
        missing = []
0.200.371 by Jelmer Vernooij
Add progress bar when determining revisions to dpush
156
        pb = ui.ui_factory.nested_progress_bar()
157
        try:
158
            graph = self.source.get_graph()
159
            for revid, _ in graph.iter_ancestry([stop_revision]):
160
                pb.update("determining revisions to fetch", len(missing))
161
                if not self.target.has_revision(revid):
162
                    missing.append(revid)
163
            return graph.iter_topo_order(missing)
164
        finally:
165
            pb.finished()
0.200.357 by Jelmer Vernooij
Move push code to push.py.
166
0.200.428 by Jelmer Vernooij
use dfetch_refs, to prepare for dpush to remote repositories.
167
    def dfetch_refs(self, refs):
168
        revidmap = {}
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
169
        new_refs = {}
0.200.428 by Jelmer Vernooij
use dfetch_refs, to prepare for dpush to remote repositories.
170
        for name, revid in refs.iteritems():
171
            newrevidmap, newgitidmap = self.dfetch(revid)
172
            revidmap.update(newrevidmap)
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
173
            if revid in newgitidmap:
174
                gitid = newgitidmap[revid]
0.200.435 by Jelmer Vernooij
Remember mapping per InterRepository.
175
            else:
176
                gitid, _ = self.mapping.revision_id_bzr_to_foreign(revid)
177
            self.target._git.set_ref(name, gitid)
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
178
            new_refs[name] = gitid
179
        return revidmap, new_refs
0.200.428 by Jelmer Vernooij
use dfetch_refs, to prepare for dpush to remote repositories.
180
0.200.360 by Jelmer Vernooij
Remove dpush ghost support - it makes no sense, git doesn't do ghosts.
181
    def dfetch(self, stop_revision=None):
0.200.357 by Jelmer Vernooij
Move push code to push.py.
182
        """Import the gist of the ancestry of a particular revision."""
0.200.428 by Jelmer Vernooij
use dfetch_refs, to prepare for dpush to remote repositories.
183
        gitidmap = {}
0.200.357 by Jelmer Vernooij
Move push code to push.py.
184
        revidmap = {}
0.200.367 by Jelmer Vernooij
In dfetch, skip fetching pushed revisions back, as cmd_dpush will already take care of that.
185
        self.source.lock_read()
0.200.357 by Jelmer Vernooij
Move push code to push.py.
186
        try:
0.200.371 by Jelmer Vernooij
Add progress bar when determining revisions to dpush
187
            todo = [revid for revid in self.missing_revisions(stop_revision) if revid != NULL_REVISION]
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
188
            pb = ui.ui_factory.nested_progress_bar()
189
            try:
0.200.435 by Jelmer Vernooij
Remember mapping per InterRepository.
190
                object_generator = MissingObjectsIterator(self.source, self.mapping, pb)
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
191
                for old_bzr_revid, git_commit in object_generator.import_revisions(
192
                    todo):
0.200.435 by Jelmer Vernooij
Remember mapping per InterRepository.
193
                    new_bzr_revid = self.mapping.revision_id_foreign_to_bzr(git_commit)
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
194
                    revidmap[old_bzr_revid] = new_bzr_revid
0.200.428 by Jelmer Vernooij
use dfetch_refs, to prepare for dpush to remote repositories.
195
                    gitidmap[old_bzr_revid] = git_commit
0.200.369 by Jelmer Vernooij
Report on pack objects progress.
196
                self.target._git.object_store.add_objects(object_generator) 
197
            finally:
198
                pb.finished()
0.200.357 by Jelmer Vernooij
Move push code to push.py.
199
        finally:
200
            self.source.unlock()
0.200.428 by Jelmer Vernooij
use dfetch_refs, to prepare for dpush to remote repositories.
201
        return revidmap, gitidmap
0.200.357 by Jelmer Vernooij
Move push code to push.py.
202
0.200.291 by Jelmer Vernooij
Print proper error about not supporting push.
203
    @staticmethod
204
    def is_compatible(source, target):
205
        """Be compatible with GitRepository."""
206
        return (not isinstance(source, GitRepository) and 
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
207
                isinstance(target, LocalGitRepository))
208
209
210
class InterToRemoteGitRepository(InterToGitRepository):
211
0.200.429 by Jelmer Vernooij
get remote dpush to a point where we now what to send.
212
    def dfetch_refs(self, new_refs):
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
213
        """Import the gist of the ancestry of a particular revision."""
214
        revidmap = {}
0.200.429 by Jelmer Vernooij
get remote dpush to a point where we now what to send.
215
        def get_changed_refs(refs):
216
            ret = {}
217
            for name, revid in new_refs.iteritems():
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
218
                ret[name] = store._lookup_revision_sha1(revid)
0.200.429 by Jelmer Vernooij
get remote dpush to a point where we now what to send.
219
            return ret
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
220
        self.source.lock_read()
221
        try:
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
222
            store = BazaarObjectStore(self.source, self.mapping)
0.200.436 by Jelmer Vernooij
Follow new API for send-pack.
223
            def generate_blob_contents(have, want):
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
224
                graphwalker = SimpleFetchGraphWalker(have, store.get_parents)
225
                objfinder = MissingObjectFinder(store, want, graphwalker)
226
                return store.iter_shas(iter(objfinder.next, None))
227
            new_refs = self.target.send_pack(get_changed_refs, generate_blob_contents)
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
228
        finally:
229
            self.source.unlock()
0.200.438 by Jelmer Vernooij
Somewhat fix dpushing to remote repos.
230
        return revidmap, new_refs
0.200.425 by Jelmer Vernooij
Split out push to remote git repositories.
231
232
    @staticmethod
233
    def is_compatible(source, target):
234
        """Be compatible with GitRepository."""
235
        return (not isinstance(source, GitRepository) and 
236
                isinstance(target, RemoteGitRepository))