d551c56
#!/bin/python3
d551c56
d551c56
'''
d551c56
    Tiny dumb script that generates virtual bundled `Provides` from a repo that
d551c56
    uses go modules and vendoring.
d551c56
'''
d551c56
d551c56
import sys
d551c56
import re
d551c56
d551c56
d551c56
def main():
d551c56
    repos = get_repos_from_go_mod()
d551c56
    print_provides_from_modules_txt(repos)
d551c56
d551c56
d551c56
def get_repos_from_go_mod():
d551c56
    repos = {}
d551c56
    in_reqs = False
d551c56
    for line in open('go.mod'):
d551c56
        line = line.strip()
d551c56
        if in_reqs and line.startswith(')'):
d551c56
            break
d551c56
        if not in_reqs:
d551c56
            if line.startswith('require ('):
d551c56
                in_reqs = True
d551c56
            continue
d551c56
        req = line.split()
d551c56
d551c56
        repo = req[0]
d551c56
        tag = req[1]
d551c56
d551c56
        repos[repo] = go_mod_tag_to_rpm_provides_version(tag)
d551c56
d551c56
    return repos
d551c56
d551c56
d551c56
def go_mod_tag_to_rpm_provides_version(tag):
d551c56
d551c56
    # go.mod tags are either exact git tags, or may be "pseudo-versions". We
d551c56
    # want to convert these tags to something resembling a version string that
d551c56
    # RPM won't fail on. For more information, see
d551c56
    # https://golang.org/cmd/go/#hdr-Pseudo_versions and following sections.
d551c56
d551c56
    # trim off any +incompatible
d551c56
    if tag.endswith('+incompatible'):
d551c56
        tag = tag[:-len('+incompatible')]
d551c56
d551c56
    # git tags are normally of the form v$VERSION
d551c56
    if tag.startswith('v'):
d551c56
        tag = tag[1:]
d551c56
d551c56
    # is this a pseudo-version? e.g. v0.0.0-20181031085051-9002847aa142
d551c56
    m = re.match("(.*)-([0-9]{14})-([a-f0-9]{12})", tag)
d551c56
    if m:
d551c56
        # rpm doesn't like multiple dashes in the version, so just merge the
d551c56
        # timestamp and the commit checksum into the "release" field
d551c56
        tag = f"{m.group(1)}-{m.group(2)}.git{m.group(3)}"
d551c56
d551c56
    return tag
d551c56
d551c56
d551c56
def print_provides_from_modules_txt(repos):
d551c56
d551c56
    for line in open('vendor/modules.txt'):
d551c56
        if line.startswith('#'):
d551c56
            continue
d551c56
        gopkg = line.strip()
d551c56
        repo = lookup_repo_for_pkg(repos, gopkg)
d551c56
        if not repo:
d551c56
            # must be a pkg for tests only; ignore
d551c56
            continue
d551c56
        tag = repos[repo]
d551c56
        print(f"Provides: bundled(golang({gopkg})) = {tag}")
d551c56
d551c56
d551c56
def lookup_repo_for_pkg(repos, gopkg):
d551c56
    for repo in repos:
d551c56
        if gopkg.startswith(repo):
d551c56
            return repo
d551c56
d551c56
d551c56
if __name__ == '__main__':
d551c56
    sys.exit(main())