Last active
January 22, 2022 22:07
-
-
Save daskol/98e76ad9b7b6e50f1eba9f8368d1170c to your computer and use it in GitHub Desktop.
Simple git credential helper in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """Simple script is a git credential helper which extracts password from | |
| password store (pass). | |
| """ | |
| from argparse import ArgumentParser, Namespace | |
| from dataclasses import dataclass | |
| from subprocess import check_output | |
| from sys import stdin, stdout | |
| from typing import Optional, TextIO | |
| parser = ArgumentParser(description=__doc__) | |
| parser.add_argument('-t', | |
| '--template', | |
| type=str, | |
| default='{username}@{host}', | |
| help='password name template') | |
| parser.add_argument('action', type=str, help='operation to execute') | |
| @dataclass | |
| class Credential: | |
| username: Optional[str] = None | |
| password: Optional[str] = None | |
| protocol: Optional[str] = None | |
| host: Optional[str] = None | |
| path: Optional[str] = None | |
| @staticmethod | |
| def read(fin: Optional[TextIO] = None) -> 'Credential': | |
| res = Credential() | |
| if not fin: | |
| fin = stdin | |
| for line in (line.strip() for line in stdin): | |
| if line == '': | |
| break | |
| if '=' not in line: | |
| raise RuntimeError('Unable to read credential from stdin.') | |
| param, value = line.split('=', 1) | |
| if param == 'username': | |
| res.username = value | |
| elif param == 'password': | |
| res.password = value | |
| elif param == 'protocol': | |
| res.protocol = value | |
| elif param == 'host': | |
| res.host = value | |
| elif param == 'path': | |
| res.path = value | |
| return res | |
| def write(self, fout: Optional[TextIO] = None): | |
| if not fout: | |
| fout = stdout | |
| def write_param(param: str): | |
| if (value := getattr(self, param, None)): | |
| fout.write(f'{param}={value}\n') | |
| write_param('username') | |
| write_param('password') | |
| write_param('protocol') | |
| write_param('host') | |
| write_param('port') | |
| def get_credential(template: str): | |
| credential = Credential.read() | |
| pass_target = template.format(host=credential.host, | |
| username=credential.username) | |
| pass_output = check_output(['pass', pass_target]) | |
| credential.password = pass_output.decode('utf-8').strip() | |
| credential.write() | |
| def main(args: Namespace): | |
| if args.action == 'get': | |
| get_credential(args.template) | |
| if __name__ == '__main__': | |
| main(parser.parse_args()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment