Patchwork D9375: ui: ensure `getpass()` returns bytes

login
register
mail settings
Submitter phabricator
Date Nov. 23, 2020, 5:26 p.m.
Message ID <differential-rev-PHID-DREV-2ajdqhglt6kekapbv6j2-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47654/
State Superseded
Headers show

Comments

phabricator - Nov. 23, 2020, 5:26 p.m.
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

Patch

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"<default response>"
     ui.writenoi18n(b'response: %s\n' % r)