/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to remote.py

Raise proper errors for ghosts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2008 Canonical Ltd
 
1
# Copyright (C) 2007-2009 Jelmer Vernooij <jelmer@samba.org>
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
import bzrlib
18
 
from bzrlib import urlutils
19
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat
20
 
from bzrlib.errors import NoSuchFile, NotLocalUrl
21
 
from bzrlib.lockable_files import TransportLock
22
 
from bzrlib.repository import Repository
23
 
from bzrlib.trace import info
24
 
from bzrlib.transport import Transport
25
 
 
26
 
from bzrlib.plugins.git import git
27
 
from bzrlib.plugins.git.branch import GitBranch
28
 
from bzrlib.plugins.git.errors import NoSuchRef
29
 
from bzrlib.plugins.git.dir import GitDir
30
 
from bzrlib.plugins.git.foreign import ForeignBranch
31
 
from bzrlib.plugins.git.repository import GitFormat, GitRepository
32
 
 
 
18
from bzrlib import (
 
19
    branch,
 
20
    tag,
 
21
    ui,
 
22
    urlutils,
 
23
    )
 
24
from bzrlib.errors import (
 
25
    BzrError,
 
26
    InvalidRevisionId,
 
27
    NoSuchFile,
 
28
    NoSuchRevision,
 
29
    NotLocalUrl,
 
30
    )
 
31
from bzrlib.trace import (
 
32
    info,
 
33
    )
 
34
from bzrlib.transport import (
 
35
    Transport,
 
36
    )
 
37
 
 
38
from bzrlib.plugins.git import (
 
39
    lazy_check_versions,
 
40
    )
 
41
lazy_check_versions()
 
42
 
 
43
from bzrlib.plugins.git.branch import (
 
44
    GitBranch,
 
45
    extract_tags,
 
46
    )
 
47
from bzrlib.plugins.git.errors import (
 
48
    GitSmartRemoteNotSupported,
 
49
    NoSuchRef,
 
50
    )
 
51
from bzrlib.plugins.git.dir import (
 
52
    GitDir,
 
53
    )
 
54
from bzrlib.plugins.git.mapping import (
 
55
    mapping_registry,
 
56
    )
 
57
from bzrlib.plugins.git.repository import (
 
58
    GitRepositoryFormat,
 
59
    GitRepository,
 
60
    )
 
61
 
 
62
import dulwich as git
 
63
from dulwich.errors import (
 
64
    GitProtocolError,
 
65
    )
 
66
from dulwich.pack import (
 
67
    Pack,
 
68
    PackData,
 
69
    )
33
70
import os
34
71
import tempfile
35
72
import urllib
36
73
import urlparse
37
74
 
38
 
from dulwich.pack import PackData, Pack
 
75
try:
 
76
    from dulwich.pack import load_pack_index
 
77
except ImportError:
 
78
    from dulwich.pack import PackIndex as load_pack_index
 
79
 
 
80
 
 
81
# Don't run any tests on GitSmartTransport as it is not intended to be 
 
82
# a full implementation of Transport
 
83
def get_test_permutations():
 
84
    return []
39
85
 
40
86
 
41
87
class GitSmartTransport(Transport):
43
89
    def __init__(self, url, _client=None):
44
90
        Transport.__init__(self, url)
45
91
        (scheme, _, loc, _, _) = urlparse.urlsplit(url)
46
 
        assert scheme == "git"
47
92
        hostport, self._path = urllib.splithost(loc)
48
 
        (self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
 
93
        (self._host, self._port) = urllib.splitnport(hostport, None)
49
94
        self._client = _client
50
95
 
 
96
    def has(self, relpath):
 
97
        return False
 
98
 
51
99
    def _get_client(self):
52
 
        if self._client is not None:
53
 
            ret = self._client
54
 
            self._client = None
55
 
            return ret
56
 
        return git.client.TCPGitClient(self._host, self._port)
 
100
        raise NotImplementedError(self._get_client)
57
101
 
58
102
    def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
59
103
        if progress is None:
60
104
            def progress(text):
61
105
                info("git: %s" % text)
62
 
        self._get_client().fetch_pack(self._path, determine_wants, 
63
 
            graph_walker, pack_data, progress)
 
106
        client = self._get_client()
 
107
        try:
 
108
            return client.fetch_pack(self._path, determine_wants, 
 
109
                graph_walker, pack_data, progress)
 
110
        except GitProtocolError, e:
 
111
            raise BzrError(e)
 
112
 
 
113
    def send_pack(self, get_changed_refs, generate_pack_contents):
 
114
        client = self._get_client()
 
115
        try:
 
116
            return client.send_pack(self._path, get_changed_refs, 
 
117
                generate_pack_contents)
 
118
        except GitProtocolError, e:
 
119
            raise BzrError(e)
64
120
 
65
121
    def get(self, path):
66
122
        raise NoSuchFile(path)
75
131
        else:
76
132
            newurl = urlutils.join(self.base, offset)
77
133
 
78
 
        return GitSmartTransport(newurl, self._client)
 
134
        return self.__class__(newurl, self._client)
 
135
 
 
136
 
 
137
class TCPGitSmartTransport(GitSmartTransport):
 
138
 
 
139
    _scheme = 'git'
 
140
 
 
141
    def _get_client(self):
 
142
        if self._client is not None:
 
143
            ret = self._client
 
144
            self._client = None
 
145
            return ret
 
146
        return git.client.TCPGitClient(self._host, self._port, thin_packs=False,
 
147
            report_activity=self._report_activity)
 
148
 
 
149
 
 
150
class SSHGitSmartTransport(GitSmartTransport):
 
151
 
 
152
    _scheme = 'git+ssh'
 
153
 
 
154
    def _get_client(self):
 
155
        if self._client is not None:
 
156
            ret = self._client
 
157
            self._client = None
 
158
            return ret
 
159
        return git.client.SSHGitClient(self._host, self._port, thin_packs=False,
 
160
            report_activity=self._report_activity)
79
161
 
80
162
 
81
163
class RemoteGitDir(GitDir):
85
167
        self.root_transport = transport
86
168
        self.transport = transport
87
169
        self._lockfiles = lockfiles
 
170
        self._mode_check_done = None
88
171
 
89
172
    def open_repository(self):
90
173
        return RemoteGitRepository(self, self._lockfiles)
91
174
 
92
 
    def open_branch(self):
 
175
    def open_branch(self, ignore_fallbacks=False):
93
176
        repo = self.open_repository()
94
177
        # TODO: Support for multiple branches in one bzrdir in bzrlib!
95
178
        return RemoteGitBranch(self, repo, "HEAD", self._lockfiles)
98
181
        raise NotLocalUrl(self.transport.base)
99
182
 
100
183
 
 
184
class EmptyObjectStoreIterator(dict):
 
185
 
 
186
    def iterobjects(self):
 
187
        return []
 
188
 
 
189
 
 
190
class TemporaryPackIterator(Pack):
 
191
 
 
192
    def __init__(self, path, resolve_ext_ref):
 
193
        super(TemporaryPackIterator, self).__init__(path)
 
194
        self.resolve_ext_ref = resolve_ext_ref
 
195
 
 
196
    @property
 
197
    def index(self):
 
198
        if self._idx is None:
 
199
            if self._data is None:
 
200
                self._data = PackData(self._data_path)
 
201
            pb = ui.ui_factory.nested_progress_bar()
 
202
            try:
 
203
                def report_progress(cur, total):
 
204
                    pb.update("generating index", cur, total)
 
205
                self._data.create_index_v2(self._idx_path, self.resolve_ext_ref,
 
206
                    progress=report_progress)
 
207
            finally:
 
208
                pb.finished()
 
209
            self._idx = load_pack_index(self._idx_path)
 
210
        return self._idx
 
211
 
 
212
    def __del__(self):
 
213
        os.remove(self._data_path)
 
214
        os.remove(self._idx_path)
 
215
 
 
216
 
101
217
class RemoteGitRepository(GitRepository):
102
218
 
103
219
    def __init__(self, gitdir, lockfiles):
104
220
        GitRepository.__init__(self, gitdir, lockfiles)
 
221
        self._refs = None
 
222
 
 
223
    @property
 
224
    def inventories(self):
 
225
        raise GitSmartRemoteNotSupported()
 
226
 
 
227
    @property
 
228
    def revisions(self):
 
229
        raise GitSmartRemoteNotSupported()
 
230
 
 
231
    @property
 
232
    def texts(self):
 
233
        raise GitSmartRemoteNotSupported()
 
234
 
 
235
    def get_refs(self):
 
236
        if self._refs is not None:
 
237
            return self._refs
 
238
        self._refs = self.bzrdir.root_transport.fetch_pack(lambda x: [], None, 
 
239
            lambda x: None, lambda x: mutter("git: %s" % x))
 
240
        return self._refs
105
241
 
106
242
    def fetch_pack(self, determine_wants, graph_walker, pack_data, 
107
243
                   progress=None):
108
 
        self._transport.fetch_pack(determine_wants, graph_walker, pack_data, 
109
 
            progress)
110
 
 
111
 
    def fetch_objects(self, determine_wants, graph_walker, progress=None):
 
244
        return self._transport.fetch_pack(determine_wants, graph_walker,
 
245
                                          pack_data, progress)
 
246
 
 
247
    def send_pack(self, get_changed_refs, generate_pack_contents):
 
248
        return self._transport.send_pack(get_changed_refs, generate_pack_contents)
 
249
 
 
250
    def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
112
251
        fd, path = tempfile.mkstemp(suffix=".pack")
113
252
        self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
114
253
        os.close(fd)
 
254
        if os.path.getsize(path) == 0:
 
255
            return EmptyObjectStoreIterator()
 
256
        return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
 
257
 
 
258
    def lookup_git_revid(self, bzr_revid):
 
259
        # This won't work for any round-tripped bzr revisions, but it's a start..
115
260
        try:
116
 
            basename = path[:-len(".pack")]
117
 
            p = PackData(path)
118
 
            p.create_index_v2(basename+".idx")
119
 
            for o in Pack(basename).iterobjects():
120
 
                yield o
121
 
        finally:
122
 
            os.remove(path)
 
261
            return mapping_registry.revision_id_bzr_to_foreign(bzr_revid)
 
262
        except InvalidRevisionId:
 
263
            raise NoSuchRevision(self, bzr_revid)
 
264
 
 
265
 
 
266
class RemoteGitTagDict(tag.BasicTags):
 
267
 
 
268
    def __init__(self, branch):
 
269
        self.branch = branch
 
270
        self.repository = branch.repository
 
271
 
 
272
    def get_tag_dict(self):
 
273
        return extract_tags(self.repository.get_refs(), self.branch.mapping)
 
274
 
 
275
    def set_tag(self, name, revid):
 
276
        # FIXME: Not supported yet, should do a push of a new ref
 
277
        raise NotImplementedError(self.set_tag)
123
278
 
124
279
 
125
280
class RemoteGitBranch(GitBranch):
126
281
 
127
282
    def __init__(self, bzrdir, repository, name, lockfiles):
128
 
        def determine_wants(heads):
129
 
            if not name in heads:
130
 
                raise NoSuchRef(name)
131
 
            self._ref = heads[name]
132
 
        bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None, 
133
 
                             lambda x: mutter("git: %s" % x))
134
 
        super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
 
283
        self._ref = None
 
284
        super(RemoteGitBranch, self).__init__(bzrdir, repository, name, 
 
285
                lockfiles)
 
286
 
 
287
    def revision_history(self):
 
288
        raise GitSmartRemoteNotSupported()
135
289
 
136
290
    def last_revision(self):
137
 
        return self.mapping.revision_id_foreign_to_bzr(self._ref)
 
291
        return self.mapping.revision_id_foreign_to_bzr(self.head)
 
292
 
 
293
    @property
 
294
    def head(self):
 
295
        if self._ref is not None:
 
296
            return self._ref
 
297
        heads = self.repository.get_refs()
 
298
        if not self.name in heads:
 
299
            raise NoSuchRef(name)
 
300
        self._ref = heads[self.name]
 
301
        return self._ref
138
302
 
139
303
    def _synchronize_history(self, destination, revision_id):
140
304
        """See Branch._synchronize_history()."""