/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

  • Committer: Jelmer Vernooij
  • Date: 2009-09-10 13:13:15 UTC
  • mto: (0.200.602 trunk)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@samba.org-20090910131315-6890xg58pl2jseml
Allow serving remote URLs.

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
 
18
from bzrlib import (
 
19
    config,
 
20
    tag,
 
21
    trace,
 
22
    ui,
 
23
    urlutils,
 
24
    )
 
25
from bzrlib.errors import (
 
26
    BzrError,
 
27
    InvalidRevisionId,
 
28
    NoSuchFile,
 
29
    NoSuchRevision,
 
30
    NotLocalUrl,
 
31
    )
 
32
from bzrlib.trace import (
 
33
    info,
 
34
    )
 
35
from bzrlib.transport import (
 
36
    Transport,
 
37
    )
25
38
 
26
 
from bzrlib.plugins.git import lazy_check_versions
 
39
from bzrlib.plugins.git import (
 
40
    lazy_check_versions,
 
41
    )
27
42
lazy_check_versions()
28
43
 
29
 
from bzrlib.plugins.git.branch import GitBranch
30
 
from bzrlib.plugins.git.errors import NoSuchRef
31
 
from bzrlib.plugins.git.dir import GitDir
32
 
from bzrlib.plugins.git.foreign import ForeignBranch
33
 
from bzrlib.plugins.git.repository import GitFormat, GitRepository
 
44
from bzrlib.plugins.git.branch import (
 
45
    GitBranch,
 
46
    extract_tags,
 
47
    )
 
48
from bzrlib.plugins.git.errors import (
 
49
    GitSmartRemoteNotSupported,
 
50
    NoSuchRef,
 
51
    )
 
52
from bzrlib.plugins.git.dir import (
 
53
    GitDir,
 
54
    )
 
55
from bzrlib.plugins.git.mapping import (
 
56
    mapping_registry,
 
57
    )
 
58
from bzrlib.plugins.git.repository import (
 
59
    GitRepository,
 
60
    )
34
61
 
 
62
import dulwich as git
 
63
from dulwich.errors import (
 
64
    GitProtocolError,
 
65
    )
 
66
from dulwich.pack import (
 
67
    Pack,
 
68
    )
35
69
import os
36
70
import tempfile
37
71
import urllib
38
72
import urlparse
39
73
 
40
 
import dulwich as git
41
 
from dulwich.pack import PackData, Pack, PackIndex
 
74
from dulwich.pack import load_pack_index
 
75
 
42
76
 
43
77
# Don't run any tests on GitSmartTransport as it is not intended to be 
44
78
# a full implementation of Transport
51
85
    def __init__(self, url, _client=None):
52
86
        Transport.__init__(self, url)
53
87
        (scheme, _, loc, _, _) = urlparse.urlsplit(url)
54
 
        assert scheme == "git"
55
88
        hostport, self._path = urllib.splithost(loc)
56
 
        (self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
 
89
        (self._username, hostport) = urllib.splituser(hostport)
 
90
        (self._host, self._port) = urllib.splitnport(hostport, None)
57
91
        self._client = _client
58
92
 
59
 
    def _get_client(self):
60
 
        if self._client is not None:
61
 
            ret = self._client
62
 
            self._client = None
63
 
            return ret
64
 
        return git.client.TCPGitClient(self._host, self._port)
 
93
    def external_url(self):
 
94
        return self.base
 
95
 
 
96
    def has(self, relpath):
 
97
        return False
 
98
 
 
99
    def _get_client(self, thin_packs):
 
100
        raise NotImplementedError(self._get_client)
 
101
 
 
102
    def _get_path(self):
 
103
        return self._path
65
104
 
66
105
    def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
67
106
        if progress is None:
68
107
            def progress(text):
69
108
                info("git: %s" % text)
70
 
        self._get_client().fetch_pack(self._path, determine_wants, 
71
 
            graph_walker, pack_data, progress)
 
109
        client = self._get_client(thin_packs=False)
 
110
        try:
 
111
            return client.fetch_pack(self._get_path(), determine_wants, 
 
112
                graph_walker, pack_data, progress)
 
113
        except GitProtocolError, e:
 
114
            raise BzrError(e)
 
115
 
 
116
    def send_pack(self, get_changed_refs, generate_pack_contents):
 
117
        client = self._get_client(thin_packs=False)
 
118
        try:
 
119
            return client.send_pack(self._get_path(), get_changed_refs, 
 
120
                generate_pack_contents)
 
121
        except GitProtocolError, e:
 
122
            raise BzrError(e)
72
123
 
73
124
    def get(self, path):
74
125
        raise NoSuchFile(path)
83
134
        else:
84
135
            newurl = urlutils.join(self.base, offset)
85
136
 
86
 
        return GitSmartTransport(newurl, self._client)
 
137
        return self.__class__(newurl, self._client)
 
138
 
 
139
 
 
140
class TCPGitSmartTransport(GitSmartTransport):
 
141
 
 
142
    _scheme = 'git'
 
143
 
 
144
    def _get_client(self, thin_packs):
 
145
        if self._client is not None:
 
146
            ret = self._client
 
147
            self._client = None
 
148
            return ret
 
149
        return git.client.TCPGitClient(self._host, self._port, thin_packs=thin_packs,
 
150
            report_activity=self._report_activity)
 
151
 
 
152
 
 
153
class SSHGitSmartTransport(GitSmartTransport):
 
154
 
 
155
    _scheme = 'git+ssh'
 
156
 
 
157
    def _get_path(self):
 
158
        if self._path.startswith("/~/"):
 
159
            return self._path[3:]
 
160
        return self._path
 
161
 
 
162
    def _get_client(self, thin_packs):
 
163
        if self._client is not None:
 
164
            ret = self._client
 
165
            self._client = None
 
166
            return ret
 
167
        return git.client.SSHGitClient(self._host, self._port, self._username,
 
168
            thin_packs=thin_packs, report_activity=self._report_activity)
87
169
 
88
170
 
89
171
class RemoteGitDir(GitDir):
93
175
        self.root_transport = transport
94
176
        self.transport = transport
95
177
        self._lockfiles = lockfiles
 
178
        self._mode_check_done = None
96
179
 
97
180
    def open_repository(self):
98
181
        return RemoteGitRepository(self, self._lockfiles)
99
182
 
100
 
    def open_branch(self, _unsupported=False):
 
183
    def open_branch(self, ignore_fallbacks=False):
101
184
        repo = self.open_repository()
102
185
        # TODO: Support for multiple branches in one bzrdir in bzrlib!
103
186
        return RemoteGitBranch(self, repo, "HEAD", self._lockfiles)
106
189
        raise NotLocalUrl(self.transport.base)
107
190
 
108
191
 
 
192
class EmptyObjectStoreIterator(dict):
 
193
 
 
194
    def iterobjects(self):
 
195
        return []
 
196
 
 
197
 
109
198
class TemporaryPackIterator(Pack):
110
199
 
 
200
    def __init__(self, path, resolve_ext_ref):
 
201
        super(TemporaryPackIterator, self).__init__(path)
 
202
        self.resolve_ext_ref = resolve_ext_ref
 
203
 
111
204
    @property
112
 
    def idx(self):
 
205
    def index(self):
113
206
        if self._idx is None:
114
 
            self._data.create_index_v2(self._idx_path)
115
 
            self._idx = PackIndex(self._idx_path)
 
207
            if not os.path.exists(self._idx_path):
 
208
                pb = ui.ui_factory.nested_progress_bar()
 
209
                try:
 
210
                    def report_progress(cur, total):
 
211
                        pb.update("generating index", cur, total)
 
212
                    self.data.create_index(self._idx_path, self.resolve_ext_ref,
 
213
                        progress=report_progress)
 
214
                finally:
 
215
                    pb.finished()
 
216
            self._idx = load_pack_index(self._idx_path)
116
217
        return self._idx
117
218
 
118
219
    def __del__(self):
124
225
 
125
226
    def __init__(self, gitdir, lockfiles):
126
227
        GitRepository.__init__(self, gitdir, lockfiles)
 
228
        self._refs = None
 
229
 
 
230
    @property
 
231
    def inventories(self):
 
232
        raise GitSmartRemoteNotSupported()
 
233
 
 
234
    @property
 
235
    def revisions(self):
 
236
        raise GitSmartRemoteNotSupported()
 
237
 
 
238
    @property
 
239
    def texts(self):
 
240
        raise GitSmartRemoteNotSupported()
 
241
 
 
242
    def get_refs(self):
 
243
        if self._refs is not None:
 
244
            return self._refs
 
245
        self._refs = self.bzrdir.root_transport.fetch_pack(lambda x: [], None, 
 
246
            lambda x: None, lambda x: trace.mutter("git: %s" % x))
 
247
        return self._refs
127
248
 
128
249
    def fetch_pack(self, determine_wants, graph_walker, pack_data, 
129
250
                   progress=None):
130
 
        self._transport.fetch_pack(determine_wants, graph_walker, pack_data, 
131
 
            progress)
132
 
 
133
 
    def fetch_objects(self, determine_wants, graph_walker, progress=None):
 
251
        return self._transport.fetch_pack(determine_wants, graph_walker,
 
252
                                          pack_data, progress)
 
253
 
 
254
    def send_pack(self, get_changed_refs, generate_pack_contents):
 
255
        return self._transport.send_pack(get_changed_refs, generate_pack_contents)
 
256
 
 
257
    def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
134
258
        fd, path = tempfile.mkstemp(suffix=".pack")
135
259
        self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
136
260
        os.close(fd)
137
 
        return TemporaryPackIterator(path[:-len(".pack")])
 
261
        if os.path.getsize(path) == 0:
 
262
            return EmptyObjectStoreIterator()
 
263
        return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
 
264
 
 
265
    def lookup_git_revid(self, bzr_revid):
 
266
        # This won't work for any round-tripped bzr revisions, but it's a start..
 
267
        try:
 
268
            return mapping_registry.revision_id_bzr_to_foreign(bzr_revid)
 
269
        except InvalidRevisionId:
 
270
            raise NoSuchRevision(self, bzr_revid)
 
271
 
 
272
 
 
273
class RemoteGitTagDict(tag.BasicTags):
 
274
 
 
275
    def __init__(self, branch):
 
276
        self.branch = branch
 
277
        self.repository = branch.repository
 
278
 
 
279
    def get_tag_dict(self):
 
280
        return extract_tags(self.repository.get_refs(), self.branch.mapping)
 
281
 
 
282
    def set_tag(self, name, revid):
 
283
        # FIXME: Not supported yet, should do a push of a new ref
 
284
        raise NotImplementedError(self.set_tag)
138
285
 
139
286
 
140
287
class RemoteGitBranch(GitBranch):
141
288
 
142
289
    def __init__(self, bzrdir, repository, name, lockfiles):
143
 
        def determine_wants(heads):
144
 
            if not name in heads:
145
 
                raise NoSuchRef(name)
146
 
            self._ref = heads[name]
147
 
        bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None, 
148
 
                             lambda x: mutter("git: %s" % x))
149
 
        super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
 
290
        self._ref = None
 
291
        super(RemoteGitBranch, self).__init__(bzrdir, repository, name, 
 
292
                lockfiles)
 
293
 
 
294
    def revision_history(self):
 
295
        raise GitSmartRemoteNotSupported()
150
296
 
151
297
    def last_revision(self):
152
 
        return self.mapping.revision_id_foreign_to_bzr(self._ref)
 
298
        return self.mapping.revision_id_foreign_to_bzr(self.head)
 
299
 
 
300
    def _get_config(self):
 
301
        class EmptyConfig(object):
 
302
 
 
303
            def _get_configobj(self):
 
304
                return config.ConfigObj()
 
305
 
 
306
        return EmptyConfig()
 
307
 
 
308
    @property
 
309
    def head(self):
 
310
        if self._ref is not None:
 
311
            return self._ref
 
312
        heads = self.repository.get_refs()
 
313
        if not self.name in heads:
 
314
            raise NoSuchRef(self.name)
 
315
        self._ref = heads[self.name]
 
316
        return self._ref
153
317
 
154
318
    def _synchronize_history(self, destination, revision_id):
155
319
        """See Branch._synchronize_history()."""
156
320
        destination.generate_revision_history(self.last_revision())
157
321
 
 
322
    def get_push_location(self):
 
323
        return None
 
324
 
 
325
    def set_push_location(self, url):
 
326
        pass