git-me/git-me.py

166 lines
5.5 KiB
Python
Executable File

#!/usr/bin/env python3
import os, argparse, sys, csv, subprocess
def eprint(*all):
print(*all, file=sys.stderr)
STORAGE_LOC = os.environ['GIT_ME_STORE'] if 'GIT_ME_STORE' in os.environ else os.environ['HOME'] + '/.config/git-me'
eprint("git-me identity store: " + STORAGE_LOC)
STCOL_LEN = 3
STCOL_SLUG = 0
STCOL_NAME = 1
STCOL_EMAIL = 2
def add(args):
slug = args.slug.lower()
name = args.name
email = args.email
try:
with open(STORAGE_LOC, 'r') as fstore:
tsvin = csv.reader(fstore, delimiter='\t')
for row in tsvin:
if len(row) < STCOL_LEN:
continue
if row[STCOL_SLUG].lower() == slug:
eprint("An identity with that slug already exists!")
eprint(f" Slug: {row[STCOL_SLUG]}")
eprint(f" Name: {row[STCOL_NAME]}")
eprint(f" E-mail: {row[STCOL_EMAIL]}")
return False
except FileNotFoundError:
pass
# now add it
with open(STORAGE_LOC, 'a+') as fstore:
fstore.write(f"\n{slug}\t{name}\t{email}\n")
return True
def list_idents(args):
print("# Slug\t\tName\t\tE-mail Address")
with open(STORAGE_LOC, 'r') as fstore:
tsvin = csv.reader(fstore, delimiter='\t')
for row in tsvin:
if len(row) < STCOL_LEN:
continue
print(f"{row[STCOL_SLUG]}\t\t{row[STCOL_NAME]}\t\t{row[STCOL_EMAIL]}")
return True
def assert_hook(args):
result_name = subprocess.run(['git', 'config', '--local', '--get', 'user.name'], stdout=subprocess.PIPE)
so_name = result_name.stdout.decode().strip()
result_email = subprocess.run(['git', 'config', '--local', '--get', 'user.email'], stdout=subprocess.PIPE)
so_email = result_email.stdout.decode().strip()
if result_email.returncode + result_name.returncode > 0:
if result_name.returncode > 0:
eprint("git-me: No user.name specified!")
else:
eprint(f"git-me: user.name OK = {so_name}")
if result_email.returncode > 0:
eprint("git-me: No user.email specified!")
else:
eprint(f"git-me: user.email OK = {so_email}")
eprint("git-me: Either specify a config manually or use `git me use <id>`.")
return False
else:
eprint(f"git-me: OK. (user.name = {so_name}, user.email = {so_email})")
return True
def remove(args):
slug = args.idslug
os.rename(STORAGE_LOC, STORAGE_LOC + "~tmp")
with open(STORAGE_LOC + "~tmp", 'r') as tsvin, open(STORAGE_LOC, 'w') as tsvout:
tsvin = csv.reader(tsvin, delimiter='\t')
tsvout = csv.writer(tsvout, delimiter='\t')
for row in tsvin:
if len(row) < STCOL_LEN:
continue
if row[STCOL_SLUG].lower() == slug:
# delete; ignore
pass
else:
tsvout.writerow(row)
os.unlink(STORAGE_LOC + "~tmp")
return True
def switch_identity(args):
slug = args.idslug
with open(STORAGE_LOC, 'r') as fstore:
tsvin = csv.reader(fstore, delimiter='\t')
for row in tsvin:
if len(row) < STCOL_LEN:
continue
if row[STCOL_SLUG].lower() == slug:
proc_name = subprocess.run(["git", "config", "--local", "user.name", row[STCOL_NAME]])
if proc_name.returncode != 0:
eprint("git-me: Failed to set user.name! (non-zero exit code. Are you in a git repo?)")
return False
else:
proc_email = subprocess.run(["git", "config", "--local", "user.email", row[STCOL_EMAIL]])
if proc_name.returncode != 0:
eprint("git-me: Failed to set user.email! (non-zero exit code.)")
return False
return True
else:
eprint(f"git-me: Unable to find identity with {slug}")
return False
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Manages repository identities. Environment variable GIT_ME_STORE can be used to override location of identity store.',
)
subparser = parser.add_subparsers(help='sub-command help', dest='cmd')
subparser.required = True
parser_assert = subparser.add_parser('assert', aliases=['check', 'hook', 'ck'])
parser_assert.set_defaults(func=assert_hook)
parser_add = subparser.add_parser('add', aliases=['mk'])
parser_add.add_argument('slug', type=str, help='A short, easy-to-type code to represent this id')
parser_add.add_argument('name', type=str, help='Your display name')
parser_add.add_argument('email', type=str, help='Your e-mail address')
parser_add.set_defaults(func=add)
parser_list = subparser.add_parser('list', aliases=['ls'])
parser_list.set_defaults(func=list_idents)
parser_remove = subparser.add_parser('remove', aliases=['rm'])
parser_remove.add_argument('idslug', type=str, help='The slug of the identity to remove.')
parser_remove.set_defaults(func=remove)
parser_switch = subparser.add_parser('use', aliases=['switch', 'choose', 'enable'])
parser_switch.add_argument('idslug', type=str, help='The slug of the identity to enable.')
parser_switch.set_defaults(func=switch_identity)
args = parser.parse_args(sys.argv[1:])
if 'func' in args:
if args.func(args):
exit(0)
else:
exit(1)
else:
print("git-me: Please specify a command!", file=sys.stderr)
exit(2)