Blame go-mods-to-bundled-provides.py

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