| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| """Contains utilities to manage Git credentials.""" |
| import re |
| import subprocess |
| from typing import List, Optional |
|
|
| from ..constants import ENDPOINT |
| from ._subprocess import run_interactive_subprocess, run_subprocess |
|
|
|
|
| GIT_CREDENTIAL_REGEX = re.compile( |
| r""" |
| ^\s* # start of line |
| credential\.helper # credential.helper value |
| \s*=\s* # separator |
| (\w+) # the helper name (group 1) |
| (\s|$) # whitespace or end of line |
| """, |
| flags=re.MULTILINE | re.IGNORECASE | re.VERBOSE, |
| ) |
|
|
|
|
| def list_credential_helpers(folder: Optional[str] = None) -> List[str]: |
| """Return the list of git credential helpers configured. |
| |
| See https://git-scm.com/docs/gitcredentials. |
| |
| Credentials are saved in all configured helpers (store, cache, macOS keychain,...). |
| Calls "`git credential approve`" internally. See https://git-scm.com/docs/git-credential. |
| |
| Args: |
| folder (`str`, *optional*): |
| The folder in which to check the configured helpers. |
| """ |
| try: |
| output = run_subprocess("git config --list", folder=folder).stdout |
| parsed = _parse_credential_output(output) |
| return parsed |
| except subprocess.CalledProcessError as exc: |
| raise EnvironmentError(exc.stderr) |
|
|
|
|
| def set_git_credential(token: str, username: str = "hf_user", folder: Optional[str] = None) -> None: |
| """Save a username/token pair in git credential for HF Hub registry. |
| |
| Credentials are saved in all configured helpers (store, cache, macOS keychain,...). |
| Calls "`git credential approve`" internally. See https://git-scm.com/docs/git-credential. |
| |
| Args: |
| username (`str`, defaults to `"hf_user"`): |
| A git username. Defaults to `"hf_user"`, the default user used in the Hub. |
| token (`str`, defaults to `"hf_user"`): |
| A git password. In practice, the User Access Token for the Hub. |
| See https://huggingface.co/settings/tokens. |
| folder (`str`, *optional*): |
| The folder in which to check the configured helpers. |
| """ |
| with run_interactive_subprocess("git credential approve", folder=folder) as ( |
| stdin, |
| _, |
| ): |
| stdin.write(f"url={ENDPOINT}\nusername={username.lower()}\npassword={token}\n\n") |
| stdin.flush() |
|
|
|
|
| def unset_git_credential(username: str = "hf_user", folder: Optional[str] = None) -> None: |
| """Erase credentials from git credential for HF Hub registry. |
| |
| Credentials are erased from the configured helpers (store, cache, macOS |
| keychain,...), if any. If `username` is not provided, any credential configured for |
| HF Hub endpoint is erased. |
| Calls "`git credential erase`" internally. See https://git-scm.com/docs/git-credential. |
| |
| Args: |
| username (`str`, defaults to `"hf_user"`): |
| A git username. Defaults to `"hf_user"`, the default user used in the Hub. |
| folder (`str`, *optional*): |
| The folder in which to check the configured helpers. |
| """ |
| with run_interactive_subprocess("git credential reject", folder=folder) as ( |
| stdin, |
| _, |
| ): |
| standard_input = f"url={ENDPOINT}\n" |
| if username is not None: |
| standard_input += f"username={username.lower()}\n" |
| standard_input += "\n" |
|
|
| stdin.write(standard_input) |
| stdin.flush() |
|
|
|
|
| def _parse_credential_output(output: str) -> List[str]: |
| """Parse the output of `git credential fill` to extract the password. |
| |
| Args: |
| output (`str`): |
| The output of `git credential fill`. |
| """ |
| |
| |
| |
| return sorted( |
| set( |
| match[0] for match in GIT_CREDENTIAL_REGEX.findall(output) |
| ) |
| ) |
|
|