From patchwork Mon Nov 23 17:26:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: D9375: ui: ensure `getpass()` returns bytes From: phabricator X-Patchwork-Id: 47654 Message-Id: To: Phabricator Cc: mercurial-devel@mercurial-scm.org Date: Mon, 23 Nov 2020 17:26:00 +0000 mharbison72 created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Previously, this could return either bytes or str. I'm not sure which direction we should go in, but since the input is bytes, I guess bytes makes sense as output. `debuguigetpass` crashed because it assumed bytes would be returned, `sslcontext.load_cert_chain()` is happy with bytes or str if the type info in PyCharm is correct, and `smtplib.SMTP.login()` wants str. I couldn't figure out how to test this, because the test stalls for input with `echo test | hg debuguigetpass --config ui.interactive=1`, likely because it drains stdin before prompting. The custom input reading with `ui.nontty=1` does not. I'm also a bit concerned with all of this encoding/decoding. The existing code in the mail module uses `encoding.strfromlocal()`, but the username and password are ascii encoded/decoded in `mercurial.url.passwordmgr.find_user_password()` with `pycompat.{str,bytes}url()`. I'm not sure if this inconsistency could cause subtle compatability issues. REPOSITORY rHG Mercurial BRANCH stable REVISION DETAIL https://phab.mercurial-scm.org/D9375 AFFECTED FILES mercurial/debugcommands.py mercurial/mail.py mercurial/ui.py CHANGE DETAILS To: mharbison72, #hg-reviewers Cc: mercurial-patches, mercurial-devel diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -1735,7 +1735,7 @@ raise EOFError return l.rstrip(b'\n') else: - return getpass.getpass('') + return encoding.strtolocal(getpass.getpass('')) except EOFError: raise error.ResponseExpected() diff --git a/mercurial/mail.py b/mercurial/mail.py --- a/mercurial/mail.py +++ b/mercurial/mail.py @@ -157,6 +157,8 @@ password = encoding.strfromlocal(password) else: password = ui.getpass() + if password is not None: + password = encoding.strfromlocal(password) if username and password: ui.note(_(b'(authenticating to mail server as %s)\n') % username) username = encoding.strfromlocal(username) diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -3787,6 +3787,10 @@ def debuguigetpass(ui, prompt=b''): """show prompt to type password""" r = ui.getpass(prompt) + if r is not None: + r = encoding.strtolocal(r) + else: + r = b"" ui.writenoi18n(b'response: %s\n' % r)