#!/usr/bin/env python3 import argparse import re import subprocess REMOTE_TYPES = [ { # github "match": re.compile(r'git@github.com:(?P<username>[\w\.-]+)/(?P<project>[\w\.-]+).git'), "format-branch": lambda g, b: f"https://github.com/{g['username']}/{g['project']}/tree/{b}/", "format-commit": lambda g, c: f"https://github.com/{g['username']}/{g['project']}/commit/{c}/", }, { # gitea "match": re.compile(r'(?P<gituser>[\w\.-]+)@(?P<host>[\w\.-]+):(?P<username>[\w\.-]+)/(?P<project>[\w\.-]+).git'), "format-branch": lambda g, b: f"https://{g['host']}/{g['username']}/{g['project']}/src/branch/{b}/", "format-commit": lambda g, c: f"https://{g['host']}/{g['username']}/{g['project']}/commit/{c}/", }, ] def get_remote_branch(): s = subprocess.run(["git", "status", "--porcelain", "-uno", "-b", "--no-ahead-behind"], capture_output=True, text=True) git_status_branch_info = s.stdout.splitlines()[0][3:].split()[0] branches = git_status_branch_info.split("...") if len(branches) != 2: raise Exception("no branch name found") local_branch, remote_branch = branches remote, branch = remote_branch.split("/") return { "remote": remote, "branch": branch, } def get_remote_url(remote): s = subprocess.run(["git", "remote", "get-url", remote], capture_output=True, text=True) remote_url = s.stdout.strip() return remote_url def get_last_commit(): s = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True) commit = s.stdout.strip() return commit def main(): parser = argparse.ArgumentParser( prog='git-show-link', ) parser.add_argument("--branch", dest="display_branch", action='store_true', help="Display link to branch, instead to commit") args = parser.parse_args() r = get_remote_branch() remote_url = get_remote_url(r["remote"]) for remote_type in REMOTE_TYPES: m = remote_type["match"].match(remote_url) if m is None: continue g = m.groupdict() if args.display_branch: print(remote_type["format-branch"](g, r["branch"])) else: commit = get_last_commit() print(remote_type["format-commit"](g, commit)) break if __name__ == "__main__": main()