go-get for china

go-get golang.org/x/... will run perfectly in china!

go-get-for-china.py

#!/bin/env python3
# by Recolic Keghart, Nov 16

import sys
import os
import subprocess

if len(sys.argv) < 2:
    print('Error: go-get-for-china <pkg path>')
    exit(1)

gopath = os.environ['GOPATH']
if gopath == '':
    print('Error: GOPATH is empty.')
    exit(2)
print('GOPATH is ' + gopath)

def cut_last_path_segment(pathstr):
    # Example: cut('/home/recolic/tmp') => '/home/recolic/'
    #          cut('/home/recolic/tmp/') => '/home/recolic/'
    if pathstr == '' or pathstr == '/':
        raise ValueError('pathstr {} is not cutable.'.format(pathstr))
    revpath = pathstr[::-1]
    if revpath[0] == '/':
        revpath = revpath[1:]
    pos = revpath.find('/')
    if pos == -1:
        raise ValueError('pathstr {} is not cutable.'.format(pathstr))
    return revpath[pos:][::-1]

def error_line_to_pkgname(errline):
    res = errline.find(': ')
    if res == -1:
        raise ValueError('Incorrect error line passed to parser.')
    return errline[8:res]

def try_install_blocked(pkgname):
    newname = 'github.com/golang' + pkgname[12:]
    try_install_normal(newname, 'expects import')
    subprocess.run(['mkdir', '-p', gopath + '/src/' + cut_last_path_segment(pkgname)], check=True)
    subprocess.run(['cp', '-rf', gopath + '/src/' + newname, gopath + '/src/' + pkgname], check=True)
    subprocess.run(['go', 'build', pkgname], check=True)
    subprocess.run(['go', 'install', pkgname], check=True)

def try_install_normal(pkgname, ignore_error = '_fuck_chinese_gfw__fuck_fangbinxing`s_family_'):
    result = subprocess.run(["go", "get", pkgname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if result.returncode == 0:
        return
    for line in result.stderr.decode().split('\n'):
        if line == '':
            continue
        if '(https fetch:' in line:
            new_pkgname = error_line_to_pkgname(line)
            try_install(new_pkgname)
        elif ignore_error not in line:
            print('ERROR>' + line)
            raise RuntimeError('go get failed.') 

def try_install(pkgname):
    print('Installing {} ...'.format(pkgname))
    if pkgname[:12] == 'golang.org/x':
        try_install_blocked(pkgname)
    else:
        try_install_normal(pkgname)

try_install(sys.argv[1])