/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

Escape slashes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
from bzrlib import (
18
18
    config,
19
19
    debug,
20
 
    tag,
21
20
    trace,
22
21
    ui,
23
22
    urlutils,
27
26
    InvalidRevisionId,
28
27
    NoSuchFile,
29
28
    NoSuchRevision,
 
29
    NotBranchError,
30
30
    NotLocalUrl,
 
31
    UninitializableFormat,
31
32
    )
32
33
from bzrlib.transport import (
33
34
    Transport,
40
41
 
41
42
from bzrlib.plugins.git.branch import (
42
43
    GitBranch,
 
44
    GitTags,
 
45
    )
 
46
from bzrlib.plugins.git.dir import (
 
47
    GitControlDirFormat,
 
48
    GitDir,
 
49
    GitLockableFiles,
 
50
    GitLock,
43
51
    )
44
52
from bzrlib.plugins.git.errors import (
45
53
    GitSmartRemoteNotSupported,
46
54
    NoSuchRef,
47
55
    )
48
 
from bzrlib.plugins.git.dir import (
49
 
    GitDir,
50
 
    )
51
56
from bzrlib.plugins.git.mapping import (
52
57
    mapping_registry,
53
58
    )
59
64
    branch_name_to_ref,
60
65
    )
61
66
 
62
 
import dulwich as git
 
67
import dulwich
 
68
import dulwich.client
63
69
from dulwich.errors import (
64
70
    GitProtocolError,
65
71
    )
66
72
from dulwich.pack import (
67
73
    Pack,
68
 
    ThinPackData,
 
74
    PackData,
69
75
    )
70
76
import os
71
77
import tempfile
97
103
    return (host, port, username, path)
98
104
 
99
105
 
 
106
def parse_git_error(url, message):
 
107
    """Parse a remote git server error and return a bzr exception.
 
108
 
 
109
    :param url: URL of the remote repository
 
110
    :param message: Message sent by the remote git server
 
111
    """
 
112
    message = str(message).strip()
 
113
    if message.startswith("Could not find Repository "):
 
114
        return NotBranchError(url, message)
 
115
    # Don't know, just return it to the user as-is
 
116
    return BzrError(message)
 
117
 
 
118
 
100
119
class GitSmartTransport(Transport):
101
120
 
102
121
    def __init__(self, url, _client=None):
118
137
        raise NotImplementedError(self._get_client)
119
138
 
120
139
    def _get_path(self):
121
 
        return self._path
122
 
 
123
 
    def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
124
 
        if progress is None:
125
 
            def progress(text):
126
 
                trace.info("git: %s" % text)
127
 
        client = self._get_client(thin_packs=False)
128
 
        try:
129
 
            return client.fetch_pack(self._get_path(), determine_wants,
130
 
                graph_walker, pack_data, progress)
131
 
        except GitProtocolError, e:
132
 
            raise BzrError(e)
133
 
 
134
 
    def send_pack(self, get_changed_refs, generate_pack_contents):
135
 
        client = self._get_client(thin_packs=False)
136
 
        try:
137
 
            return client.send_pack(self._get_path(), get_changed_refs,
138
 
                generate_pack_contents)
139
 
        except GitProtocolError, e:
140
 
            raise BzrError(e)
 
140
        return urlutils.split_segment_parameters_raw(self._path)[0]
141
141
 
142
142
    def get(self, path):
143
143
        raise NoSuchFile(path)
164
164
            ret = self._client
165
165
            self._client = None
166
166
            return ret
167
 
        return git.client.TCPGitClient(self._host, self._port,
 
167
        return dulwich.client.TCPGitClient(self._host, self._port,
168
168
            thin_packs=thin_packs, report_activity=self._report_activity)
169
169
 
170
170
 
173
173
    _scheme = 'git+ssh'
174
174
 
175
175
    def _get_path(self):
176
 
        if self._path.startswith("/~/"):
177
 
            return self._path[3:]
178
 
        return self._path
 
176
        path = urlutils.split_segment_parameters_raw(self._path)[0]
 
177
        if path.startswith("/~/"):
 
178
            return path[3:]
 
179
        return path
179
180
 
180
181
    def _get_client(self, thin_packs):
181
182
        if self._client is not None:
183
184
            self._client = None
184
185
            return ret
185
186
        location_config = config.LocationConfig(self.base)
186
 
        client = git.client.SSHGitClient(self._host, self._port, self._username,
 
187
        client = dulwich.client.SSHGitClient(self._host, self._port, self._username,
187
188
            thin_packs=thin_packs, report_activity=self._report_activity)
188
189
        # Set up alternate pack program paths
189
190
        upload_pack = location_config.get_user_option('git_upload_pack')
197
198
 
198
199
class RemoteGitDir(GitDir):
199
200
 
200
 
    def __init__(self, transport, lockfiles, format):
 
201
    def __init__(self, transport, lockfiles, format, get_client, client_path):
201
202
        self._format = format
202
203
        self.root_transport = transport
203
204
        self.transport = transport
204
205
        self._lockfiles = lockfiles
205
206
        self._mode_check_done = None
206
 
 
207
 
    def _branch_name_to_ref(self, name, default=None):
208
 
        return branch_name_to_ref(name, default=default)
 
207
        self._get_client = get_client
 
208
        self._client_path = client_path
 
209
 
 
210
    def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
 
211
        if progress is None:
 
212
            def progress(text):
 
213
                trace.info("git: %s" % text)
 
214
        client = self._get_client(thin_packs=False)
 
215
        try:
 
216
            return client.fetch_pack(self._client_path, determine_wants,
 
217
                graph_walker, pack_data, progress)
 
218
        except GitProtocolError, e:
 
219
            raise parse_git_error(self.transport.external_url(), e)
 
220
 
 
221
    def send_pack(self, get_changed_refs, generate_pack_contents):
 
222
        client = self._get_client(thin_packs=False)
 
223
        try:
 
224
            return client.send_pack(self._client_path, get_changed_refs,
 
225
                generate_pack_contents)
 
226
        except GitProtocolError, e:
 
227
            raise parse_git_error(self.transport.external_url(), e)
 
228
 
 
229
    @property
 
230
    def user_url(self):
 
231
        return self.control_url
 
232
 
 
233
    @property
 
234
    def user_transport(self):
 
235
        return self.root_transport
209
236
 
210
237
    def open_repository(self):
211
238
        return RemoteGitRepository(self, self._lockfiles)
212
239
 
213
 
    def _open_branch(self, name=None, ignore_fallbacks=False, 
214
 
                    unsupported=False):
 
240
    def open_branch(self, name=None, unsupported=False,
 
241
            ignore_fallbacks=False):
215
242
        repo = self.open_repository()
216
 
        refname = self._branch_name_to_ref(name)
 
243
        refname = self._get_selected_ref(name)
217
244
        return RemoteGitBranch(self, repo, refname, self._lockfiles)
218
245
 
219
246
    def open_workingtree(self, recommend_upgrade=False):
235
262
    @property
236
263
    def data(self):
237
264
        if self._data is None:
238
 
            self._data = ThinPackData(self.resolve_ext_ref, self._data_path)
 
265
            self._data = PackData(self._data_path)
239
266
        return self._data
240
267
 
241
268
    @property
262
289
            os.remove(self._data_path)
263
290
 
264
291
 
 
292
class BzrGitHttpClient(dulwich.client.HttpGitClient):
 
293
 
 
294
    def __init__(self, transport, *args, **kwargs):
 
295
        self.transport = transport
 
296
        super(BzrGitHttpClient, self).__init__(transport.external_url(), *args, **kwargs)
 
297
        import urllib2
 
298
        self._http_perform = getattr(self.transport, "_perform", urllib2.urlopen)
 
299
 
 
300
    def _perform(self, req):
 
301
        req.accepted_errors = (200, 404)
 
302
        req.follow_redirections = True
 
303
        req.redirected_to = None
 
304
        return self._http_perform(req)
 
305
 
 
306
 
 
307
class RemoteGitControlDirFormat(GitControlDirFormat):
 
308
    """The .git directory control format."""
 
309
 
 
310
    supports_workingtrees = False
 
311
 
 
312
    @classmethod
 
313
    def _known_formats(self):
 
314
        return set([RemoteGitControlDirFormat()])
 
315
 
 
316
    def open(self, transport, _found=None):
 
317
        """Open this directory.
 
318
 
 
319
        """
 
320
        # we dont grok readonly - git isn't integrated with transport.
 
321
        url = transport.base
 
322
        if url.startswith('readonly+'):
 
323
            url = url[len('readonly+'):]
 
324
        if isinstance(transport, GitSmartTransport):
 
325
            get_client = transport._get_client
 
326
            client_path = transport._get_path()
 
327
        elif urlparse.urlsplit(transport.external_url())[0] in ("http", "https"):
 
328
            def get_client(thin_packs=False):
 
329
                return BzrGitHttpClient(transport, thin_packs=thin_packs)
 
330
            client_path = transport._path
 
331
        else:
 
332
            raise NotBranchError(transport.base)
 
333
        lockfiles = GitLockableFiles(transport, GitLock())
 
334
        return RemoteGitDir(transport, lockfiles, self, get_client, client_path)
 
335
 
 
336
    def get_format_description(self):
 
337
        return "Remote Git Repository"
 
338
 
 
339
    def initialize_on_transport(self, transport):
 
340
        raise UninitializableFormat(self)
 
341
 
 
342
 
265
343
class RemoteGitRepository(GitRepository):
266
344
 
267
345
    def __init__(self, gitdir, lockfiles):
269
347
        self._refs = None
270
348
 
271
349
    @property
272
 
    def inventories(self):
273
 
        raise GitSmartRemoteNotSupported()
274
 
 
275
 
    @property
276
 
    def revisions(self):
277
 
        raise GitSmartRemoteNotSupported()
278
 
 
279
 
    @property
280
 
    def texts(self):
 
350
    def user_url(self):
 
351
        return self.control_url
 
352
 
 
353
    def get_parent_map(self, revids):
281
354
        raise GitSmartRemoteNotSupported()
282
355
 
283
356
    def get_refs(self):
284
357
        if self._refs is not None:
285
358
            return self._refs
286
 
        self._refs = self.bzrdir.root_transport.fetch_pack(lambda x: [], None,
 
359
        self._refs = self.bzrdir.fetch_pack(lambda x: [], None,
287
360
            lambda x: None, lambda x: trace.mutter("git: %s" % x))
288
361
        return self._refs
289
362
 
290
363
    def fetch_pack(self, determine_wants, graph_walker, pack_data,
291
364
                   progress=None):
292
 
        return self._transport.fetch_pack(determine_wants, graph_walker,
 
365
        return self.bzrdir.fetch_pack(determine_wants, graph_walker,
293
366
                                          pack_data, progress)
294
367
 
295
368
    def send_pack(self, get_changed_refs, generate_pack_contents):
296
 
        return self._transport.send_pack(get_changed_refs, generate_pack_contents)
 
369
        return self.bzrdir.send_pack(get_changed_refs, generate_pack_contents)
297
370
 
298
371
    def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref,
299
372
                      progress=None):
300
373
        fd, path = tempfile.mkstemp(suffix=".pack")
301
 
        self.fetch_pack(determine_wants, graph_walker,
302
 
            lambda x: os.write(fd, x), progress)
303
 
        os.close(fd)
 
374
        try:
 
375
            self.fetch_pack(determine_wants, graph_walker,
 
376
                lambda x: os.write(fd, x), progress)
 
377
        finally:
 
378
            os.close(fd)
304
379
        if os.path.getsize(path) == 0:
305
380
            return EmptyObjectStoreIterator()
306
381
        return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
322
397
        return mapping.revision_id_foreign_to_bzr(foreign_revid)
323
398
 
324
399
 
325
 
class RemoteGitTagDict(tag.BasicTags):
326
 
 
327
 
    def __init__(self, branch):
328
 
        self.branch = branch
329
 
        self.repository = branch.repository
330
 
 
331
 
    def get_tag_dict(self):
332
 
        tags = {}
333
 
        for k, v in extract_tags(self.repository.get_refs()).iteritems():
334
 
            tags[k] = self.branch.mapping.revision_id_foreign_to_bzr(v)
335
 
        return tags
 
400
class RemoteGitTagDict(GitTags):
 
401
 
 
402
    def get_refs(self):
 
403
        return self.repository.get_refs()
 
404
 
 
405
    def _iter_tag_refs(self, refs):
 
406
        for k, (peeled, unpeeled) in extract_tags(refs).iteritems():
 
407
            yield (k, peeled, unpeeled,
 
408
                  self.branch.mapping.revision_id_foreign_to_bzr(peeled))
336
409
 
337
410
    def set_tag(self, name, revid):
338
411
        # FIXME: Not supported yet, should do a push of a new ref
346
419
        super(RemoteGitBranch, self).__init__(bzrdir, repository, name,
347
420
                lockfiles)
348
421
 
 
422
    def last_revision_info(self):
 
423
        raise GitSmartRemoteNotSupported()
 
424
 
 
425
    @property
 
426
    def user_url(self):
 
427
        return self.control_url
 
428
 
 
429
    @property
 
430
    def control_url(self):
 
431
        return self.base
 
432
 
349
433
    def revision_history(self):
350
434
        raise GitSmartRemoteNotSupported()
351
435
 
365
449
        if self._sha is not None:
366
450
            return self._sha
367
451
        heads = self.repository.get_refs()
368
 
        name = self.bzrdir._branch_name_to_ref(self.name, "HEAD")
 
452
        name = branch_name_to_ref(self.name, "HEAD")
369
453
        if name in heads:
370
454
            self._sha = heads[name]
371
455
        else: