gomodtorbm
The snippet can be accessed without any authentication.
Authored by
Cecylia Bocovich
Tool for getting snowflake dependencies in the right format for rbm.
gomodtorbm 5.89 KiB
#!/usr/bin/env python3
# Usage: go mod graph | ./gomodtorbm
import errno
import os
import os.path
import re
import sys
STAGING_DIR = "staging"
MAIN_VERSION = "v3.1.41"
# Projects that already exist.
TERMINALS = {
"golang.org/x/crypto",
"golang.org/x/net",
"golang.org/x/sys",
"golang.org/x/text",
}
def strip_version_suffix(import_path):
return re.sub(r'/+v[0-9]+$', "", import_path)
def parse_spec(spec):
print("Parsing "+ spec)
try:
import_path, version = spec.split("@")
except ValueError:
import_path = spec
version = MAIN_VERSION
return strip_version_suffix(import_path), Version(version)
class Version:
def __init__(self, version):
self.version = version
def tuple(self):
m = re.match(r'^v([0-9]+)\.([0-9]+)\.([0-9]+)-(?:0\.)?([0-9]+)-([0-9a-fA-F]+)(\+incompatible)?$', self.version)
if m:
g = m.groups()
return int(g[0]), int(g[1]), int(g[2]), g[3], g[4]
m = re.match(r'^v([0-9]+)\.([0-9]+)\.([0-9]+)-(rc\.[0-9\.]+)-([0-9a-fA-F]+)$', self.version)
if m:
g = m.groups()
return int(g[0]), int(g[1]), int(g[2]), g[3], g[4]
m = re.match(r'^v([0-9]+)\.([0-9]+)\.([0-9]+)-(rc\.[0-9]+)$', self.version)
if m:
g = m.groups()
return int(g[0]), int(g[1]), int(g[2]), g[3], ""
m = re.match(r'^v([0-9]+)\.([0-9]+)\.([0-9]+)-([0-9]{4}\.[0-9]+\.[0-9]+)$', self.version)
if m:
g = m.groups()
return int(g[0]), int(g[1]), int(g[2]), g[3], ""
m = re.match(r'^v([0-9]+)\.([0-9]+)\.([0-9]+)(\+incompatible)?$', self.version)
if m:
g = m.groups()
return int(g[0]), int(g[1]), int(g[2]), "", ""
assert False, self.version
def __str__(self):
major, minor, micro, _, hash = self.tuple()
if hash:
if major != 0 or minor != 0 or micro != 0:
return "{} # v{}.{}.{}".format(hash, major, minor, micro)
else:
return "{}".format(hash)
else:
return "v{}.{}.{}".format(major, minor, micro)
# https://github.com/golang/proposal/blob/master/design/24301-versioned-go.md#update-timing--high-fidelity-builds
# https://github.com/golang/proposal/blob/master/design/24301-versioned-go.md#compatibility
def __lt__(self, other):
return self.tuple() < other.tuple()
PROJECT_MAP = {}
# Create a unique Project for each unique import path, and set version to the
# maximum seen.
def lookup_project(spec):
import_path, version = parse_spec(spec)
try:
project = PROJECT_MAP[import_path]
except KeyError:
project = Project(spec)
PROJECT_MAP[import_path] = project
print("Project version = ", project.version, "version = ", version)
if project.version < version:
project.version = version
return project
class Project:
def __init__(self, spec):
self.import_path, self.version = parse_spec(spec)
self.deps = set()
def add_dep(self, dep):
self.deps.add(dep)
# Cheesy heuristics to choose an rbm package name given an import path.
def project_name(self):
m = re.match(r'^gopkg\.in/([\w_-]+)\.v[0-9]+$', self.import_path)
if m:
return "go" + m.group(1)
m = re.match(r'^github\.com/(?:golang|hpcloud)/([\w_-]+)$', self.import_path)
if m:
return "go" + m.group(1)
try:
return {
"golang.org/x/crypto": "goxcrypto",
"golang.org/x/mod": "goxmod",
"golang.org/x/net": "goxnet",
"golang.org/x/sys": "goxsys",
"golang.org/x/sync": "goxsync",
"golang.org/x/term": "goxterm",
"golang.org/x/text": "goxtext",
"golang.org/x/tools": "goxtools",
"golang.org/x/xerrors": "goxxerrors",
"github.com/pkg/errors": "goerrors",
"google.golang.org/protobuf": "protobuf",
}[self.import_path]
except KeyError:
pass
if self.import_path.startswith("github.com/pion"):
return "-".join(self.import_path.split("/")[1:])
elif self.import_path.startswith("github.com/"):
return "-".join(self.import_path.split("/")[2:])
assert False, self.import_path
def output(self, f):
print("""\
# vim: filetype=yaml sw=2
version: '[% c("abbrev") %]'
git_url: https://{import_path}
git_hash: {version}
filename: '[% project %]-[% c("version") %]-[% c("var/osname") %]-[% c("var/build_id") %].tar.gz'
build: '[% c("projects/go/var/build_go_lib") %]'
var:
container:
use_container: 1
go_lib: {import_path}\
""".format(import_path=self.import_path, version=self.version), file=f)
if self.deps:
print(" go_lib_deps:", file=f)
for dep in sorted(self.deps, key=lambda x: x.project_name()):
print(" - {project_name}".format(project_name=dep.project_name()), file=f)
print("""\
input_files:
- project: container-image
- name: go
project: go\
""", file=f)
for dep in sorted(self.deps, key=lambda x: x.project_name()):
print("""\
- name: {project_name}
project: {project_name}\
""".format(project_name=dep.project_name()), file=f)
def makedirs(path):
try:
os.makedirs(path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
for line in sys.stdin:
mod_spec, req_spec = line.strip().split()
mod_project = lookup_project(mod_spec)
req_project = lookup_project(req_spec)
mod_project.add_dep(req_project)
for project in PROJECT_MAP.values():
if project.import_path in TERMINALS:
continue
project_path = os.path.join(STAGING_DIR, "projects", project.project_name())
makedirs(project_path)
with open(os.path.join(project_path, "config"), "w") as f:
print(project_path)
project.output(f)
Please register or sign in to comment