import re
import json
import base64
import codecs
import os.path
import asyncio
import subprocess


_PREFIX = 'docker-credential-'


def read_config():
    path = os.path.expanduser('~/.docker/config.json')
    if not os.path.exists(path):
        return {}
    with codecs.open(path, encoding='utf-8') as f:
        json_data = f.read()
    return json.loads(json_data)


async def _read_creds(creds_store, server):
    if not re.match(r'^\w+$', creds_store, re.ASCII):
        raise ValueError('Invalid credsStore: {!r}'.format(creds_store))

    proc = await asyncio.create_subprocess_exec(
        _PREFIX + creds_store, 'get',
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    stdout, stderr = await proc.communicate(server.encode('ascii'))
    if proc.returncode != 0:
        return None
    else:
        data = json.loads(stdout)
        return {
            'Username': data['Username'],
            'Password': data['Secret'],
            'ServerAddress': server,
        }


def _decode_auth(auth_data, server):
    auth_data_decoded = base64.b64decode(auth_data).decode('utf-8')
    username, _, password = auth_data_decoded.partition(':')
    return {
        'Username': username,
        'Password': password,
        'ServerAddress': server,
    }


async def resolve_auth(config, server):
    config_auths = config.get('auths')
    if config_auths is None:
        return None

    server_auth = config_auths.get(server)
    if server_auth is not None:
        auth_data = server_auth.get('auth')
        if auth_data is not None:
            return _decode_auth(auth_data, server)

    creds_store = config.get('credsStore')
    if creds_store is not None:
        return await _read_creds(creds_store, server)

    return None


def server_name(image_name):
    registry, _, name = image_name.partition('/')
    if not name:
        return 'docker.io'
    else:
        return registry


def encode_header(auth):
    json_data = json.dumps(auth)
    return base64.urlsafe_b64encode(json_data.encode('ascii'))

[((19, 11, 19, 32), 'json.loads', 'json.loads', ({(19, 22, 19, 31): 'json_data'}, {}), '(json_data)', False, 'import json\n'), ((81, 16, 81, 32), 'json.dumps', 'json.dumps', ({(81, 27, 81, 31): 'auth'}, {}), '(auth)', False, 'import json\n'), ((17, 9, 17, 44), 'codecs.open', 'codecs.open', (), '', False, 'import codecs\n'), ((23, 11, 23, 52), 're.match', 're.match', ({(23, 20, 23, 28): '"""^\\\\w+$"""', (23, 30, 23, 41): 'creds_store', (23, 43, 23, 51): 're.ASCII'}, {}), "('^\\\\w+$', creds_store, re.ASCII)", False, 'import re\n'), ((26, 17, 31, 5), 'asyncio.create_subprocess_exec', 'asyncio.create_subprocess_exec', (), '', False, 'import asyncio\n'), ((36, 15, 36, 33), 'json.loads', 'json.loads', ({(36, 26, 36, 32): 'stdout'}, {}), '(stdout)', False, 'import json\n'), ((45, 24, 45, 51), 'base64.b64decode', 'base64.b64decode', ({(45, 41, 45, 50): 'auth_data'}, {}), '(auth_data)', False, 'import base64\n')]