sshaskpass: use a standalone script

Summary:
Before this patch, sshaskpass will set SSH_ASKPASS to itself, aka. `__file__`.
This won't work if sshaskpass.py gets installed by setup.py because setup.py
will remove its `+x` bit.

Test Plan:
Run `chg push -r . ssh://root@localhost//tmp/foo -f --allow-ano` and make
sure ssh password prompt works.

Reviewers: #mercurial, ttung, rmcelroy

Reviewed By: rmcelroy

Subscribers: mjpieters

Differential Revision: https://phabricator.intern.facebook.com/D3705657

Signature: t1:3705657:1471008122:9cfa3adf078e4bbe8f6b6ba05d1fb6be513d3e71
This commit is contained in:
Jun Wu 2016-08-11 21:42:54 +01:00
parent 6015a95c00
commit d4366acbd5

21
hgext3rd/sshaskpass.py Executable file → Normal file
View File

@ -17,9 +17,8 @@ When ssh is unable to use /dev/tty, it will try to run SSH_ASKPASS if DISPLAY
is set, which is usually a GUI program. Here we set it to a special program
receiving fds from a simple unix socket server.
This file is both a mercurial extension to start that tty server and an
executable serving as the ssh-askpass script. Therefore its mode should
have the +x (executable) bit.
This file is both a mercurial extension to start that tty server and a
standalone ssh-askpass script.
"""
import contextlib
@ -153,12 +152,15 @@ def _validaterepo(orig, self, sshcmd, args, remotecmd):
if not _isttyserverneeded():
return orig(self, sshcmd, args, remotecmd)
pid = sockpath = None
pid = sockpath = scriptpath = None
with _silentexception(terminate=False):
pid, sockpath = _startttyserver()
scriptpath = os.path.abspath(__file__)
if scriptpath[-4:].lower() in ('.pyc', '.pyo'):
scriptpath = scriptpath[:-1]
scriptpath = sockpath + '.sh'
with open(scriptpath, 'w') as f:
f.write('#!/bin/bash\nexec %s %s "$@"'
% (util.shellquote(sys.executable),
util.shellquote(__file__)))
os.chmod(scriptpath, 0o755)
parentpids = [os.getpid(), pid]
env = {
# ssh will not use SSH_ASKPASS if DISPLAY is not set
@ -175,8 +177,9 @@ def _validaterepo(orig, self, sshcmd, args, remotecmd):
finally:
if pid:
_killprocess(pid)
if sockpath and os.path.exists(sockpath):
util.unlinkpath(sockpath, ignoremissing=True)
for path in [scriptpath, sockpath]:
if path and os.path.exists(path):
util.unlinkpath(path, ignoremissing=True)
def uisetup(ui):
# _validaterepo runs ssh and needs to be wrapped