Skip to content

Instantly share code, notes, and snippets.

@edudobay
Created May 10, 2019 16:25
Show Gist options
  • Save edudobay/d00d6bf00352cb39399a0bf29a99e668 to your computer and use it in GitHub Desktop.
Save edudobay/d00d6bf00352cb39399a0bf29a99e668 to your computer and use it in GitHub Desktop.
Script to open GitLab project URLs in your browser
#!/usr/bin/env python3
import argparse
import sys
import subprocess
import re
import urllib.parse
def git(args):
proc = subprocess.run(
['git'] + args,
check=True,
capture_output=True,
encoding=sys.getdefaultencoding(),
)
return proc.stdout
def browse(url):
proc = subprocess.run(
[get_browser(), url],
check=True,
)
def get_browser():
if sys.platform == 'linux':
return 'xdg-open'
return 'open'
def get_remote_url(remote_name):
stdout = git(['remote', 'get-url', remote_name])
remote_url = stdout.strip()
match = re.match('^git@gitlab.com:(.+?)(\.git)?$', remote_url)
if match is None:
return None
repo = match.group(1)
return f'https://gitlab.com/{repo}'
def get_current_branch():
stdout = git(['rev-parse', '--abbrev-ref', 'HEAD'])
branch_name = stdout.strip()
return branch_name
class Commands:
@staticmethod
def create_merge_request(args):
repo_http = get_remote_url(args.remote)
url = f'{repo_http}/merge_requests/new'
source_branch = args.source_branch or get_current_branch()
target_branch = args.target_branch
params = {
'merge_request[source_branch]': source_branch,
'merge_request[target_branch]': target_branch,
}
params = dict(**{k: v for k, v in params.items() if v is not None})
full_url = '{url}?{query}'.format(
url=url,
query=urllib.parse.urlencode(params),
)
print(full_url)
browse(full_url)
@staticmethod
def view_any(args):
repo_http = get_remote_url(args.remote)
url = repo_http + '/' + args.page.lstrip('/')
print(url)
browse(url)
@staticmethod
def view_branches(args):
repo_http = get_remote_url(args.remote)
url = repo_http + '/branches'
print(url)
browse(url)
def main(args):
handler = getattr(Commands, args.command)
handler(args)
def cli_main():
parser = argparse.ArgumentParser(
description='Open GitLab pages on your web browser'
)
parser.add_argument(
'-r',
'--remote',
default='origin',
help='set the remote that should be used (defaults to origin)',
)
# TODO: default to first remote (as returned by `git remote`) if `origin`
# does not exist or is not a GitLab repo
###
subparsers = parser.add_subparsers(
help='sub-command help',
)
###
go_parser = subparsers.add_parser(
'go',
help='Open any repository page given by its path',
)
go_parser.set_defaults(command='view_any')
go_parser.add_argument(
'page', nargs='?', default='',
help='Specify a custom plain path below the repository URL'
)
###
repo_parser = subparsers.add_parser(
'repo',
aliases=['browse'],
help='Open the main repository page',
)
repo_parser.set_defaults(command='view_any', page='')
###
branches_parser = subparsers.add_parser(
'branches',
help='Open the repository branches page',
)
branches_parser.set_defaults(command='view_branches')
###
pr_parser = subparsers.add_parser(
'pr',
aliases=['mr', 'pull', 'merge'],
help='Create a merge request',
)
pr_parser.set_defaults(command='create_merge_request')
pr_parser.add_argument(
'-t',
'--target',
dest='target_branch',
help='set the target branch (defaults to master)',
)
pr_parser.add_argument(
'source_branch',
nargs='?',
help='set the source branch (defaults to currently checked out branch)',
)
###
args = parser.parse_args()
if not 'command' in args:
parser.print_usage()
sys.exit(1)
main(args)
if __name__ == '__main__':
cli_main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment