~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/__init__.py

  • Committer: Vincent Ladeuil
  • Date: 2011-11-24 15:48:29 UTC
  • mfrom: (6289 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6337.
  • Revision ID: v.ladeuil+lp@free.fr-20111124154829-avowjpsxdl8yp2vz
merge trunk resolving conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
"""
21
21
 
22
22
from cStringIO import StringIO
23
 
import mimetools
24
23
import re
25
24
import urlparse
26
25
import urllib
35
34
    urlutils,
36
35
    )
37
36
from bzrlib.smart import medium
38
 
from bzrlib.symbol_versioning import (
39
 
        deprecated_method,
40
 
        )
41
37
from bzrlib.trace import mutter
42
38
from bzrlib.transport import (
43
39
    ConnectedTransport,
44
 
    _CoalescedOffset,
45
 
    Transport,
46
40
    )
47
41
 
48
42
# TODO: This is not used anymore by HttpTransport_urllib
148
142
 
149
143
        user and passwords are not embedded in the path provided to the server.
150
144
        """
151
 
        relative = urlutils.unescape(relpath).encode('utf-8')
152
 
        path = self._combine_paths(self._path, relative)
153
 
        return self._unsplit_url(self._unqualified_scheme,
154
 
                                 None, None, self._host, self._port, path)
 
145
        url = self._parsed_url.clone(relpath)
 
146
        url.user = url.quoted_user = None
 
147
        url.password = url.quoted_password = None
 
148
        url.scheme = self._unqualified_scheme
 
149
        return str(url)
155
150
 
156
151
    def _create_auth(self):
157
152
        """Returns a dict containing the credentials provided at build time."""
158
 
        auth = dict(host=self._host, port=self._port,
159
 
                    user=self._user, password=self._password,
 
153
        auth = dict(host=self._parsed_url.host, port=self._parsed_url.port,
 
154
                    user=self._parsed_url.user, password=self._parsed_url.password,
160
155
                    protocol=self._unqualified_scheme,
161
 
                    path=self._path)
 
156
                    path=self._parsed_url.path)
162
157
        return auth
163
158
 
164
159
    def get_smart_medium(self):
412
407
        """See bzrlib.transport.Transport.external_url."""
413
408
        # HTTP URL's are externally usable as long as they don't mention their
414
409
        # implementation qualifier
415
 
        return self._unsplit_url(self._unqualified_scheme,
416
 
                                 self._user, self._password,
417
 
                                 self._host, self._port,
418
 
                                 self._path)
 
410
        url = self._parsed_url.clone()
 
411
        url.scheme = self._unqualified_scheme
 
412
        return str(url)
419
413
 
420
414
    def is_readonly(self):
421
415
        """See Transport.is_readonly."""
517
511
 
518
512
        :returns: A transport or None.
519
513
        """
520
 
        def relpath(abspath):
521
 
            """Returns the path relative to our base.
522
 
 
523
 
            The constraints are weaker than the real relpath method because the
524
 
            abspath is coming from the server and may slightly differ from our
525
 
            base. We don't check the scheme, host, port, user, password parts,
526
 
            relying on the caller to give us a proper url (i.e. one returned by
527
 
            the server mirroring the one we sent).
528
 
            """
529
 
            (scheme,
530
 
             user, password,
531
 
             host, port,
532
 
             path) = self._split_url(abspath)
533
 
            pl = len(self._path)
534
 
            return path[pl:].strip('/')
535
 
 
536
 
        relpath = relpath(source)
537
 
        if not target.endswith(relpath):
 
514
        parsed_source = self._split_url(source)
 
515
        parsed_target = self._split_url(target)
 
516
        pl = len(self._parsed_url.path)
 
517
        # determine the excess tail - the relative path that was in
 
518
        # the original request but not part of this transports' URL.
 
519
        excess_tail = parsed_source.path[pl:].strip("/")
 
520
        if not target.endswith(excess_tail):
538
521
            # The final part of the url has been renamed, we can't handle the
539
522
            # redirection.
540
523
            return None
541
 
        new_transport = None
542
 
        (scheme,
543
 
         user, password,
544
 
         host, port,
545
 
         path) = self._split_url(target)
546
 
        # Recalculate base path. This is needed to ensure that when the
547
 
        # redirected tranport will be used to re-try whatever request was
548
 
        # redirected, we end up with the same url
549
 
        base_path = path[:-len(relpath)]
550
 
        if scheme in ('http', 'https'):
 
524
 
 
525
        target_path = parsed_target.path
 
526
        if excess_tail:
 
527
            # Drop the tail that was in the redirect but not part of
 
528
            # the path of this transport.
 
529
            target_path = target_path[:-len(excess_tail)]
 
530
 
 
531
        if parsed_target.scheme in ('http', 'https'):
551
532
            # Same protocol family (i.e. http[s]), we will preserve the same
552
533
            # http client implementation when a redirection occurs from one to
553
534
            # the other (otherwise users may be surprised that bzr switches
554
535
            # from one implementation to the other, and devs may suffer
555
536
            # debugging it).
556
 
            if (scheme == self._unqualified_scheme
557
 
                and host == self._host
558
 
                and port == self._port
559
 
                and (user is None or user == self._user)):
 
537
            if (parsed_target.scheme == self._unqualified_scheme
 
538
                and parsed_target.host == self._parsed_url.host
 
539
                and parsed_target.port == self._parsed_url.port
 
540
                and (parsed_target.user is None or
 
541
                     parsed_target.user == self._parsed_url.user)):
560
542
                # If a user is specified, it should match, we don't care about
561
543
                # passwords, wrong passwords will be rejected anyway.
562
 
                new_transport = self.clone(base_path)
 
544
                return self.clone(target_path)
563
545
            else:
564
546
                # Rebuild the url preserving the scheme qualification and the
565
547
                # credentials (if they don't apply, the redirected to server
566
548
                # will tell us, but if they do apply, we avoid prompting the
567
549
                # user)
568
 
                redir_scheme = scheme + '+' + self._impl_name
 
550
                redir_scheme = parsed_target.scheme + '+' + self._impl_name
569
551
                new_url = self._unsplit_url(redir_scheme,
570
 
                                            self._user, self._password,
571
 
                                            host, port,
572
 
                                            base_path)
573
 
                new_transport = transport.get_transport(new_url)
 
552
                    self._parsed_url.user,
 
553
                    self._parsed_url.password,
 
554
                    parsed_target.host, parsed_target.port,
 
555
                    target_path)
 
556
                return transport.get_transport_from_url(new_url)
574
557
        else:
575
558
            # Redirected to a different protocol
576
 
            new_url = self._unsplit_url(scheme,
577
 
                                        user, password,
578
 
                                        host, port,
579
 
                                        base_path)
580
 
            new_transport = transport.get_transport(new_url)
581
 
        return new_transport
 
559
            new_url = self._unsplit_url(parsed_target.scheme,
 
560
                    parsed_target.user,
 
561
                    parsed_target.password,
 
562
                    parsed_target.host, parsed_target.port,
 
563
                    target_path)
 
564
            return transport.get_transport_from_url(new_url)
582
565
 
583
566
 
584
567
# TODO: May be better located in smart/medium.py with the other
614
597
            t = self._http_transport_ref()
615
598
            code, body_filelike = t._post(bytes)
616
599
            if code != 200:
617
 
                raise InvalidHttpResponse(
 
600
                raise errors.InvalidHttpResponse(
618
601
                    t._remote_path('.bzr/smart'),
619
602
                    'Expected 200 response code, got %r' % (code,))
620
603
        except (errors.InvalidHttpResponse, errors.ConnectionReset), e: