1+ import os
12from contextlib import AbstractContextManager
2- from typing import TYPE_CHECKING , Callable , Optional , Union
3+ from types import TracebackType
4+ from typing import TYPE_CHECKING , Callable , Optional , Type , Union
35
46from pygit2 import RemoteCallbacks as _RemoteCallbacks
57
@@ -20,14 +22,21 @@ def __init__(
2022 self ,
2123 * args ,
2224 progress : Optional [Callable [["GitProgressEvent" ], None ]] = None ,
23- ** kwargs
25+ ** kwargs ,
2426 ):
2527 super ().__init__ (* args , ** kwargs )
2628 self .progress = GitProgressReporter (progress ) if progress else None
2729 self ._store_credentials : Optional ["Credential" ] = None
30+ self ._tried_credentials = False
2831
29- def __exit__ (self , * args , ** kwargs ):
30- self ._approve_credentials ()
32+ def __exit__ (
33+ self ,
34+ exc_type : Optional [Type [BaseException ]],
35+ exc_value : Optional [BaseException ],
36+ traceback : Optional [TracebackType ],
37+ ):
38+ if exc_type is None :
39+ self ._approve_credentials ()
3140
3241 def sideband_progress (self , string : str ):
3342 if self .progress is not None :
@@ -36,16 +45,37 @@ def sideband_progress(self, string: str):
3645 def credentials (
3746 self , url : str , username_from_url : Optional [str ], allowed_types : int
3847 ) -> "_Pygit2Credential" :
39- from pygit2 import Passthrough
48+ from getpass import getpass
49+
50+ from pygit2 import GitError , Passthrough
4051 from pygit2 .credentials import GIT_CREDENTIAL_USERPASS_PLAINTEXT , UserPass
4152
53+ if self ._tried_credentials :
54+ raise GitError (f"authentication failed for '{ url } '" )
55+ self ._tried_credentials = True
56+
4257 if allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT :
4358 try :
44- creds = Credential (username = username_from_url , url = url ).fill ()
45- self ._store_credentials = creds
59+ if self ._store_credentials :
60+ creds = self ._store_credentials
61+ else :
62+ Credential (username = username_from_url , url = url ).fill ()
63+ self ._store_credentials = creds
4664 return UserPass (creds .username , creds .password )
4765 except CredentialNotFoundError :
4866 pass
67+
68+ if os .environ .get ("GIT_TERMINAL_PROMPT" ) != "0" :
69+ try :
70+ if username_from_url :
71+ username = username_from_url
72+ else :
73+ username = input (f"Username for '{ url } ': " )
74+ password = getpass (f"Password for '{ url } ': " )
75+ if username and password :
76+ return UserPass (username , password )
77+ except KeyboardInterrupt :
78+ pass
4979 raise Passthrough
5080
5181 def _approve_credentials (self ):
0 commit comments