mercurial/httprepo.py
author Greg Ward <greg@gerg.ca>
Fri, 30 Sep 2011 21:58:54 -0400
changeset 15183 59e8bc22506e
parent 15159 85322c19c831
child 15246 7b15dd9125b3
permissions -rw-r--r--
rollback: avoid unsafe rollback when not at tip (issue2998) You can get into trouble if you commit, update back to an older changeset, and then rollback. The update removes your valuable changes from the working dir, then rollback removes them history. Oops: you've just irretrievably lost data running nothing but core Mercurial commands. (More subtly: rollback from a shared clone that was already at an older changeset -- no update required, just rollback from the wrong directory.) The fix assumes that only "commit" transactions have irreplaceable data, and allows rolling back non-commit transactions as always. But when rolling back a commit, check that the working dir is checked out to tip, i.e. the changeset we're about to destroy. If not, abort. You can get back the old (dangerous) behaviour with --force.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1089
142b5d5ec9cc Break apart hg.py
mpm@selenic.com
parents: 1072
diff changeset
     1
# httprepo.py - HTTP repository proxy classes for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     2
#
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2740
diff changeset
     3
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2740
diff changeset
     4
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     5
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8206
diff changeset
     6
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9878
diff changeset
     7
# GNU General Public License version 2 or any later version.
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     8
12062
c327bfa5e831 cleanup: remove unused imports
Brodie Rao <brodie@bitheap.org>
parents: 11759
diff changeset
     9
from node import nullid
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
    10
from i18n import _
14244
e7525a555a64 url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents: 14149
diff changeset
    11
import changegroup, statichttprepo, error, httpconnection, url, util, wireproto
13819
d16894e29f91 httprepo/sshrepo: use url.url
Brodie Rao <brodie@bitheap.org>
parents: 13603
diff changeset
    12
import os, urllib, urllib2, zlib, httplib
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
    13
import errno, socket
4678
a814a5b11fff Work around urllib2 digest auth bug with Python < 2.5
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4633
diff changeset
    14
3661
e99ba8726bda remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents: 3614
diff changeset
    15
def zgenerator(f):
e99ba8726bda remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents: 3614
diff changeset
    16
    zd = zlib.decompressobj()
e99ba8726bda remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents: 3614
diff changeset
    17
    try:
e99ba8726bda remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents: 3614
diff changeset
    18
        for chunk in util.filechunkiter(f):
11757
65bd4b8e48bd httprepo: decompress stream incrementally to reduce memory usage
Matt Mackall <mpm@selenic.com>
parents: 11370
diff changeset
    19
            while chunk:
65bd4b8e48bd httprepo: decompress stream incrementally to reduce memory usage
Matt Mackall <mpm@selenic.com>
parents: 11370
diff changeset
    20
                yield zd.decompress(chunk, 2**18)
65bd4b8e48bd httprepo: decompress stream incrementally to reduce memory usage
Matt Mackall <mpm@selenic.com>
parents: 11370
diff changeset
    21
                chunk = zd.unconsumed_tail
7280
810ca383da9c remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7279
diff changeset
    22
    except httplib.HTTPException:
3661
e99ba8726bda remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents: 3614
diff changeset
    23
        raise IOError(None, _('connection ended unexpectedly'))
e99ba8726bda remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents: 3614
diff changeset
    24
    yield zd.flush()
e99ba8726bda remove duplicate zgenerator in httprepo
Matt Mackall <mpm@selenic.com>
parents: 3614
diff changeset
    25
11587
a036f6bd1da3 protocol: unify basic http client requests
Matt Mackall <mpm@selenic.com>
parents: 11567
diff changeset
    26
class httprepository(wireproto.wirerepository):
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
    27
    def __init__(self, ui, path):
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
    28
        self.path = path
2442
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    29
        self.caps = None
4132
0d94e4a3ddb4 Close keepalive connections to fix server traceback
Andrei Vermel <avermel@mail.ru>
parents: 4025
diff changeset
    30
        self.handler = None
14076
924c82157d46 url: move URL parsing functions into util to improve startup time
Brodie Rao <brodie@bitheap.org>
parents: 14060
diff changeset
    31
        u = util.url(path)
13819
d16894e29f91 httprepo/sshrepo: use url.url
Brodie Rao <brodie@bitheap.org>
parents: 13603
diff changeset
    32
        if u.query or u.fragment:
2337
3f24bc5dee81 http: fix many problems with url parsing and auth. added proxy test.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2336
diff changeset
    33
            raise util.Abort(_('unsupported URL component: "%s"') %
13819
d16894e29f91 httprepo/sshrepo: use url.url
Brodie Rao <brodie@bitheap.org>
parents: 13603
diff changeset
    34
                             (u.query or u.fragment))
2337
3f24bc5dee81 http: fix many problems with url parsing and auth. added proxy test.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2336
diff changeset
    35
3f24bc5dee81 http: fix many problems with url parsing and auth. added proxy test.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2336
diff changeset
    36
        # urllib cannot handle URLs with embedded user or passwd
13819
d16894e29f91 httprepo/sshrepo: use url.url
Brodie Rao <brodie@bitheap.org>
parents: 13603
diff changeset
    37
        self._url, authinfo = u.authinfo()
7270
2db33c1a5654 factor out the url handling from httprepo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7269
diff changeset
    38
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
    39
        self.ui = ui
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 8563
diff changeset
    40
        self.ui.debug('using %s\n' % self._url)
2337
3f24bc5dee81 http: fix many problems with url parsing and auth. added proxy test.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2336
diff changeset
    41
7270
2db33c1a5654 factor out the url handling from httprepo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7269
diff changeset
    42
        self.urlopener = url.opener(ui, authinfo)
4516
96d8a56d4ef9 Removed trailing whitespace and tabs from python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4369
diff changeset
    43
7752
998fc8f62539 close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents: 7641
diff changeset
    44
    def __del__(self):
998fc8f62539 close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents: 7641
diff changeset
    45
        for h in self.urlopener.handlers:
998fc8f62539 close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents: 7641
diff changeset
    46
            h.close()
14955
6349a9eb0178 httprepo: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14648
diff changeset
    47
            getattr(h, "close_all", lambda : None)()
7752
998fc8f62539 close sockets on httprepository deletion (issue1487)
Steve Borho <steve@borho.org>
parents: 7641
diff changeset
    48
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
    49
    def url(self):
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
    50
        return self.path
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
    51
2442
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    52
    # look up capabilities only when needed
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    53
13603
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
    54
    def _fetchcaps(self):
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
    55
        self.caps = set(self._call('capabilities').split())
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
    56
2442
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    57
    def get_caps(self):
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    58
        if self.caps is None:
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    59
            try:
13603
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
    60
                self._fetchcaps()
7637
1d54e2f6c0b7 error: move repo errors
Matt Mackall <mpm@selenic.com>
parents: 7342
diff changeset
    61
            except error.RepoError:
8150
bbc24c0753a0 util: use built-in set and frozenset
Martin Geisler <mg@lazybytes.net>
parents: 8055
diff changeset
    62
                self.caps = set()
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 8563
diff changeset
    63
            self.ui.debug('capabilities: %s\n' %
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
    64
                          (' '.join(self.caps or ['none'])))
2442
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    65
        return self.caps
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    66
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    67
    capabilities = property(get_caps)
c660691fb45d http: query server for capabilities
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
    68
1870
8a8ab47cccde make push over http print good error message.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1736
diff changeset
    69
    def lock(self):
8a8ab47cccde make push over http print good error message.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1736
diff changeset
    70
        raise util.Abort(_('operation not supported over http'))
8a8ab47cccde make push over http print good error message.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1736
diff changeset
    71
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
    72
    def _callstream(self, cmd, **args):
13006
ea68947ad0ce httprepo: remove is-comparison with string literal
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 12969
diff changeset
    73
        if cmd == 'pushkey':
12969
6bd9778ae749 pushkey: force HTTP POST on push and add tests (issue2489)
Matt Mackall <mpm@selenic.com>
parents: 12062
diff changeset
    74
            args['data'] = ''
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
    75
        data = args.pop('data', None)
15152
94b200a11cf7 http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents: 14991
diff changeset
    76
        size = 0
94b200a11cf7 http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents: 14991
diff changeset
    77
        if util.safehasattr(data, 'length'):
94b200a11cf7 http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents: 14991
diff changeset
    78
            size = data.length
94b200a11cf7 http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents: 14991
diff changeset
    79
        elif data is not None:
94b200a11cf7 http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents: 14991
diff changeset
    80
            size = len(data)
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
    81
        headers = args.pop('headers', {})
14245
13d44e4235f8 httprepo: send 100-continue on POSTs if using http2
Augie Fackler <durin42@gmail.com>
parents: 14244
diff changeset
    82
15152
94b200a11cf7 http: handle push of bundles > 2 GB again (issue3017)
Mads Kiilerich <mads@kiilerich.com>
parents: 14991
diff changeset
    83
        if size and self.ui.configbool('ui', 'usehttp2', False):
14245
13d44e4235f8 httprepo: send 100-continue on POSTs if using http2
Augie Fackler <durin42@gmail.com>
parents: 14244
diff changeset
    84
            headers['Expect'] = '100-Continue'
14991
4f39610996fa http2: send an extra header to signal a non-broken client
Augie Fackler <durin42@gmail.com>
parents: 14648
diff changeset
    85
            headers['X-HgHttp2'] = '1'
14245
13d44e4235f8 httprepo: send 100-continue on POSTs if using http2
Augie Fackler <durin42@gmail.com>
parents: 14244
diff changeset
    86
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 8563
diff changeset
    87
        self.ui.debug("sending %s command\n" % cmd)
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    88
        q = [('cmd', cmd)]
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    89
        headersize = 0
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    90
        if len(args) > 0:
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    91
            httpheader = self.capable('httpheader')
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    92
            if httpheader:
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    93
                headersize = int(httpheader.split(',')[0])
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    94
        if headersize > 0:
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    95
            # The headers can typically carry more data than the URL.
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    96
            encargs = urllib.urlencode(sorted(args.items()))
14094
d10c6835497e http: minor tweaks to long arg handling
Matt Mackall <mpm@selenic.com>
parents: 14093
diff changeset
    97
            headerfmt = 'X-HgArg-%s'
14093
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    98
            contentlen = headersize - len(headerfmt % '000' + ': \r\n')
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
    99
            headernum = 0
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   100
            for i in xrange(0, len(encargs), contentlen):
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   101
                headernum += 1
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   102
                header = headerfmt % str(headernum)
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   103
                headers[header] = encargs[i:i + contentlen]
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   104
            varyheaders = [headerfmt % str(h) for h in range(1, headernum + 1)]
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   105
            headers['Vary'] = ','.join(varyheaders)
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   106
        else:
ce99d887585f httprepo: long arguments support (issue2126)
Steven Brown <StevenGBrown@gmail.com>
parents: 14076
diff changeset
   107
            q += sorted(args.items())
3562
88b4755fa48f httprepo: record the url after a request, makes pull + redirect works
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3445
diff changeset
   108
        qs = '?%s' % urllib.urlencode(q)
88b4755fa48f httprepo: record the url after a request, makes pull + redirect works
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3445
diff changeset
   109
        cu = "%s%s" % (self._url, qs)
10491
d7e582cab6b6 http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
   110
        req = urllib2.Request(cu, data, headers)
d7e582cab6b6 http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
   111
        if data is not None:
d7e582cab6b6 http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
   112
            self.ui.debug("sending %s bytes\n" % size)
d7e582cab6b6 http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
   113
            req.add_unredirected_header('Content-Length', '%d' % size)
2294
ce67fa312f61 Catch urllib's HTTPException and give a meaningful error message to the user.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2281
diff changeset
   114
        try:
10491
d7e582cab6b6 http: len(x) fails if it doesn't fit into an int, use __len__() instead
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
   115
            resp = self.urlopener.open(req)
2467
4e78dc71d946 http client: better work with authorization errors, broken sockets.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2465
diff changeset
   116
        except urllib2.HTTPError, inst:
4e78dc71d946 http client: better work with authorization errors, broken sockets.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2465
diff changeset
   117
            if inst.code == 401:
4e78dc71d946 http client: better work with authorization errors, broken sockets.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2465
diff changeset
   118
                raise util.Abort(_('authorization failed'))
4e78dc71d946 http client: better work with authorization errors, broken sockets.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2465
diff changeset
   119
            raise
2294
ce67fa312f61 Catch urllib's HTTPException and give a meaningful error message to the user.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2281
diff changeset
   120
        except httplib.HTTPException, inst:
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 8563
diff changeset
   121
            self.ui.debug('http error while sending %s command\n' % cmd)
8206
cce63ef1045b ui: print_exc() -> traceback()
Matt Mackall <mpm@selenic.com>
parents: 8150
diff changeset
   122
            self.ui.traceback()
2336
f77edcffb837 http: print better error if exception happens.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2294
diff changeset
   123
            raise IOError(None, inst)
3399
5dbb3a991bbf Catch python2.3's IndexError with bogus http proxy settings. (issue203)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3223
diff changeset
   124
        except IndexError:
5dbb3a991bbf Catch python2.3's IndexError with bogus http proxy settings. (issue203)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3223
diff changeset
   125
            # this only happens with Python 2.3, later versions raise URLError
5dbb3a991bbf Catch python2.3's IndexError with bogus http proxy settings. (issue203)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3223
diff changeset
   126
            raise util.Abort(_('http error, possibly caused by proxy setting'))
3562
88b4755fa48f httprepo: record the url after a request, makes pull + redirect works
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3445
diff changeset
   127
        # record the url we got redirected to
3570
c141d07198b9 Inform the user about the new URL when being redirected via http.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3569
diff changeset
   128
        resp_url = resp.geturl()
c141d07198b9 Inform the user about the new URL when being redirected via http.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3569
diff changeset
   129
        if resp_url.endswith(qs):
c141d07198b9 Inform the user about the new URL when being redirected via http.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3569
diff changeset
   130
            resp_url = resp_url[:-len(qs)]
9881
54b518fc6671 httprepo: suppress the `real URL is...' message in safe, common cases.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 9878
diff changeset
   131
        if self._url.rstrip('/') != resp_url.rstrip('/'):
14504
c59968e8b579 httprepo: send URL redirection notices to stderr (issue2828)
Matt Mackall <mpm@selenic.com>
parents: 14503
diff changeset
   132
            if not self.ui.quiet:
c59968e8b579 httprepo: send URL redirection notices to stderr (issue2828)
Matt Mackall <mpm@selenic.com>
parents: 14503
diff changeset
   133
                self.ui.warn(_('real URL is %s\n') % resp_url)
10208
37c4ce51a12d httprepo: always store the response url (issue1968)
Steve Borho <steve@borho.org>
parents: 9881
diff changeset
   134
        self._url = resp_url
2435
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   135
        try:
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   136
            proto = resp.getheader('content-type')
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   137
        except AttributeError:
14503
4e958f2a193f httprepo: proper handling of invalid responses without content-type (issue2019)
Mads Kiilerich <mads@kiilerich.com>
parents: 13115
diff changeset
   138
            proto = resp.headers.get('content-type', '')
752
c693eafd5967 Simplify content type checking
mpm@selenic.com
parents: 751
diff changeset
   139
14076
924c82157d46 url: move URL parsing functions into util to improve startup time
Brodie Rao <brodie@bitheap.org>
parents: 14060
diff changeset
   140
        safeurl = util.hidepassword(self._url)
15017
f4522df38c65 wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents: 14999
diff changeset
   141
        if proto.startswith('application/hg-error'):
f4522df38c65 wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents: 14999
diff changeset
   142
            raise error.OutOfBandError(resp.read())
753
8760d0c83b9b Check protocol versions
mpm@selenic.com
parents: 752
diff changeset
   143
        # accept old "text/plain" and "application/hg-changegroup" for now
4633
ff7253a0d1da Cleanup of whitespace, indentation and line continuation.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4516
diff changeset
   144
        if not (proto.startswith('application/mercurial-') or
ff7253a0d1da Cleanup of whitespace, indentation and line continuation.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4516
diff changeset
   145
                proto.startswith('text/plain') or
ff7253a0d1da Cleanup of whitespace, indentation and line continuation.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4516
diff changeset
   146
                proto.startswith('application/hg-changegroup')):
14076
924c82157d46 url: move URL parsing functions into util to improve startup time
Brodie Rao <brodie@bitheap.org>
parents: 14060
diff changeset
   147
            self.ui.debug("requested URL: '%s'\n" % util.hidepassword(cu))
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   148
            raise error.RepoError(
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   149
                _("'%s' does not appear to be an hg repository:\n"
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   150
                  "---%%<--- (%s)\n%s\n---%%<---\n")
14503
4e958f2a193f httprepo: proper handling of invalid responses without content-type (issue2019)
Mads Kiilerich <mads@kiilerich.com>
parents: 13115
diff changeset
   151
                % (safeurl, proto or 'no content-type', resp.read()))
752
c693eafd5967 Simplify content type checking
mpm@selenic.com
parents: 751
diff changeset
   152
4012
d1e31d7f7d44 fix handling of multiple Content-type headers
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3703
diff changeset
   153
        if proto.startswith('application/mercurial-'):
d1e31d7f7d44 fix handling of multiple Content-type headers
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3703
diff changeset
   154
            try:
4356
aed9e6dceb85 Avoid float rounding errors when checking http protocol version.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4226
diff changeset
   155
                version = proto.split('-', 1)[1]
aed9e6dceb85 Avoid float rounding errors when checking http protocol version.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4226
diff changeset
   156
                version_info = tuple([int(n) for n in version.split('.')])
4012
d1e31d7f7d44 fix handling of multiple Content-type headers
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3703
diff changeset
   157
            except ValueError:
7637
1d54e2f6c0b7 error: move repo errors
Matt Mackall <mpm@selenic.com>
parents: 7342
diff changeset
   158
                raise error.RepoError(_("'%s' sent a broken Content-Type "
8053
976170068286 hide passwords in httprepo error messages
Steve Borho <steve@borho.org>
parents: 7752
diff changeset
   159
                                        "header (%s)") % (safeurl, proto))
4356
aed9e6dceb85 Avoid float rounding errors when checking http protocol version.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4226
diff changeset
   160
            if version_info > (0, 1):
7637
1d54e2f6c0b7 error: move repo errors
Matt Mackall <mpm@selenic.com>
parents: 7342
diff changeset
   161
                raise error.RepoError(_("'%s' uses newer protocol %s") %
8053
976170068286 hide passwords in httprepo error messages
Steve Borho <steve@borho.org>
parents: 7752
diff changeset
   162
                                      (safeurl, version))
753
8760d0c83b9b Check protocol versions
mpm@selenic.com
parents: 752
diff changeset
   163
752
c693eafd5967 Simplify content type checking
mpm@selenic.com
parents: 751
diff changeset
   164
        return resp
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
   165
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   166
    def _call(self, cmd, **args):
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   167
        fp = self._callstream(cmd, **args)
2435
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   168
        try:
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   169
            return fp.read()
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   170
        finally:
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   171
            # if using keepalive, allow connection to be reused
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   172
            fp.close()
ff2bac730b99 http client: support persistent connections.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2337
diff changeset
   173
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   174
    def _callpush(self, cmd, cg, **args):
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   175
        # have to stream bundle to a temp file because we do not have
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   176
        # http 1.1 chunked transfer.
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   177
3662
f4dc02d7fb71 unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents: 3661
diff changeset
   178
        types = self.capable('unbundle')
3703
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
   179
        try:
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
   180
            types = types.split(',')
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
   181
        except AttributeError:
14060
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
   182
            # servers older than d1b16a746db6 will send 'unbundle' as a
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
   183
            # boolean capability. They only support headerless/uncompressed
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
   184
            # bundles.
3703
e674cae8efee fix push over HTTP to older servers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3662
diff changeset
   185
            types = [""]
14060
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
   186
        for x in types:
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
   187
            if x in changegroup.bundletypes:
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
   188
                type = x
aaa9a5989405 bundle: more comments about the different header types, remove useless if
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13819
diff changeset
   189
                break
3613
cbf352b9a3cd Client support for hgweb unbundle with versions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3609
diff changeset
   190
3662
f4dc02d7fb71 unduplicate bundle writing code from httprepo
Matt Mackall <mpm@selenic.com>
parents: 3661
diff changeset
   191
        tempname = changegroup.writebundle(cg, None, type)
14244
e7525a555a64 url: use new http support if requested by the user
Augie Fackler <durin42@gmail.com>
parents: 14149
diff changeset
   192
        fp = httpconnection.httpsendfile(self.ui, tempname, "rb")
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   193
        headers = {'Content-Type': 'application/mercurial-0.1'}
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   194
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   195
        try:
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   196
            try:
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   197
                r = self._call(cmd, data=fp, headers=headers, **args)
14641
f2789767a2c4 http: report unexpected unparsable push responses (issue2777)
Matt Mackall <mpm@selenic.com>
parents: 14509
diff changeset
   198
                vals = r.split('\n', 1)
f2789767a2c4 http: report unexpected unparsable push responses (issue2777)
Matt Mackall <mpm@selenic.com>
parents: 14509
diff changeset
   199
                if len(vals) < 2:
14648
ba3c36cea66e http: fix variable name in unexpected response message
Matt Mackall <mpm@selenic.com>
parents: 14641
diff changeset
   200
                    raise error.ResponseError(_("unexpected response:"), r)
14641
f2789767a2c4 http: report unexpected unparsable push responses (issue2777)
Matt Mackall <mpm@selenic.com>
parents: 14509
diff changeset
   201
                return vals
2467
4e78dc71d946 http client: better work with authorization errors, broken sockets.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2465
diff changeset
   202
            except socket.error, err:
11567
34cc8b84407f removed exception args indexing (not supported by py3k)
Renato Cunha <renatoc@gmail.com>
parents: 11370
diff changeset
   203
                if err.args[0] in (errno.ECONNRESET, errno.EPIPE):
34cc8b84407f removed exception args indexing (not supported by py3k)
Renato Cunha <renatoc@gmail.com>
parents: 11370
diff changeset
   204
                    raise util.Abort(_('push failed: %s') % err.args[1])
34cc8b84407f removed exception args indexing (not supported by py3k)
Renato Cunha <renatoc@gmail.com>
parents: 11370
diff changeset
   205
                raise util.Abort(err.args[1])
2465
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   206
        finally:
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   207
            fp.close()
c91118f425d0 push over http: client support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2447
diff changeset
   208
            os.unlink(tempname)
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2435
diff changeset
   209
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   210
    def _abort(self, exception):
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   211
        raise exception
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2569
diff changeset
   212
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   213
    def _decompress(self, stream):
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   214
        return util.chunkbuffer(zgenerator(stream))
11370
db3f6f0e4e7d pushkey: add http support
Matt Mackall <mpm@selenic.com>
parents: 11153
diff changeset
   215
923
c7a3b88505cd Add basic https support for pull
mpm@selenic.com
parents: 919
diff changeset
   216
class httpsrepository(httprepository):
2569
52ce0d6bc375 HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2557
diff changeset
   217
    def __init__(self, ui, path):
7279
1f0f84660dea Fix https availability checking
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7270
diff changeset
   218
        if not url.has_https:
2569
52ce0d6bc375 HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2557
diff changeset
   219
            raise util.Abort(_('Python support for SSL and HTTPS '
52ce0d6bc375 HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2557
diff changeset
   220
                               'is not installed'))
52ce0d6bc375 HTTPS: fix python2.3, persistent connections, don't explode if SSL is not available
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2557
diff changeset
   221
        httprepository.__init__(self, ui, path)
2740
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2673
diff changeset
   222
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2673
diff changeset
   223
def instance(ui, path, create):
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2673
diff changeset
   224
    if create:
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2673
diff changeset
   225
        raise util.Abort(_('cannot create new http repository'))
7211
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
   226
    try:
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
   227
        if path.startswith('https:'):
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
   228
            inst = httpsrepository(ui, path)
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
   229
        else:
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
   230
            inst = httprepository(ui, path)
13603
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
   231
        try:
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
   232
            # Try to do useful work when checking compatibility.
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
   233
            # Usually saves a roundtrip since we want the caps anyway.
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
   234
            inst._fetchcaps()
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
   235
        except error.RepoError:
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
   236
            # No luck, try older compatibility check.
395a84f78736 httprepo: use caps instead of between for compat check
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13555
diff changeset
   237
            inst.between([(nullid, nullid)])
7211
25c0dee16ee0 Autodetect static-http
Matt Mackall <mpm@selenic.com>
parents: 7207
diff changeset
   238
        return inst
14148
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
   239
    except error.RepoError, httpexception:
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
   240
        try:
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
   241
            r = statichttprepo.instance(ui, "static-" + path, create)
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
   242
            ui.note('(falling back to static-http)\n')
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
   243
            return r
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
   244
        except error.RepoError:
cc9366a3751b httprepo: use the original exception after falling back to static-http failed
Mads Kiilerich <mads@kiilerich.com>
parents: 14094
diff changeset
   245
            raise httpexception # use the original http RepoError instead