/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

Update docs.

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.dir import GitDir
29
 
from bzrlib.plugins.git.foreign import ForeignBranch
30
 
from bzrlib.plugins.git.repository import GitFormat, GitRepository
31
 
 
 
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
    )
 
70
import os
 
71
import tempfile
32
72
import urllib
33
73
import urlparse
34
74
 
35
 
from dulwich.pack import PackData
 
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 []
36
85
 
37
86
 
38
87
class GitSmartTransport(Transport):
40
89
    def __init__(self, url, _client=None):
41
90
        Transport.__init__(self, url)
42
91
        (scheme, _, loc, _, _) = urlparse.urlsplit(url)
43
 
        assert scheme == "git"
44
92
        hostport, self._path = urllib.splithost(loc)
45
 
        (self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
46
 
        if _client is not None:
47
 
            self._client = _client
48
 
        else:
49
 
            self._client = git.client.TCPGitClient(self._host, self._port)
 
93
        (self._host, self._port) = urllib.splitnport(hostport, None)
 
94
        self._client = _client
 
95
 
 
96
    def has(self, relpath):
 
97
        return False
 
98
 
 
99
    def _get_client(self):
 
100
        raise NotImplementedError(self._get_client)
50
101
 
51
102
    def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
52
103
        if progress is None:
53
104
            def progress(text):
54
105
                info("git: %s" % text)
55
 
        self._client.fetch_pack(self._path, determine_wants, graph_walker, 
56
 
                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)
57
112
 
58
 
    def fetch_objects(self, determine_wants, graph_walker, progress=None):
59
 
        fd, path = tempfile.mkstemp(dir=self.pack_dir(), suffix=".pack")
60
 
        self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
61
 
        os.close(fd)
 
113
    def send_pack(self, get_changed_refs, generate_pack_contents):
 
114
        client = self._get_client()
62
115
        try:
63
 
            p = PackData(path)
64
 
            for o in p.iterobjects():
65
 
                yield o
66
 
        finally:
67
 
            os.remove(path)
 
116
            return client.send_pack(self._path, get_changed_refs, 
 
117
                generate_pack_contents)
 
118
        except GitProtocolError, e:
 
119
            raise BzrError(e)
68
120
 
69
121
    def get(self, path):
70
122
        raise NoSuchFile(path)
71
123
 
 
124
    def abspath(self, relpath):
 
125
        return urlutils.join(self.base, relpath)
 
126
 
72
127
    def clone(self, offset=None):
73
128
        """See Transport.clone()."""
74
129
        if offset is None:
76
131
        else:
77
132
            newurl = urlutils.join(self.base, offset)
78
133
 
79
 
        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)
80
161
 
81
162
 
82
163
class RemoteGitDir(GitDir):
86
167
        self.root_transport = transport
87
168
        self.transport = transport
88
169
        self._lockfiles = lockfiles
 
170
        self._mode_check_done = None
89
171
 
90
172
    def open_repository(self):
91
173
        return RemoteGitRepository(self, self._lockfiles)
92
174
 
93
 
    def open_branch(self):
 
175
    def open_branch(self, ignore_fallbacks=False):
94
176
        repo = self.open_repository()
95
177
        # TODO: Support for multiple branches in one bzrdir in bzrlib!
96
178
        return RemoteGitBranch(self, repo, "HEAD", self._lockfiles)
99
181
        raise NotLocalUrl(self.transport.base)
100
182
 
101
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
 
102
217
class RemoteGitRepository(GitRepository):
103
218
 
104
219
    def __init__(self, gitdir, lockfiles):
105
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
106
241
 
107
242
    def fetch_pack(self, determine_wants, graph_walker, pack_data, 
108
243
                   progress=None):
109
 
        self._transport.fetch_pack(determine_wants, graph_walker, pack_data, 
110
 
            progress)
 
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):
 
251
        fd, path = tempfile.mkstemp(suffix=".pack")
 
252
        self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
 
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..
 
260
        try:
 
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)
111
278
 
112
279
 
113
280
class RemoteGitBranch(GitBranch):
114
281
 
115
282
    def __init__(self, bzrdir, repository, name, lockfiles):
116
 
        def determine_wants(heads):
117
 
            self._ref = heads[name]
118
 
        bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None, 
119
 
                             lambda x: mutter("git: %s" % x))
120
 
        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()
121
289
 
122
290
    def last_revision(self):
123
 
        return self.mapping.revision_id_foreign_to_bzr(self._ref)
124
 
 
 
291
        return self.mapping.revision_id_foreign_to_bzr(self.head)
 
292
 
 
293
    @property
 
294
    def head(self):
 
295
        if self._ref is None:
 
296
            return self._ref
 
297
        heads = repository.get_refs()
 
298
        if not name in heads:
 
299
            raise NoSuchRef(name)
 
300
        self._ref = heads[name]
 
301
        return self._ref
 
302
 
 
303
    def _synchronize_history(self, destination, revision_id):
 
304
        """See Branch._synchronize_history()."""
 
305
        destination.generate_revision_history(self.last_revision())
 
306