comparison contrib/phabricator.py @ 34064:8b659b7388c0

phabricator: add a config to use curl for communication Not sure why, but I got `phabsend` hang on work network pretty frequently. The traceback indicates it hangs at `_sslobj.do_handshake()`: File "mercurial/sslutil.py", line 404, in wrapsocket sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname) File "/usr/lib/python2.7/ssl.py", line 363, in wrap_socket _context=self) File "/usr/lib/python2.7/ssl.py", line 611, in __init__ self.do_handshake() File "/usr/lib/python2.7/ssl.py", line 840, in do_handshake self._sslobj.do_handshake() I had tried adding `timeout` in various places but they seem not effective. It seems easier to just allow shelling out to `curl` with retry and timeout flags. This could also be helpful for people with an older Python installed without modern security (SNI). Differential Revision: https://phab.mercurial-scm.org/D605
author Jun Wu <quark@fb.com>
date Fri, 01 Sep 2017 12:13:17 -0700
parents 941c33cfde81
children a0d33f4ddff9
comparison
equal deleted inserted replaced
34063:941c33cfde81 34064:8b659b7388c0
26 26
27 # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its 27 # Repo callsign. If a repo has a URL https://$HOST/diffusion/FOO, then its
28 # callsign is "FOO". 28 # callsign is "FOO".
29 callsign = FOO 29 callsign = FOO
30 30
31 # curl command to use. If not set (default), use builtin HTTP library to
32 # communicate. If set, use the specified curl command. This could be useful
33 # if you need to specify advanced options that is not easily supported by
34 # the internal library.
35 curlcmd = curl --connect-timeout 2 --retry 3 --silent
31 """ 36 """
32 37
33 from __future__ import absolute_import 38 from __future__ import absolute_import
34 39
35 import itertools 40 import itertools
106 111
107 def callconduit(repo, name, params): 112 def callconduit(repo, name, params):
108 """call Conduit API, params is a dict. return json.loads result, or None""" 113 """call Conduit API, params is a dict. return json.loads result, or None"""
109 host, token = readurltoken(repo) 114 host, token = readurltoken(repo)
110 url, authinfo = util.url('/'.join([host, 'api', name])).authinfo() 115 url, authinfo = util.url('/'.join([host, 'api', name])).authinfo()
111 urlopener = urlmod.opener(repo.ui, authinfo)
112 repo.ui.debug('Conduit Call: %s %s\n' % (url, params)) 116 repo.ui.debug('Conduit Call: %s %s\n' % (url, params))
113 params = params.copy() 117 params = params.copy()
114 params['api.token'] = token 118 params['api.token'] = token
115 request = util.urlreq.request(url, data=urlencodenested(params)) 119 data = urlencodenested(params)
116 body = urlopener.open(request).read() 120 curlcmd = repo.ui.config('phabricator', 'curlcmd')
121 if curlcmd:
122 sin, sout = util.popen2('%s -d @- %s' % (curlcmd, util.shellquote(url)))
123 sin.write(data)
124 sin.close()
125 body = sout.read()
126 else:
127 urlopener = urlmod.opener(repo.ui, authinfo)
128 request = util.urlreq.request(url, data=data)
129 body = urlopener.open(request).read()
117 repo.ui.debug('Conduit Response: %s\n' % body) 130 repo.ui.debug('Conduit Response: %s\n' % body)
118 parsed = json.loads(body) 131 parsed = json.loads(body)
119 if parsed.get(r'error_code'): 132 if parsed.get(r'error_code'):
120 msg = (_('Conduit Error (%s): %s') 133 msg = (_('Conduit Error (%s): %s')
121 % (parsed[r'error_code'], parsed[r'error_info'])) 134 % (parsed[r'error_code'], parsed[r'error_info']))